/*
//
// ADOBE SYSTEMS INCORPORATED
// Copyright (C) 2000-2003 Adobe Systems Incorporated
// All rights reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file
// in accordance with the terms of the Adobe license agreement
// accompanying it. If you have received this file from a source other
// than Adobe, then your use, modification, or distribution of it
// requires the prior written permission of Adobe.
//
*/
/*
//
// Description:
// This file contains several externally visible functions:
// _ Get a PDF file's base URI (if any)
// - Enumerate weblinks in a PDF file
// - Get a URI from a PDAction
// - Set a PDAction's URI
// - Get an annotation's PDAction
//
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "
CosCalls.h"
#include "
CorCalls.h"
#include "
ASCalls.h"
#include "
PDCalls.h"
#include "NSelExpT.h"
#include "extrURI.h"
#include "
PIExcept.h"
/* Line endings - lineend is defined so that it is correct for Mac, Win, UNIX */
#ifdef WIN_ENV
#define lineend "\r\n"
#elif MAC_ENV
#define lineend "\r"
#else
#define lineend "\n"
#endif
#define MAX_URI_SIZE 2048
/* Static Function Declarations */
static char *CosCStringValue( char *cBuf,
CosObj coValue, int nLen);
static
ASBool CosObjIsValid(
CosObj co,
CosType ct);
/**************************************************************************
Function name:
PDDocGetBaseURI
Description:
Gets the base URL, if any, from a specified PDF file.
Input parameters:
pdd - The document whose base URI is to be obtained
cBase - Buffer into which base URI will be written
nLen - Length of buffer (in bytes)into which URI is written
Output parameters:
cBase - Buffer containing base URI
Return value:
true if the document has a base URI
false if the document has no base URL, if cBase is NULL, or nLen is 0.
****************************************************************************/
ASBool PDDocGetBaseURI(
PDDoc pdd, char *cBase,
Uns16 nLen)
{
CosObj coDict, coBase;
/* Get the catalog. */
coDict =
CosDocGetRoot(
PDDocGetCosDoc(pdd));
if (!CosObjIsValid(coDict,
CosDict))
return false ;
/* Get the URI dictionary. */
coDict =
CosDictGet(coDict,
ASAtomFromString( "URI" ));
if (!CosObjIsValid(coDict,
CosDict))
return false ;
/* Get the Base key. */
coBase =
CosDictGet(coDict,
ASAtomFromString( "Base" ));
if (!CosObjIsValid(coBase,
CosString))
return false ;
CosCStringValue(cBase, coBase, nLen);
return true ;
}
/**************************************************************************
Function name:
PDDocEnumURILinks
Description:
Enumerates weblinks on a specific page, or on all pages, of
a specified PDF file.
Input parameters:
pdd - The document whose whose weblinks are to be enumerated
nPageNum - Page number for which to enumerate wseblinks. The first page in
a PDF file has page number zero. Pass PDAllPages to enumerate weblinks
on all pages.
linkProc - User-supplied procedure that is called for each weblink found
vClientData - User-supplied data that is passed to linkProc each time that
it is called.
Output parameters:
None
Return value:
None
****************************************************************************/
void PDDocEnumURILinks(
PDDoc pdd,
Int32 nPageNum,
PDURILinkEnumProc linkProc, void *vClientData)
{
Int32 nNumPages, nStartPage, nEndPage;
Int32 nError;
register
Int32 i;
if (linkProc ==
NULL) {
ASRaise(
GenError(genErrBadParm));
}
nError = 0;
DURING
nNumPages =
PDDocGetNumPages(pdd);
nStartPage = 0;
nEndPage = nNumPages;
/* Determine the start and end page numbers. */
if (nPageNum !=
PDAllPages)
{
if (nPageNum >= nNumPages || nPageNum < 0)
ASRaise(
GenError(genErrBadParm));
nStartPage = nPageNum;
nEndPage = nStartPage + 1;
}
/* Loop over each requested page. */
for (i = nStartPage; i < nEndPage; i++){
PDPage pdp =
PDDocAcquirePage(pdd, i);
Int32 nNumAnnots;
register
Int32 j;
char cURI[MAX_URI_SIZE];
PDAction pdac;
fprintf( stdout, "." );
fflush(stdout);
/* Loop over all annotations on the page. */
nNumAnnots =
PDPageGetNumAnnots(pdp);
for (j = 0; j < nNumAnnots; j++){
/* Get the annotation and check to see if it's a link. */
PDAnnot pdan;
pdan =
PDPageGetAnnot(pdp, j);
if (!
PDAnnotIsValid(pdan) ||
PDAnnotGetSubtype(pdan) !=
ASAtomFromString( "Link" ))
continue ;
/* Try to get the action dictionary. */
pdac = PDAnnotGetAction(pdan);
if (PDActionGetURI(pdac, cURI, sizeof (cURI))){
if (!linkProc(pdp, pdan, cURI, vClientData)){
/* linkProc has asked us to stop. */
PDPageRelease(pdp);
E_RTRN_VOID;
}
}
}
PDPageRelease(pdp);
}
HANDLER
nError =
ERRORCODE;
END_HANDLER
if (nError)
ASRaise(nError);
}
/**************************************************************************
Function name:
PDActionGetURI
Description:
Gets the URI from a specified action.
Input parameters:
pdac - The action whose URI is to be obtained
cURI - buffer into which the URI is to be written
nLen - Maximum number of bytes that cURI can hold
Output parameters:
cURI - The action's URI. If the URI will not fit, the URI is truncated
Return value:
true if the URI was successfully obtained, false otherwise
****************************************************************************/
ASBool PDActionGetURI(
PDAction pdac, char *cURI,
Uns16 nLen)
{
CosObj coAction, coURI;
PDFileSpec filespec;
char buf[MAX_URI_SIZE + 10];
/* Make sure we have a valid action. */
if (!
PDActionIsValid(pdac))
return false ;
/* Make sure that the subtype is URI. */
if (
PDActionGetSubtype(pdac) ==
ASAtomFromString( "URI" )){
coAction =
PDActionGetCosObj(pdac);
/* Get the value of the URI key.*/
coURI =
CosDictGet(coAction,
ASAtomFromString( "URI" ));
if (!CosObjIsValid(coURI,
CosString))
return false ;
CosCStringValue(cURI, coURI, nLen);
if (!strstr(cURI, "http://" )){
strcpy(buf, "http://" );
strcat(buf, cURI);
strcpy(cURI, buf);
}
return true ;
}
if (
PDActionGetSubtype(pdac) ==
ASAtomFromString( "GoToR" ) ||
PDActionGetSubtype(pdac) ==
ASAtomFromString( "Launch" )){
filespec =
PDActionGetFileSpec(pdac);
PDFileSpecGetDIPath(filespec, cURI,MAX_URI_SIZE);
strcpy(buf,
ASAtomGetString(
PDActionGetSubtype(pdac)));
strcat(buf, ": " );
strcat(buf, cURI);
strcpy(cURI, buf);
return true ;
}
return false ;
}
/**************************************************************************
Function name:
PDAnnotGetAction
Description:
Gets the action from a specified PDAnnot.
Input parameters:
pdan - The PDAnnot whose action is to be obtained
Output parameters:
None
Return value:
The action associated with the specified PDAnnot. Returns a NULL Cos object
if the PDAnnot does not have an action (i.e., does not have an "A" key)
****************************************************************************/
PDAction PDAnnotGetAction(
PDAnnot pdan)
{
CosObj coAction;
CosObj coAnnot =
PDAnnotGetCosObj(pdan);
CosObj coNull =
CosNewNull();
if (!CosObjIsValid(coAnnot,
CosDict))
return (*(
PDAction *) &(coNull));
/* Get the Action dict. */
coAction =
CosDictGet(coAnnot,
ASAtomFromString( "Action" ));
if (
CosObjGetType(coAction) !=
CosDict) {
coAction =
CosDictGet(coAnnot,
ASAtomFromString( "A" ));
if (
CosObjGetType(coAction) !=
CosDict)
return (*(
PDAction *) &(coNull));
}
return
PDActionFromCosObj(coAction);
}
/* ---- Static Function Definitions ---- */
/**************************************************************************
Function name:
CosObjIsValid
Description:
Tests whether or not a specified COS Object is valid. Note that this test
is minimal; the object is valid if it is not a NULL object, and if it is
of the specified type.
Input parameters:
obj - The COS object whose validity is to be tested
objType - The object type (boolean, string, dictionary...) that obj is
supposed to be
Output parameters:
None
Return value:
true if the object is valid, falce otherwise
****************************************************************************/
static
ASBool CosObjIsValid(
CosObj obj,
CosType objType)
{
return !((
CosObjGetType(obj) ==
CosNull) ||
CosObjGetType(obj) != objType);
}
/**************************************************************************
Function name:
CosCStringValue
Description:
Gets the value of a specified COS string as a C-style string.
Input parameters:
cBuf - Buffer into which the COS string's value is to be placed
objType - The object type (boolean, string, dictionary...) that obj is
supposed to be
nLen - Maximum number of bytes that cBuf can hold
Output parameters:
cBuf - The value of the COS string. If the string's value is longer than
nLen, the string is truncated to fit into cBuf.
Return value:
The value of the COS string.
****************************************************************************/
static char *CosCStringValue( char *cBuf,
CosObj coValue, int nLen)
{
Int32 nCount;
char *c =
CosStringValue(coValue, &nCount);
if (nCount > nLen - 1)
nCount = nLen - 1;
while (nCount--)
*cBuf++ = *c++;
*cBuf = '\0' ;
return cBuf;
}
/**************************************************************************
Function name:
getURI
Description:
Extracts the URL from the first weblink annotation on the first page of a
specified document. Prints the URL to a specified file.
Input parameters:
docP - PDDoc from which URL is to be extracted
outf - file into which output is to be written (NULL if none)
Output parameters:
None
Return value:
None
**************************************************************************/
void getURI(
PDDoc docP, FILE *outf)
{
PDAction action;
PDPage page;
char buf[32];
PDAnnot annot;
DURING
strcpy(buf, "thisisit" );
page =
PDDocAcquirePage(docP, 0);
annot =
PDPageGetAnnot(page, 0);
action = PDAnnotGetAction(annot);
PDActionGetURI(action, ( char *)&buf, sizeof (buf));
fprintf(outf, "%s\n" , buf);
PDPageRelease(page);
HANDLER
END_HANDLER
}