javascript.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:43k
- /*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
- #include "signtool.h"
- #include <prmem.h>
- #include <prio.h>
- #include <prenv.h>
- static int javascript_fn(char *relpath, char *basedir, char *reldir,
- char *filename, void *arg);
- static int extract_js (char *filename);
- static int copyinto (char *from, char *to);
- static PRStatus ensureExists (char *base, char *path);
- static int make_dirs(char *path, PRInt32 file_perms);
- static char *jartree = NULL;
- static int idOrdinal;
- static PRBool dumpParse=PR_FALSE;
- static char *event_handlers[] = {
- "onAbort",
- "onBlur",
- "onChange",
- "onClick",
- "onDblClick",
- "onDragDrop",
- "onError",
- "onFocus",
- "onKeyDown",
- "onKeyPress",
- "onKeyUp",
- "onLoad",
- "onMouseDown",
- "onMouseMove",
- "onMouseOut",
- "onMouseOver",
- "onMouseUp",
- "onMove",
- "onReset",
- "onResize",
- "onSelect",
- "onSubmit",
- "onUnload"
- };
- static int num_handlers = 23;
- /*
- * I n l i n e J a v a S c r i p t
- *
- * Javascript signing. Instead of passing an archive to signtool,
- * a directory containing html files is given. Archives are created
- * from the archive= and src= tag attributes inside the html,
- * as appropriate. Then the archives are signed.
- *
- */
- int
- InlineJavaScript(char *dir, PRBool recurse)
- {
- jartree = dir;
- if(verbosity >= 0) {
- PR_fprintf(outputFD, "nGenerating inline signatures from HTML files in: %sn", dir);
- }
- if(PR_GetEnv("SIGNTOOL_DUMP_PARSE")) {
- dumpParse = PR_TRUE;
- }
- return foreach(dir, "", javascript_fn, recurse, PR_FALSE /*include dirs*/,
- (void*)NULL);
- }
- /************************************************************************
- *
- * j a v a s c r i p t _ f n
- */
- static int javascript_fn
- (char *relpath, char *basedir, char *reldir, char *filename, void *arg)
- {
- char fullname [FNSIZE];
- /* only process inline scripts from .htm, .html, and .shtml*/
- if(! (PL_strcaserstr(filename, ".htm") == filename + strlen(filename) -4) &&
- ! (PL_strcaserstr(filename, ".html") == filename + strlen(filename) -5)&&
- ! (PL_strcaserstr(filename, ".shtml") == filename + strlen(filename)-6)){
- return 0;
- }
- /* don't process scripts that signtool has already
- extracted (those that are inside .arc directories) */
- if(PL_strcaserstr(filename, ".arc") == filename + strlen(filename) - 4)
- return 0;
- if(verbosity >= 0) {
- PR_fprintf(outputFD, "Processing HTML file: %sn", relpath);
- }
- /* reset firstArchive at top of each HTML file */
- /* skip directories that contain extracted scripts */
- if(PL_strcaserstr(reldir, ".arc") == reldir + strlen(reldir) - 4)
- return 0;
- sprintf (fullname, "%s/%s", basedir, relpath);
- return extract_js (fullname);
- }
- /*===========================================================================
- =
- = D A T A S T R U C T U R E S
- =
- */
- typedef enum {
- TEXT_HTML_STATE=0,
- SCRIPT_HTML_STATE
- } HTML_STATE ;
- typedef enum {
- /* we start in the start state */
- START_STATE,
- /* We are looking for or reading in an attribute */
- GET_ATT_STATE,
- /* We're burning ws before finding an attribute */
- PRE_ATT_WS_STATE,
- /* We're burning ws after an attribute. Looking for an '='. */
- POST_ATT_WS_STATE,
- /* We're burning ws after an '=', waiting for a value */
- PRE_VAL_WS_STATE,
- /* We're reading in a value */
- GET_VALUE_STATE,
- /* We're reading in a value that's inside quotes */
- GET_QUOTED_VAL_STATE,
- /* We've encountered the closing '>' */
- DONE_STATE,
- /* Error state */
- ERR_STATE
- } TAG_STATE ;
- typedef struct AVPair_Str {
- char *attribute;
- char *value;
- unsigned int valueLine; /* the line that the value ends on */
- struct AVPair_Str *next;
- } AVPair;
- typedef enum {
- APPLET_TAG,
- SCRIPT_TAG,
- LINK_TAG,
- STYLE_TAG,
- COMMENT_TAG,
- OTHER_TAG
- } TAG_TYPE ;
- typedef struct {
- TAG_TYPE type;
- AVPair *attList;
- AVPair *attListTail;
- char *text;
- } TagItem;
- typedef enum {
- TAG_ITEM,
- TEXT_ITEM
- } ITEM_TYPE ;
- typedef struct HTMLItem_Str{
- unsigned int startLine;
- unsigned int endLine;
- ITEM_TYPE type;
- union {
- TagItem *tag;
- char *text;
- } item;
- struct HTMLItem_Str *next;
- } HTMLItem;
- typedef struct {
- PRFileDesc *fd;
- PRInt32 curIndex;
- PRBool IsEOF;
- #define FILE_BUFFER_BUFSIZE 512
- char buf[FILE_BUFFER_BUFSIZE];
- PRInt32 startOffset;
- PRInt32 maxIndex;
- unsigned int lineNum;
- } FileBuffer;
- /*===========================================================================
- =
- = F U N C T I O N S
- =
- */
- static HTMLItem* CreateTextItem(char *text, unsigned int startline,
- unsigned int endline);
- static HTMLItem* CreateTagItem(TagItem* ti, unsigned int startline,
- unsigned int endline);
- static TagItem* ProcessTag(FileBuffer* fb, char **errStr);
- static void DestroyHTMLItem(HTMLItem *item);
- static void DestroyTagItem(TagItem* ti);
- static TAG_TYPE GetTagType(char *att);
- static FileBuffer* FB_Create(PRFileDesc* fd);
- static int FB_GetChar(FileBuffer *fb);
- static PRInt32 FB_GetPointer(FileBuffer *fb);
- static PRInt32 FB_GetRange(FileBuffer *fb, PRInt32 start, PRInt32 end,
- char **buf);
- static unsigned int FB_GetLineNum(FileBuffer *fb);
- static void FB_Destroy(FileBuffer *fb);
- static void PrintTagItem(PRFileDesc *fd, TagItem *ti);
- static void PrintHTMLStream(PRFileDesc *fd, HTMLItem *head);
- /************************************************************************
- *
- * C r e a t e T e x t I t e m
- */
- static HTMLItem*
- CreateTextItem(char *text, unsigned int startline, unsigned int endline)
- {
- HTMLItem *item;
- item = PR_Malloc(sizeof(HTMLItem));
- if(!item) {
- return NULL;
- }
- item->type = TEXT_ITEM;
- item->item.text = text;
- item->next = NULL;
- item->startLine = startline;
- item->endLine = endline;
- return item;
- }
- /************************************************************************
- *
- * C r e a t e T a g I t e m
- */
- static HTMLItem*
- CreateTagItem(TagItem* ti, unsigned int startline, unsigned int endline)
- {
- HTMLItem *item;
- item = PR_Malloc(sizeof(HTMLItem));
- if(!item) {
- return NULL;
- }
- item->type = TAG_ITEM;
- item->item.tag = ti;
- item->next = NULL;
- item->startLine = startline;
- item->endLine = endline;
- return item;
- }
- static PRBool
- isAttChar(char c)
- {
- return (isalnum(c) || c=='/' || c=='-');
- }
- /************************************************************************
- *
- * P r o c e s s T a g
- */
- static TagItem*
- ProcessTag(FileBuffer* fb, char **errStr)
- {
- TAG_STATE state;
- PRInt32 startText, startID, curPos;
- PRBool firstAtt;
- int curchar;
- TagItem *ti=NULL;
- AVPair *curPair=NULL;
- char quotechar;
- unsigned int linenum;
- unsigned int startline;
- state = START_STATE;
- startID = FB_GetPointer(fb);
- startText = startID;
- firstAtt = PR_TRUE;
- ti = (TagItem*) PR_Malloc(sizeof(TagItem));
- if(!ti) out_of_memory();
- ti->type = OTHER_TAG;
- ti->attList = NULL;
- ti->attListTail = NULL;
- ti->text = NULL;
- startline = FB_GetLineNum(fb);
- while(state != DONE_STATE && state != ERR_STATE) {
- linenum = FB_GetLineNum(fb);
- curchar = FB_GetChar(fb);
- if(curchar == EOF) {
- *errStr = PR_smprintf(
- "line %d: Unexpected end-of-file while parsing tag starting at line %d.n", linenum, startline);
- state = ERR_STATE;
- continue;
- }
- switch(state) {
- case START_STATE:
- if(curchar=='!') {
- /*
- * SGML tag or comment
- * Here's the general rule for SGML tags. Everything from
- * <! to > is the tag. Inside the tag, comments are
- * delimited with --. So we are looking for the first '>'
- * that is not commented out, that is, not inside a pair
- * of --: <!DOCTYPE --this is a comment >(psyche!) -->
- */
- PRBool inComment = PR_FALSE;
- short hyphenCount = 0; /* number of consecutive hyphens */
- while(1) {
- linenum = FB_GetLineNum(fb);
- curchar = FB_GetChar(fb);
- if(curchar == EOF) {
- /* Uh oh, EOF inside comment */
- *errStr = PR_smprintf(
- "line %d: Unexpected end-of-file inside comment starting at line %d.n",
- linenum, startline);
- state = ERR_STATE;
- break;
- }
- if(curchar=='-') {
- if(hyphenCount==1) {
- /* This is a comment delimiter */
- inComment = !inComment;
- hyphenCount=0;
- } else {
- /* beginning of a comment delimiter? */
- hyphenCount=1;
- }
- } else if(curchar=='>') {
- if(!inComment) {
- /* This is the end of the tag */
- state = DONE_STATE;
- break;
- } else {
- /* The > is inside a comment, so it's not
- * really the end of the tag */
- hyphenCount=0;
- }
- } else {
- hyphenCount = 0;
- }
- }
- ti->type = COMMENT_TAG;
- break;
- }
- /* fall through */
- case GET_ATT_STATE:
- if(isspace(curchar) || curchar=='=' || curchar=='>') {
- /* end of the current attribute */
- curPos = FB_GetPointer(fb)-2;
- if(curPos >= startID) {
- /* We have an attribute */
- curPair = (AVPair*)PR_Malloc(sizeof(AVPair));
- if(!curPair) out_of_memory();
- curPair->value = NULL;
- curPair->next = NULL;
- FB_GetRange(fb, startID, curPos, &curPair->attribute);
- /* Stick this attribute on the list */
- if(ti->attListTail) {
- ti->attListTail->next = curPair;
- ti->attListTail = curPair;
- } else {
- ti->attList = ti->attListTail = curPair;
- }
-
- /* If this is the first attribute, find the type of tag
- * based on it. Also, start saving the text of the tag. */
- if(firstAtt) {
- ti->type = GetTagType(curPair->attribute);
- startText = FB_GetPointer(fb)-1;
- firstAtt = PR_FALSE;
- }
- } else {
- if(curchar=='=') {
- /* If we don't have any attribute but we do have an
- * equal sign, that's an error */
- *errStr = PR_smprintf("line %d: Malformed tag starting at line %d.n", linenum, startline);
- state = ERR_STATE;
- break;
- }
- }
- /* Compute next state */
- if(curchar=='=') {
- startID = FB_GetPointer(fb);
- state = PRE_VAL_WS_STATE;
- } else if(curchar=='>') {
- state = DONE_STATE;
- } else if(curPair) {
- state = POST_ATT_WS_STATE;
- } else {
- state = PRE_ATT_WS_STATE;
- }
- } else if(isAttChar(curchar)) {
- /* Just another char in the attribute. Do nothing */
- state = GET_ATT_STATE;
- } else {
- /* bogus char */
- *errStr= PR_smprintf("line %d: Bogus chararacter '%c' in tag.n",
- linenum, curchar);
- state = ERR_STATE;
- break;
- }
- break;
- case PRE_ATT_WS_STATE:
- if(curchar=='>') {
- state = DONE_STATE;
- } else if(isspace(curchar)) {
- /* more whitespace, do nothing */
- } else if(isAttChar(curchar)) {
- /* starting another attribute */
- startID = FB_GetPointer(fb)-1;
- state = GET_ATT_STATE;
- } else {
- /* bogus char */
- *errStr = PR_smprintf("line %d: Bogus character '%c' in tag.n",
- linenum, curchar);
- state = ERR_STATE;
- break;
- }
- break;
- case POST_ATT_WS_STATE:
- if(curchar=='>') {
- state = DONE_STATE;
- } else if(isspace(curchar)) {
- /* more whitespace, do nothing */
- } else if(isAttChar(curchar)) {
- /* starting another attribute */
- startID = FB_GetPointer(fb)-1;
- state = GET_ATT_STATE;
- } else if(curchar=='=') {
- /* there was whitespace between the attribute and its equal
- * sign, which means there's a value coming up */
- state = PRE_VAL_WS_STATE;
- } else {
- /* bogus char */
- *errStr = PR_smprintf("line %d: Bogus character '%c' in tag.n",
- linenum, curchar);
- state = ERR_STATE;
- break;
- }
- break;
- case PRE_VAL_WS_STATE:
- if(curchar=='>') {
- /* premature end-of-tag (sounds like a personal problem). */
- *errStr = PR_smprintf(
- "line %d: End of tag while waiting for value.n", linenum);
- state = ERR_STATE;
- break;
- } else if(isspace(curchar)) {
- /* more whitespace, do nothing */
- break;
- } else {
- /* this must be some sort of value. Fall through
- * to GET_VALUE_STATE */
- startID=FB_GetPointer(fb)-1;
- state = GET_VALUE_STATE;
- }
- /* Fall through if we didn't break on '>' or whitespace */
- case GET_VALUE_STATE:
- if(isspace(curchar) || curchar=='>') {
- /* end of value */
- curPos = FB_GetPointer(fb)-2;
- if(curPos >= startID) {
- /* Grab the value */
- FB_GetRange(fb, startID, curPos, &curPair->value);
- curPair->valueLine = linenum;
- } else {
- /* empty value, leave as NULL */
- }
- if(isspace(curchar)) {
- state = PRE_ATT_WS_STATE;
- } else {
- state = DONE_STATE;
- }
- } else if(curchar=='"' || curchar==''') {
- /* quoted value. Start recording the value inside the quote*/
- startID = FB_GetPointer(fb);
- state = GET_QUOTED_VAL_STATE;
- quotechar = curchar; /* look for matching quote type */
- } else {
- /* just more value */
- }
- break;
- case GET_QUOTED_VAL_STATE:
- if(curchar == quotechar) {
- /* end of quoted value */
- curPos = FB_GetPointer(fb)-2;
- if(curPos >= startID) {
- /* Grab the value */
- FB_GetRange(fb, startID, curPos, &curPair->value);
- curPair->valueLine = linenum;
- } else {
- /* empty value, leave it as NULL */
- }
- state = GET_ATT_STATE;
- startID = FB_GetPointer(fb);
- } else {
- /* more quoted value, continue */
- }
- break;
- case DONE_STATE:
- case ERR_STATE:
- default:
- ; /* should never get here */
- }
- }
- if(state == DONE_STATE) {
- /* Get the text of the tag */
- curPos = FB_GetPointer(fb)-1;
- FB_GetRange(fb, startText, curPos, &ti->text);
- /* Return the tag */
- return ti;
- }
- /* Uh oh, an error. Kill the tag item*/
- DestroyTagItem(ti);
- return NULL;
- }
- /************************************************************************
- *
- * D e s t r o y H T M L I t e m
- */
- static void
- DestroyHTMLItem(HTMLItem *item)
- {
- if(item->type == TAG_ITEM) {
- DestroyTagItem(item->item.tag);
- } else {
- if(item->item.text) {
- PR_Free(item->item.text);
- }
- }
- }
- /************************************************************************
- *
- * D e s t r o y T a g I t e m
- */
- static void
- DestroyTagItem(TagItem* ti)
- {
- AVPair *temp;
- if(ti->text) {
- PR_Free(ti->text); ti->text = NULL;
- }
- while(ti->attList) {
- temp = ti->attList;
- ti->attList = ti->attList->next;
- if(temp->attribute) {
- PR_Free(temp->attribute); temp->attribute = NULL;
- }
- if(temp->value) {
- PR_Free(temp->value); temp->value = NULL;
- }
- PR_Free(temp);
- }
- PR_Free(ti);
- }
- /************************************************************************
- *
- * G e t T a g T y p e
- */
- static TAG_TYPE
- GetTagType(char *att)
- {
- if(!PORT_Strcasecmp(att, "APPLET")) {
- return APPLET_TAG;
- }
- if(!PORT_Strcasecmp(att, "SCRIPT")) {
- return SCRIPT_TAG;
- }
- if(!PORT_Strcasecmp(att, "LINK")) {
- return LINK_TAG;
- }
- if(!PORT_Strcasecmp(att, "STYLE")) {
- return STYLE_TAG;
- }
- return OTHER_TAG;
- }
- /************************************************************************
- *
- * F B _ C r e a t e
- */
- static FileBuffer*
- FB_Create(PRFileDesc* fd)
- {
- FileBuffer *fb;
- PRInt32 amountRead;
- PRInt32 storedOffset;
- fb = (FileBuffer*) PR_Malloc(sizeof(FileBuffer));
- fb->fd = fd;
- storedOffset = PR_Seek(fd, 0, PR_SEEK_CUR);
- PR_Seek(fd, 0, PR_SEEK_SET);
- fb->startOffset = 0;
- amountRead = PR_Read(fd, fb->buf, FILE_BUFFER_BUFSIZE);
- if(amountRead == -1) goto loser;
- fb->maxIndex = amountRead-1;
- fb->curIndex = 0;
- fb->IsEOF = (fb->curIndex>fb->maxIndex) ? PR_TRUE : PR_FALSE;
- fb->lineNum = 1;
- PR_Seek(fd, storedOffset, PR_SEEK_SET);
- return fb;
- loser:
- PR_Seek(fd, storedOffset, PR_SEEK_SET);
- PR_Free(fb);
- return NULL;
- }
- /************************************************************************
- *
- * F B _ G e t C h a r
- */
- static int
- FB_GetChar(FileBuffer *fb)
- {
- PRInt32 storedOffset;
- PRInt32 amountRead;
- int retval=-1;
- if(fb->IsEOF) {
- return EOF;
- }
- storedOffset = PR_Seek(fb->fd, 0, PR_SEEK_CUR);
- retval = fb->buf[fb->curIndex++];
- if(retval=='n') fb->lineNum++;
- if(fb->curIndex > fb->maxIndex) {
- /* We're at the end of the buffer. Try to get some new data from the
- * file */
- fb->startOffset += fb->maxIndex+1;
- PR_Seek(fb->fd, fb->startOffset, PR_SEEK_SET);
- amountRead = PR_Read(fb->fd, fb->buf, FILE_BUFFER_BUFSIZE);
- if(amountRead==-1) goto loser;
- fb->maxIndex = amountRead-1;
- fb->curIndex = 0;
- }
- fb->IsEOF = (fb->curIndex > fb->maxIndex) ? PR_TRUE : PR_FALSE;
- loser:
- PR_Seek(fb->fd, storedOffset, PR_SEEK_SET);
- return retval;
- }
- /************************************************************************
- *
- * F B _ G e t L i n e N u m
- *
- */
- static unsigned int
- FB_GetLineNum(FileBuffer *fb)
- {
- return fb->lineNum;
- }
- /************************************************************************
- *
- * F B _ G e t P o i n t e r
- *
- */
- static PRInt32
- FB_GetPointer(FileBuffer *fb)
- {
- return fb->startOffset + fb->curIndex;
- }
- /************************************************************************
- *
- * F B _ G e t R a n g e
- *
- */
- static PRInt32
- FB_GetRange(FileBuffer *fb, PRInt32 start, PRInt32 end, char **buf)
- {
- PRInt32 amountRead;
- PRInt32 storedOffset;
- *buf = PR_Malloc(end-start+2);
- if(*buf == NULL) {
- return 0;
- }
- storedOffset = PR_Seek(fb->fd, 0, PR_SEEK_CUR);
- PR_Seek(fb->fd, start, PR_SEEK_SET);
- amountRead = PR_Read(fb->fd, *buf, end-start+1);
- PR_Seek(fb->fd, storedOffset, PR_SEEK_SET);
- if(amountRead == -1) {
- PR_Free(*buf);
- *buf = NULL;
- return 0;
- }
- (*buf)[end-start+1] = ' ';
- return amountRead;
- }
- /************************************************************************
- *
- * F B _ D e s t r o y
- *
- */
- static void
- FB_Destroy(FileBuffer *fb)
- {
- if(fb) {
- PR_Free(fb);
- }
- }
- /************************************************************************
- *
- * P r i n t T a g I t e m
- *
- */
- static void
- PrintTagItem(PRFileDesc *fd, TagItem *ti)
- {
- AVPair *pair;
- PR_fprintf(fd, "TAG:n----nType: ");
- switch(ti->type) {
- case APPLET_TAG:
- PR_fprintf(fd, "appletn");
- break;
- case SCRIPT_TAG:
- PR_fprintf(fd, "scriptn");
- break;
- case LINK_TAG:
- PR_fprintf(fd, "linkn");
- break;
- case STYLE_TAG:
- PR_fprintf(fd, "stylen");
- break;
- case COMMENT_TAG:
- PR_fprintf(fd, "commentn");
- break;
- case OTHER_TAG:
- default:
- PR_fprintf(fd, "othern");
- break;
- }
- PR_fprintf(fd, "Attributes:n");
- for(pair = ti->attList; pair; pair=pair->next) {
- PR_fprintf(fd, "t%s=%sn", pair->attribute,
- pair->value ? pair->value : "");
- }
- PR_fprintf(fd, "Text:%sn", ti->text ? ti->text : "");
- PR_fprintf(fd, "---End of tag---n");
- }
- /************************************************************************
- *
- * P r i n t H T M L S t r e a m
- *
- */
- static void
- PrintHTMLStream(PRFileDesc *fd, HTMLItem *head)
- {
- while(head) {
- if(head->type==TAG_ITEM) {
- PrintTagItem(fd, head->item.tag);
- } else {
- PR_fprintf(fd, "nTEXT:n-----n%sn-----nn", head->item.text);
- }
- head = head->next;
- }
- }
- /************************************************************************
- *
- * S a v e I n l i n e S c r i p t
- *
- */
- static int
- SaveInlineScript(char *text, char *id, char *basedir, char *archiveDir)
- {
- char *filename=NULL;
- PRFileDesc *fd=NULL;
- int retval = -1;
- PRInt32 writeLen;
- char *ilDir=NULL;
- if(!text || !id || !archiveDir) {
- return -1;
- }
- if(dumpParse) {
- PR_fprintf(outputFD, "SaveInlineScript: text=%s, id=%s, n"
- "basedir=%s, archiveDir=%sn",
- text, id, basedir, archiveDir);
- }
- /* Make sure the archive directory is around */
- if(ensureExists(basedir, archiveDir) != PR_SUCCESS) {
- PR_fprintf(errorFD,
- "ERROR: Unable to create archive directory %s.n", archiveDir);
- errorCount++;
- return -1;
- }
- /* Make sure the inline script directory is around */
- ilDir = PR_smprintf("%s/inlineScripts", archiveDir);
- scriptdir = "inlineScripts";
- if(ensureExists(basedir, ilDir) != PR_SUCCESS) {
- PR_fprintf(errorFD,
- "ERROR: Unable to create directory %s.n", ilDir);
- errorCount++;
- return -1;
- }
- filename = PR_smprintf("%s/%s/%s", basedir, ilDir, id);
- /* If the file already exists, give a warning, then blow it away */
- if(PR_Access(filename, PR_ACCESS_EXISTS) == PR_SUCCESS) {
- PR_fprintf(errorFD,
- "warning: file "%s" already exists--will overwrite.n",
- filename);
- warningCount++;
- if(rm_dash_r(filename)) {
- PR_fprintf(errorFD,
- "ERROR: Unable to delete %s.n", filename);
- errorCount++;
- goto finish;
- }
- }
- /* Write text into file with name id */
- fd = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0777);
- if(!fd) {
- PR_fprintf(errorFD, "ERROR: Unable to create file "%s".n",
- filename);
- errorCount++;
- goto finish;
- }
- writeLen = strlen(text);
- if( PR_Write(fd, text, writeLen) != writeLen) {
- PR_fprintf(errorFD, "ERROR: Unable to write to file "%s".n",
- filename);
- errorCount++;
- goto finish;
- }
- retval = 0;
- finish:
- if(filename) {
- PR_smprintf_free(filename);
- }
- if(ilDir) {
- PR_smprintf_free(ilDir);
- }
- if(fd) {
- PR_Close(fd);
- }
- return retval;
- }
- /************************************************************************
- *
- * S a v e U n n a m a b l e S c r i p t
- *
- */
- static int
- SaveUnnamableScript(char *text, char *basedir, char *archiveDir,
- char *HTMLfilename)
- {
- char *id=NULL;
- char *ext=NULL;
- char *start=NULL;
- int retval = -1;
- if(!text || !archiveDir || !HTMLfilename) {
- return -1;
- }
- if(dumpParse) {
- PR_fprintf(outputFD, "SaveUnnamableScript: text=%s, basedir=%s,n"
- "archiveDir=%s, filename=%sn", text, basedir, archiveDir,
- HTMLfilename);
- }
- /* Construct the filename */
- ext = PL_strrchr(HTMLfilename, '.');
- if(ext) {
- *ext = ' ';
- }
- for(start=HTMLfilename; strpbrk(start, "/\");
- start=strpbrk(start, "/\")+1);
- if(*start==' ') start = HTMLfilename;
- id = PR_smprintf("_%s%d", start, idOrdinal++);
- if(ext) {
- *ext = '.';
- }
- /* Now call SaveInlineScript to do the work */
- retval = SaveInlineScript(text, id, basedir, archiveDir);
- PR_Free(id);
- return retval;
- }
- /************************************************************************
- *
- * S a v e S o u r c e
- *
- */
- static int
- SaveSource(char *src, char *codebase, char *basedir, char *archiveDir)
- {
- char *from=NULL, *to=NULL;
- int retval = -1;
- char *arcDir=NULL;
- if(!src || !archiveDir) {
- return -1;
- }
- if(dumpParse) {
- PR_fprintf(outputFD, "SaveSource: src=%s, codebase=%s, basedir=%s,n"
- "archiveDir=%sn", src, codebase, basedir, archiveDir);
- }
- if(codebase) {
- arcDir = PR_smprintf("%s/%s/%s/", basedir, codebase, archiveDir);
- } else {
- arcDir = PR_smprintf("%s/%s/", basedir, archiveDir);
- }
- if(codebase) {
- from = PR_smprintf("%s/%s/%s", basedir, codebase, src);
- to = PR_smprintf("%s%s", arcDir, src);
- } else {
- from = PR_smprintf("%s/%s", basedir, src);
- to = PR_smprintf("%s%s", arcDir, src);
- }
- if(make_dirs(to, 0777)) {
- PR_fprintf(errorFD,
- "ERROR: Unable to create archive directory %s.n", archiveDir);
- errorCount++;
- goto finish;
- }
- retval = copyinto(from, to);
- finish:
- if(from) PR_Free(from);
- if(to) PR_Free(to);
- if(arcDir) PR_Free(arcDir);
- return retval;
- }
- /************************************************************************
- *
- * T a g T y p e T o S t r i n g
- *
- */
- char *
- TagTypeToString(TAG_TYPE type)
- {
- switch(type) {
- case APPLET_TAG:
- return "APPLET";
- case SCRIPT_TAG:
- return "SCRIPT";
- case LINK_TAG:
- return "LINK";
- case STYLE_TAG:
- return "STYLE";
- default:
- return "unknown";
- }
- return "unknown";
- }
- /************************************************************************
- *
- * e x t r a c t _ j s
- *
- */
- static int
- extract_js(char *filename)
- {
- PRFileDesc *fd=NULL;
- FileBuffer *fb=NULL;
- HTML_STATE state;
- int curchar;
- HTMLItem *head = NULL;
- HTMLItem *tail = NULL;
- PRInt32 textStart;
- PRInt32 curOffset;
- TagItem *tagp=NULL;
- char *text=NULL;
- HTMLItem *curitem=NULL;
- int retval = -1;
- char *tagerr=NULL;
- unsigned int linenum, startLine;
- char *archiveDir=NULL, *firstArchiveDir=NULL;
- HTMLItem *styleList, *styleListTail;
- HTMLItem *entityList, *entityListTail;
- char *basedir=NULL;
- styleList = entityList = styleListTail = entityListTail = NULL;
- /* Initialize the implicit ID counter for each file */
- idOrdinal = 0;
- /*
- * First, parse the HTML into a stream of tags and text.
- */
- fd = PR_Open(filename, PR_RDONLY, 0);
- if(!fd) {
- PR_fprintf(errorFD, "Unable to open %s for reading.n", filename);
- errorCount++;
- return -1;
- }
- /* Construct base directory of filename. */
- {
- char *cp;
- basedir = PL_strdup(filename);
- /* Remove trailing slashes */
- while( (cp = PL_strprbrk(basedir, "/\")) ==
- (basedir + strlen(basedir) - 1)) {
- *cp = ' ';
- }
- /* Now remove everything from the last slash (which will be followed
- * by a filename) to the end */
- cp = PL_strprbrk(basedir, "/\");
- if(cp) {
- *cp = ' ';
- }
- }
- state = TEXT_HTML_STATE;
- fb = FB_Create(fd);
- textStart=0;
- startLine = 0;
- while(linenum=FB_GetLineNum(fb), (curchar = FB_GetChar(fb)) != EOF) {
- switch(state) {
- case TEXT_HTML_STATE:
- if(curchar == '<') {
- /*
- * Found a tag
- */
- /* Save the text so far to a new text item */
- curOffset = FB_GetPointer(fb)-2;
- if(curOffset >= textStart) {
- if(FB_GetRange(fb, textStart, curOffset, &text) !=
- curOffset-textStart+1) {
- PR_fprintf(errorFD,
- "Unable to read from %s.n", filename);
- errorCount++;
- goto loser;
- }
- /* little fudge here. If the first character on a line
- * is '<', meaning a new tag, the preceding text item
- * actually ends on the previous line. In this case
- * we will be saying that the text segment ends on the
- * next line. I don't think this matters for text items. */
- curitem = CreateTextItem(text, startLine, linenum);
- text = NULL;
- if(tail == NULL) {
- head = tail = curitem;
- } else {
- tail->next = curitem;
- tail = curitem;
- }
- }
- /* Process the tag */
- tagp = ProcessTag(fb, &tagerr);
- if(!tagp) {
- if(tagerr) {
- PR_fprintf(errorFD, "Error in file %s: %sn",
- filename, tagerr);
- errorCount++;
- } else {
- PR_fprintf(errorFD,
- "Error in file %s, in tag starting at line %dn",
- filename, linenum);
- errorCount++;
- }
- goto loser;
- }
- /* Add the tag to the list */
- curitem = CreateTagItem(tagp, linenum, FB_GetLineNum(fb));
- if(tail == NULL) {
- head = tail = curitem;
- } else {
- tail->next = curitem;
- tail = curitem;
- }
- /* What's the next state */
- if(tagp->type == SCRIPT_TAG) {
- state = SCRIPT_HTML_STATE;
- }
- /* Start recording text from the new offset */
- textStart = FB_GetPointer(fb);
- startLine = FB_GetLineNum(fb);
- } else {
- /* regular character. Next! */
- }
- break;
- case SCRIPT_HTML_STATE:
- if(curchar == '<') {
- char *cp;
- /*
- * If this is a </script> tag, then we're at the end of the
- * script. Otherwise, ignore
- */
- curOffset = FB_GetPointer(fb)-1;
- cp = NULL;
- if(FB_GetRange(fb, curOffset, curOffset+8, &cp) != 9) {
- if(cp) { PR_Free(cp); cp = NULL; }
- } else {
- /* compare the strings */
- if( !PORT_Strncasecmp(cp, "</script>", 9) ) {
- /* This is the end of the script. Record the text. */
- curOffset--;
- if(curOffset >= textStart) {
- if(FB_GetRange(fb, textStart, curOffset, &text) !=
- curOffset-textStart+1) {
- PR_fprintf(errorFD,
- "Unable to read from %s.n", filename);
- errorCount++;
- goto loser;
- }
- curitem = CreateTextItem(text, startLine, linenum);
- text = NULL;
- if(tail == NULL) {
- head = tail = curitem;
- } else {
- tail->next = curitem;
- tail = curitem;
- }
- }
-
- /* Now parse the /script tag and put it on the list */
- tagp = ProcessTag(fb, &tagerr);
- if(!tagp) {
- if(tagerr) {
- PR_fprintf(errorFD,
- "Error in file %s: %sn", filename, tagerr);
- } else {
- PR_fprintf(errorFD,
- "Error in file %s, in tag starting at"
- " line %dn", filename, linenum);
- }
- errorCount++;
- goto loser;
- }
- curitem = CreateTagItem(tagp, linenum,
- FB_GetLineNum(fb));
- if(tail == NULL) {
- head = tail = curitem;
- } else {
- tail->next = curitem;
- tail = curitem;
- }
- /* go back to text state */
- state = TEXT_HTML_STATE;
- textStart = FB_GetPointer(fb);
- startLine = FB_GetLineNum(fb);
- }
- }
- }
- break;
- }
- }
- /* End of the file. Wrap up any remaining text */
- if(state == SCRIPT_HTML_STATE) {
- if(tail && tail->type==TAG_ITEM) {
- PR_fprintf(errorFD, "ERROR: <SCRIPT> tag at %s:%d is not followed "
- "by a </SCRIPT> tag.n", filename, tail->startLine);
- } else {
- PR_fprintf(errorFD, "ERROR: <SCRIPT> tag in file %s is not followed"
- " by a </SCRIPT tag.n", filename);
- }
- errorCount++;
- goto loser;
- }
- curOffset = FB_GetPointer(fb)-1;
- if(curOffset >= textStart) {
- text = NULL;
- if( FB_GetRange(fb, textStart, curOffset, &text) !=
- curOffset-textStart+1) {
- PR_fprintf(errorFD, "Unable to read from %s.n", filename);
- errorCount++;
- goto loser;
- }
- curitem = CreateTextItem(text, startLine, linenum);
- text = NULL;
- if(tail == NULL) {
- head = tail = curitem;
- } else {
- tail->next = curitem;
- tail = curitem;
- }
- }
- if(dumpParse) {
- PrintHTMLStream(outputFD, head);
- }
- /*
- * Now we have a stream of tags and text. Go through and deal with each.
- */
- for(curitem = head; curitem; curitem = curitem->next) {
- TagItem *tagp=NULL;
- AVPair *pairp=NULL;
- char *src=NULL, *id=NULL, *codebase=NULL;
- PRBool hasEventHandler=PR_FALSE;
- int i;
- /* Reset archive directory for each tag */
- if(archiveDir) {
- PR_Free(archiveDir); archiveDir = NULL;
- }
- /* We only analyze tags */
- if(curitem->type != TAG_ITEM) {
- continue;
- }
- tagp = curitem->item.tag;
- /* go through the attributes to get information */
- for(pairp=tagp->attList; pairp; pairp=pairp->next) {
- /* ARCHIVE= */
- if( !PL_strcasecmp(pairp->attribute, "archive")) {
- if(archiveDir) {
- /* Duplicate attribute. Print warning */
- PR_fprintf(errorFD,
- "warning: "%s" attribute overwrites previous attribute"
- " in tag starting at %s:%d.n",
- pairp->attribute, filename, curitem->startLine);
- warningCount++;
- PR_Free(archiveDir);
- }
- archiveDir = PL_strdup(pairp->value);
- /* Substiture ".arc" for ".jar" */
- if( (PL_strlen(archiveDir)<4) ||
- PL_strcasecmp((archiveDir+strlen(archiveDir)-4), ".jar")){
- PR_fprintf(errorFD,
- "warning: ARCHIVE attribute should end in ".jar" in tag"
- " starting on %s:%d.n", filename, curitem->startLine);
- warningCount++;
- PR_Free(archiveDir);
- archiveDir = PR_smprintf("%s.arc", archiveDir);
- } else {
- PL_strcpy(archiveDir+strlen(archiveDir)-4, ".arc");
- }
- /* Record the first archive. This will be used later if
- * the archive is not specified */
- if(firstArchiveDir == NULL) {
- firstArchiveDir = PL_strdup(archiveDir);
- }
- }
- /* CODEBASE= */
- else if( !PL_strcasecmp(pairp->attribute, "codebase")) {
- if(codebase) {
- /* Duplicate attribute. Print warning */
- PR_fprintf(errorFD,
- "warning: "%s" attribute overwrites previous attribute"
- " in tag staring at %s:%d.n",
- pairp->attribute, filename, curitem->startLine);
- warningCount++;
- }
- codebase = pairp->value;
- }
- /* SRC= and HREF= */
- else if( !PORT_Strcasecmp(pairp->attribute, "src") ||
- !PORT_Strcasecmp(pairp->attribute, "href") ) {
- if(src) {
- /* Duplicate attribute. Print warning */
- PR_fprintf(errorFD,
- "warning: "%s" attribute overwrites previous attribute"
- " in tag staring at %s:%d.n",
- pairp->attribute, filename, curitem->startLine);
- warningCount++;
- }
- src = pairp->value;
- }
- /* CODE= */
- else if(!PORT_Strcasecmp(pairp->attribute, "code") ) {
- /*!!!XXX Change PORT to PL all over this code !!! */
- if(src) {
- /* Duplicate attribute. Print warning */
- PR_fprintf(errorFD,
- "warning: "%s" attribute overwrites previous attribute"
- " ,in tag staring at %s:%d.n",
- pairp->attribute, filename, curitem->startLine);
- warningCount++;
- }
- src = pairp->value;
- /* Append a .class if one is not already present */
- if( (PL_strlen(src)<6) ||
- PL_strcasecmp( (src + PL_strlen(src) - 6), ".class") ) {
- src = PR_smprintf("%s.class", src);
- /* Put this string back into the data structure so it
- * will be deallocated properly */
- PR_Free(pairp->value);
- pairp->value = src;
- }
- }
- /* ID= */
- else if (!PL_strcasecmp(pairp->attribute, "id") ) {
- if(id) {
- /* Duplicate attribute. Print warning */
- PR_fprintf(errorFD,
- "warning: "%s" attribute overwrites previous attribute"
- " in tag staring at %s:%d.n",
- pairp->attribute, filename, curitem->startLine);
- warningCount++;
- }
- id = pairp->value;
- }
- /* STYLE= */
- /* style= attributes, along with JS entities, are stored into
- * files with dynamically generated names. The filenames are
- * based on the order in which the text is found in the file.
- * All JS entities on all lines up to and including the line
- * containing the end of the tag that has this style= attribute
- * will be processed before this style=attribute. So we need
- * to record the line that this _tag_ (not the attribute) ends on.
- */
- else if(!PL_strcasecmp(pairp->attribute, "style") && pairp->value) {
- HTMLItem *styleItem;
- /* Put this item on the style list */
- styleItem = CreateTextItem(PL_strdup(pairp->value),
- curitem->startLine, curitem->endLine);
- if(styleListTail == NULL) {
- styleList = styleListTail = styleItem;
- } else {
- styleListTail->next = styleItem;
- styleListTail = styleItem;
- }
- }
- /* Event handlers */
- else {
- for(i=0; i < num_handlers; i++) {
- if(!PL_strcasecmp(event_handlers[i], pairp->attribute)) {
- hasEventHandler = PR_TRUE;
- break;
- }
- }
- }
- /* JS Entity */
- {
- char *entityStart, *entityEnd;
- HTMLItem *entityItem;
- /* go through each JavaScript entity ( &{...}; ) and store it
- * in the entityList. The important thing is to record what
- * line number it's on, so we can get it in the right order
- * in relation to style= attributes.
- * Apparently, these can't flow across lines, so the start and
- * end line will be the same. That helps matters.
- */
- entityEnd = pairp->value;
- while( entityEnd &&
- (entityStart = PL_strstr(entityEnd, "&{")) != NULL) {
- entityStart +=2; /* point at beginning of actual entity */
- entityEnd = PL_strstr(entityStart, "}");
- if(entityEnd) {
- /* Put this item on the entity list */
- *entityEnd = ' ';
- entityItem = CreateTextItem(PL_strdup(entityStart),
- pairp->valueLine, pairp->valueLine);
- *entityEnd = '}';
- if(entityListTail) {
- entityListTail->next = entityItem;
- entityListTail = entityItem;
- } else {
- entityList = entityListTail = entityItem;
- }
- }
- }
- }
- }
- /* If no archive was supplied, we use the first one of the file */
- if(!archiveDir && firstArchiveDir) {
- archiveDir = PL_strdup(firstArchiveDir);
- }
- /* If we have an event handler, we need to archive this tag */
- if(hasEventHandler) {
- if(!id) {
- PR_fprintf(errorFD,
- "warning: tag starting at %s:%d has event handler but"
- " no ID attribute. The tag will not be signed.n",
- filename, curitem->startLine);
- warningCount++;
- } else if(!archiveDir) {
- PR_fprintf(errorFD,
- "warning: tag starting at %s:%d has event handler but"
- " no ARCHIVE attribute. The tag will not be signed.n",
- filename, curitem->startLine);
- warningCount++;
- } else {
- if(SaveInlineScript(tagp->text, id, basedir, archiveDir)) {
- goto loser;
- }
- }
- }
- switch(tagp->type) {
- case APPLET_TAG:
- if(!src) {
- PR_fprintf(errorFD,
- "error: APPLET tag starting on %s:%d has no CODE "
- "attribute.n", filename, curitem->startLine);
- errorCount++;
- goto loser;
- } else if(!archiveDir) {
- PR_fprintf(errorFD,
- "error: APPLET tag starting on %s:%d has no ARCHIVE "
- "attribute.n", filename, curitem->startLine);
- errorCount++;
- goto loser;
- } else {
- if(SaveSource(src, codebase, basedir, archiveDir)) {
- goto loser;
- }
- }
- break;
- case SCRIPT_TAG:
- case LINK_TAG:
- case STYLE_TAG:
- if(!archiveDir) {
- PR_fprintf(errorFD,
- "error: %s tag starting on %s:%d has no ARCHIVE "
- "attribute.n", TagTypeToString(tagp->type),
- filename, curitem->startLine);
- errorCount++;
- goto loser;
- } else if(src) {
- if(SaveSource(src, codebase, basedir, archiveDir)) {
- goto loser;
- }
- } else if(id) {
- /* Save the next text item */
- if(!curitem->next || (curitem->next->type != TEXT_ITEM)) {
- PR_fprintf(errorFD,
- "warning: %s tag starting on %s:%d is not followed"
- " by script text.n", TagTypeToString(tagp->type),
- filename, curitem->startLine);
- warningCount++;
- /* just create empty file */
- if(SaveInlineScript("", id, basedir, archiveDir)) {
- goto loser;
- }
- } else {
- curitem = curitem->next;
- if(SaveInlineScript(curitem->item.text, id, basedir,
- archiveDir)){
- goto loser;
- }
- }
- } else {
- /* No src or id tag--warning */
- PR_fprintf(errorFD,
- "warning: %s tag starting on %s:%d has no SRC or"
- " ID attributes. Will not sign.n",
- TagTypeToString(tagp->type), filename, curitem->startLine);
- warningCount++;
- }
- break;
- default:
- /* do nothing for other tags */
- break;
- }
- }
- /* Now deal with all the unnamable scripts */
- if(firstArchiveDir) {
- HTMLItem *style, *entity;
- /* Go through the lists of JS entities and style attributes. Do them
- * in chronological order within a list. Pick the list with the lower
- * endLine. In case of a tie, entities come first.
- */
- style = styleList; entity = entityList;
- while(style || entity) {
- if(!entity || (style && (style->endLine < entity->endLine))) {
- /* Process style */
- SaveUnnamableScript(style->item.text, basedir, firstArchiveDir,
- filename);
- style=style->next;
- } else {
- /* Process entity */
- SaveUnnamableScript(entity->item.text, basedir, firstArchiveDir,
- filename);
- entity=entity->next;
- }
- }
- }
- retval = 0;
- loser:
- /* Blow away the stream */
- while(head) {
- curitem = head;
- head = head->next;
- DestroyHTMLItem(curitem);
- }
- while(styleList) {
- curitem = styleList;
- styleList = styleList->next;
- DestroyHTMLItem(curitem);
- }
- while(entityList) {
- curitem = entityList;
- entityList = entityList->next;
- DestroyHTMLItem(curitem);
- }
- if(text) {
- PR_Free(text); text=NULL;
- }
- if(fb) {
- FB_Destroy(fb); fb=NULL;
- }
- if(fd) {
- PR_Close(fd);
- }
- if(tagerr) {
- PR_smprintf_free(tagerr); tagerr=NULL;
- }
- if(archiveDir) {
- PR_Free(archiveDir); archiveDir=NULL;
- }
- if(firstArchiveDir) {
- PR_Free(firstArchiveDir); firstArchiveDir=NULL;
- }
- return retval;
- }
- /**********************************************************************
- *
- * e n s u r e E x i s t s
- *
- * Check for existence of indicated directory. If it doesn't exist,
- * it will be created.
- * Returns PR_SUCCESS if the directory is present, PR_FAILURE otherwise.
- */
- static PRStatus
- ensureExists (char *base, char *path)
- {
- char fn [FNSIZE];
- PRDir *dir;
- sprintf (fn, "%s/%s", base, path);
- /*PR_fprintf(outputFD, "Trying to open directory %s.n", fn);*/
- if( (dir=PR_OpenDir(fn)) ) {
- PR_CloseDir(dir);
- return PR_SUCCESS;
- }
- return PR_MkDir(fn, 0777);
- }
- /***************************************************************************
- *
- * m a k e _ d i r s
- *
- * Ensure that the directory portion of the path exists. This may require
- * making the directory, and its parent, and its parent's parent, etc.
- */
- static int
- make_dirs(char *path, int file_perms)
- {
- char *Path;
- char *start;
- char *sep;
- int ret = 0;
- PRFileInfo info;
- if(!path) {
- return 0;
- }
- Path = PL_strdup(path);
- start = strpbrk(Path, "/\");
- if(!start) {
- return 0;
- }
- start++; /* start right after first slash */
- /* Each time through the loop add one more directory. */
- while( (sep=strpbrk(start, "/\")) ) {
- *sep = ' ';
- if( PR_GetFileInfo(Path, &info) != PR_SUCCESS) {
- /* No such dir, we have to create it */
- if( PR_MkDir(Path, file_perms) != PR_SUCCESS) {
- PR_fprintf(errorFD, "ERROR: Unable to create directory %s.n",
- Path);
- errorCount++;
- ret = -1;
- goto loser;
- }
- } else {
- /* something exists by this name, make sure it's a directory */
- if( info.type != PR_FILE_DIRECTORY ) {
- PR_fprintf(errorFD, "ERROR: Unable to create directory %s.n",
- Path);
- errorCount++;
- ret = -1;
- goto loser;
- }
- }
- start = sep+1; /* start after the next slash */
- *sep = '/';
- }
- loser:
- PR_Free(Path);
- return ret;
- }
- /*
- * c o p y i n t o
- *
- * Function to copy file "from" to path "to".
- *
- */
- static int
- copyinto (char *from, char *to)
- {
- PRInt32 num;
- char buf [BUFSIZ];
- PRFileDesc *infp=NULL, *outfp=NULL;
- int retval = -1;
- if ((infp = PR_Open(from, PR_RDONLY, 0777)) == NULL) {
- PR_fprintf(errorFD, "ERROR: Unable to open "%s" for reading.n",
- from);
- errorCount++;
- goto finish;
- }
- /* If to already exists, print a warning before deleting it */
- if(PR_Access(to, PR_ACCESS_EXISTS) == PR_SUCCESS) {
- PR_fprintf(errorFD, "warning: %s already exists--will overwriten",
- to);
- warningCount++;
- if(rm_dash_r(to)) {
- PR_fprintf(errorFD,
- "ERROR: Unable to remove %s.n", to);
- errorCount++;
- goto finish;
- }
- }
- if ((outfp = PR_Open(to, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0777))
- == NULL) {
- char *errBuf=NULL;
- errBuf = PR_Malloc(PR_GetErrorTextLength());
- PR_fprintf(errorFD, "ERROR: Unable to open "%s" for writing.n",
- to);
- if(PR_GetErrorText(errBuf)) {
- PR_fprintf(errorFD, "Cause: %sn", errBuf);
- }
- if(errBuf) {
- PR_Free(errBuf);
- }
- errorCount++;
- goto finish;
- }
- while( (num = PR_Read(infp, buf, BUFSIZ)) >0) {
- if(PR_Write(outfp, buf, num) != num) {
- PR_fprintf(errorFD, "ERROR: Error writing to %s.n", to);
- errorCount++;
- goto finish;
- }
- }
- retval = 0;
- finish:
- if(infp) PR_Close(infp);
- if(outfp) PR_Close(outfp);
- return retval;
- }