diff options
Diffstat (limited to 'security/nss/cmd/signtool/javascript.c')
-rw-r--r-- | security/nss/cmd/signtool/javascript.c | 1867 |
1 files changed, 0 insertions, 1867 deletions
diff --git a/security/nss/cmd/signtool/javascript.c b/security/nss/cmd/signtool/javascript.c deleted file mode 100644 index add76db03..000000000 --- a/security/nss/cmd/signtool/javascript.c +++ /dev/null @@ -1,1867 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * 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 the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#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: %s\n", - 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: %s\n", 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(int 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 = '\0'; - 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; - PORT_Assert(quotechar == '\0'); - quotechar = curchar; /* look for matching quote type */ - } else { - /* just more value */ - } - break; - case GET_QUOTED_VAL_STATE: - PORT_Assert(quotechar != '\0'); - 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; - quotechar = '\0'; - 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 = (unsigned char) 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] = '\0'; - 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, "applet\n"); - break; - case SCRIPT_TAG: - PR_fprintf(fd, "script\n"); - break; - case LINK_TAG: - PR_fprintf(fd, "link\n"); - break; - case STYLE_TAG: - PR_fprintf(fd, "style\n"); - break; - case COMMENT_TAG: - PR_fprintf(fd, "comment\n"); - break; - case OTHER_TAG: - default: - PR_fprintf(fd, "other\n"); - break; - } - - PR_fprintf(fd, "Attributes:\n"); - for (pair = ti->attList; pair; pair = pair->next) { - PR_fprintf(fd, "\t%s=%s\n", pair->attribute, - pair->value ? pair->value : ""); - } - PR_fprintf(fd, "Text:%s\n", 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%s\n-----\n\n", 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=%s\n", - 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=%s\n", text, basedir, archiveDir, - HTMLfilename); - } - - /* Construct the filename */ - ext = PL_strrchr(HTMLfilename, '.'); - if (ext) { - *ext = '\0'; - } - for (start = HTMLfilename; strpbrk(start, "/\\"); - start = strpbrk(start, "/\\") + 1) - /* do nothing */; - if (*start == '\0') - 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=%s\n", 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: - break; - } - return "unknown"; -} - - -/************************************************************************ - * - * e x t r a c t _ j s - * - */ -static int -extract_js(char *filename) -{ - PRFileDesc * fd = NULL; - FileBuffer * fb = NULL; - HTMLItem * head = NULL; - HTMLItem * tail = NULL; - HTMLItem * curitem = NULL; - HTMLItem * styleList = NULL; - HTMLItem * styleListTail = NULL; - HTMLItem * entityList = NULL; - HTMLItem * entityListTail = NULL; - TagItem * tagp = NULL; - char *text = NULL; - char *tagerr = NULL; - char *archiveDir = NULL; - char *firstArchiveDir = NULL; - char *basedir = NULL; - PRInt32 textStart; - PRInt32 curOffset; - HTML_STATE state; - int curchar; - int retval = -1; - unsigned int linenum, startLine; - - /* 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 = '\0'; - } - - /* Now remove everything from the last slash (which will be followed - * by a filename) to the end */ - cp = PL_strprbrk(basedir, "/\\"); - if (cp) { - *cp = '\0'; - } - } - - 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: %s\n", - filename, tagerr); - errorCount++; - } else { - PR_fprintf(errorFD, - "Error in file %s, in tag starting at line %d\n", - 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: %s\n", - filename, tagerr); - } else { - PR_fprintf(errorFD, - "Error in file %s, in tag starting at" - " line %d\n", 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 = '\0'; - 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 = '\0'; - - 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 overwrite\n", 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: %s\n", 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; -} - - |