void main() { int ch; char *b; int32 src_count; char *dst; int32 dst_count; char * src; int src_size; int done; done = ch = 0; src_size = src_count = 0; src = (char *) XP_ALLOC(TEST_CSS_INITIAL_BUFSIZ); if (src) src_size = TEST_CSS_INITIAL_BUFSIZ; while (!done) { for (b = src + src_count; src_count < src_size; src_count++, b++) { *b = ch = getc(stdin); /* Either the null character or EOF will serve to terminate. */ if (ch == EOF || ch == '\0') { done = 1; /* We don't need to add this character to the src_count */ break; } } if (!done) { src_size += TEST_CSS_INCR_BUFSIZ; src = (char *) XP_REALLOC(src, src_size); if (!src) { src_size = src_count = 0; printf("css test: memory allocation failure\n"); done = 1; } } } /* The src_count need not include the terminating NULL or EOF */ CSS_ConvertToJS(src, src_count, &dst, &dst_count); printf("%s", dst); XP_FREE(dst); }
void lo_ProcessScriptTag(MWContext *context, lo_DocState *state, PA_Tag *tag, JSObject *obj) { lo_TopState *top_state; pa_DocData *doc_data; XP_Bool type_explicitly_set=FALSE; XP_Bool saw_archive=FALSE; #ifdef DEBUG_ScriptPlugin char * mimebuf = NULL; #endif top_state = state->top_state; doc_data = (pa_DocData *)top_state->doc_data; XP_ASSERT(doc_data != NULL || state->in_relayout || tag->lo_data); if (tag->is_end == FALSE) { PA_Block buff; char *str, *url, *archiveSrc, *id, *codebase; /* Controversial default language value. */ top_state->version = JSVERSION_DEFAULT; if (tag->type == P_STYLE || tag->type == P_LINK) { top_state->in_script = top_state->default_style_script_type; } else { /* in order to get old script behaviour, pretend * that the content-type is explicitly set for all scripts */ type_explicitly_set = TRUE; top_state->in_script = SCRIPT_TYPE_MOCHA; } /* XXX account for HTML comment bytes and "lost" newlines */ if (lo_IsAnyCurrentAncestorSourced(state)) top_state->script_bytes = top_state->layout_bytes; else top_state->script_bytes = top_state->layout_bytes - tag->true_len; if (tag->lo_data != NULL) { top_state->script_bytes += (int32)tag->lo_data - 1; tag->lo_data = NULL; } else if (doc_data != NULL) { top_state->script_bytes += doc_data->comment_bytes; } else { XP_ASSERT(state->in_relayout); } lo_ParseScriptLanguage(context, tag, &top_state->in_script, &top_state->version); #ifdef DEBUG_ScriptPlugin if (top_state->in_script == SCRIPT_TYPE_UNKNOWN) { mimebuf = npl_Script2mimeType(context,tag); if (mimebuf){ if (NPL_FindPluginEnabledForType(mimebuf)){ top_state->in_script = SCRIPT_TYPE_PLUGIN; XP_ASSERT(top_state->mimetype == NULL); StrAllocCopy((char *)top_state->mimetype,mimebuf); XP_FREE(mimebuf); mimebuf = NULL; } else{ XP_FREE(mimebuf); mimebuf = NULL; } } } #endif /* DEBUG_ScriptPlugin */ buff = lo_FetchParamValue(context, tag, PARAM_TYPE); if (buff != NULL) { PA_LOCK(str, char *, buff); if ((XP_STRCASECMP(str, js_content_type) == 0) || (!XP_STRCASECMP(str, "text/javascript"))) { if(tag->type == P_STYLE || tag->type == P_LINK) { top_state->in_script = SCRIPT_TYPE_JSSS; top_state->default_style_script_type = SCRIPT_TYPE_JSSS; } else { top_state->in_script = SCRIPT_TYPE_MOCHA; } type_explicitly_set = TRUE; } else if ((XP_STRCASECMP(str, TEXT_CSS) == 0)) { top_state->in_script = SCRIPT_TYPE_CSS; top_state->default_style_script_type = SCRIPT_TYPE_CSS; type_explicitly_set = TRUE; } else { top_state->in_script = SCRIPT_TYPE_UNKNOWN; top_state->default_style_script_type = SCRIPT_TYPE_UNKNOWN; } PA_UNLOCK(buff); PA_FREE(buff); } /* check for media=screen * don't load the style sheet if there * is a media not equal to screen */ buff = lo_FetchParamValue(context, tag, PARAM_MEDIA); if (buff) { if (strcasecomp((char*)buff, "screen")) { /* set the script type to UNKNOWN * so that it will get thrown away */ top_state->in_script = SCRIPT_TYPE_UNKNOWN; } PA_FREE(buff); } /* * Flush the line buffer so we can start storing Mocha script * source lines in there. */ lo_FlushLineBuffer(context, state); url = archiveSrc = id = codebase = NULL; if (top_state->in_script != SCRIPT_TYPE_NOT) { /* * Check for the archive parameter for known languages. */ buff = lo_FetchParamValue(context, tag, PARAM_ARCHIVE); if (buff != NULL) { saw_archive = TRUE; PA_LOCK(str, char *, buff); url = NET_MakeAbsoluteURL(top_state->base_url, str); PA_UNLOCK(buff); PA_FREE(buff); if (url == NULL) { top_state->out_of_memory = TRUE; return; } } /* * Look for ID attribute. If it's there we have may have * an inline signed script. */ buff = lo_FetchParamValue(context, tag, PARAM_ID); if (buff != NULL) { PA_LOCK(str, char *, buff); StrAllocCopy(id, str); PA_UNLOCK(buff); PA_FREE(buff); if (id == NULL) { top_state->out_of_memory = TRUE; XP_FREEIF(url); return; } } /* * Now look for a SRC="url" attribute for known languages. * If found, synchronously load the url. */ buff = lo_FetchParamValue(context, tag, PARAM_SRC); /* XXX overloaded rv */ if (buff != NULL) { XP_Bool allowFileSrc = FALSE; char *absUrl; PA_LOCK(str, char *, buff); PREF_GetBoolPref(lo_jsAllowFileSrcFromNonFile, &allowFileSrc); absUrl = NET_MakeAbsoluteURL(top_state->base_url, str); if (absUrl == NULL) { top_state->out_of_memory = TRUE; XP_FREEIF(id); } else if (allowFileSrc == FALSE && NET_URL_Type(absUrl) == FILE_TYPE_URL && NET_URL_Type(top_state->url) != FILE_TYPE_URL) { /* * Deny access from http: to file: via SCRIPT SRC=... * XXX silently */ top_state->in_script = SCRIPT_TYPE_UNKNOWN; XP_FREE(absUrl); XP_FREEIF(url); XP_FREEIF(id); } else if (url != NULL) { XP_FREE(absUrl); StrAllocCopy(archiveSrc, str); if (archiveSrc == NULL) { top_state->out_of_memory = TRUE; XP_FREE(url); XP_FREEIF(id); } } else { url = absUrl; } PA_UNLOCK(buff); PA_FREE(buff); if (top_state->out_of_memory) return; /* * If we are doing a <script src=""> mocha script but JS * is turned off just ignore the tag */ if (!LM_CanDoJS(context)) { top_state->in_script = SCRIPT_TYPE_UNKNOWN; XP_FREE(url); XP_FREEIF(id); XP_FREEIF(archiveSrc); return; } } } /* * Set text_divert so we know to accumulate text in line_buf * without interpretation. */ state->text_divert = tag->type; /* * XXX need to stack these to handle blocked SCRIPT tags */ top_state->script_lineno = tag->newline_count + 1; /* if we got here as a result of a LINK tag * check to make sure rel=stylesheet and then * check for an HREF and if one does not exist * fail */ if (tag->type == P_LINK) { char *cbuff = (char*)lo_FetchParamValue(context, tag, PARAM_REL); if (cbuff && !strcasecomp(cbuff, "stylesheet")) { XP_FREE(cbuff); cbuff = (char*)lo_FetchParamValue(context, tag, PARAM_HREF); if (cbuff) { if (saw_archive && url) { archiveSrc = XP_STRDUP(cbuff); } else { XP_FREEIF(url); url = NET_MakeAbsoluteURL(top_state->base_url, cbuff); } } } XP_FREEIF(cbuff); } if (url != NULL || id != NULL || codebase != NULL) { if ((doc_data != NULL) && (state->in_relayout == FALSE) && SCRIPT_EXEC_OK(top_state, state, tag->type, P_SCRIPT)) { ScriptData *data; data = XP_ALLOC(sizeof(ScriptData)); if (data == NULL) { top_state->out_of_memory = TRUE; return; } data->context = context; data->state = state; data->tag = PA_CloneMDLTag(tag); if (data->tag == NULL) { top_state->out_of_memory = TRUE; XP_FREE(data); return; } data->url = url; data->archiveSrc = archiveSrc; data->id = id; if (codebase == NULL) { StrAllocCopy(codebase, top_state->base_url); } data->codebase = codebase; data->buffer = NULL; data->bufferSize = 0; data->version = top_state->version; /* * Only SCRIPT ARCHIVE= ID= without SRC= is an inline signed * script -- if there is a SRC= attribute, archiveSrc will be * non-null. */ data->inlineSigned = (JSBool) (url != NULL && archiveSrc == NULL && id != NULL); /* Reset version accumulator */ top_state->version = JSVERSION_UNKNOWN; XP_ASSERT (tag->type == P_SCRIPT || tag->type == P_STYLE || tag->type == P_LINK); /* * Out-of-line included (by src=) or inline signed script. * Save continuatation data on top_state. If it's signed, * we'll verify the signature once we see </script> and * have the inline script to verify. */ top_state->scriptData = data; } else { XP_FREE(url); XP_FREEIF(id); XP_FREEIF(archiveSrc); } } } else { /* * We are in the </script> tag now... */ size_t line_buf_len; intn script_type; char *scope_to=NULL; char *untransformed = NULL; script_type = top_state->in_script; top_state->in_script = SCRIPT_TYPE_NOT; /* guard against superfluous end tags */ if (script_type == SCRIPT_TYPE_NOT) goto end_tag_out; /* convert from CSS to JavaScript here */ if (tag->type != P_LINK && script_type == SCRIPT_TYPE_CSS) { char *new_buffer; int32 new_buffer_length; CSS_ConvertToJS((char *)state->line_buf, state->line_buf_len, &new_buffer, &new_buffer_length); if (!new_buffer) { /* css translator error, unblock layout and return */ state->text_divert = P_UNKNOWN; state->line_buf_len = 0; /* clear script text */ goto end_tag_out; } untransformed = (char *) state->line_buf; state->line_buf = (PA_Block) new_buffer; state->line_buf_len = new_buffer_length; state->line_buf_size = new_buffer_length; if (state->line_buf_len) state->line_buf_len--; /* hack: subtract one to remove final \n */ script_type = SCRIPT_TYPE_JSSS; } if (tag->type == P_STYLE) { /* mocha scoped to document == jsss */ scope_to = "document"; } /* * Reset these before potentially recursing indirectly through * the document.write() built-in function, which writes to the * very same doc_data->parser_stream that this <SCRIPT> tag * came in on. */ state->text_divert = P_UNKNOWN; line_buf_len = state->line_buf_len; state->line_buf_len = 0; if (script_type != SCRIPT_TYPE_UNKNOWN && script_type != SCRIPT_TYPE_NOT) { /* * If mocha is disabled or can't be done in this context we * are going to just ignore the buffer contents */ if (!LM_CanDoJS(context)) { top_state->in_script = SCRIPT_TYPE_UNKNOWN; goto end_tag_out; } if ((doc_data != NULL) && (state->in_relayout == FALSE) && SCRIPT_EXEC_OK(top_state, state, tag->type, P_SCRIPT)) { /* * First off, make sure layout is blocking on us */ if (lo_create_script_blockage(context, state, tag->type == P_SCRIPT ? LO_SCRIPT : LO_UNKNOWN)) { ScriptData *data; /* * Extreme hackery. Hideous and shameful. See the comment * in lo_BlockScriptTag before similar is_end/overflow code * and commence vomiting. */ lo_BlockScriptTag(context, state, NULL); if (tag->is_end == (PRPackedBool)1) { PA_PushOverflow(doc_data); doc_data->overflow_depth ++; } /* * Set the document.write tag insertion point. */ top_state->input_write_point[top_state->input_write_level] = &top_state->tags; data = top_state->scriptData; top_state->scriptData = NULL; if (data && data->url) { /* * Three cases: * 1. SCRIPT SRC=: url non-null * 2. SCRIPT ARCHIVE= SRC=: url, archiveSrc non-null * 3. SCRIPT ARCHIVE= ID=: url, id non-null * In the last case, we copy the inline script into * data's buffer and let lo_script_archive_exit_fn do * the eval. We use an inlineSigned flag to avoid a * bunch of (url != NULL && archiveSrc == NULL && id * != NULL) tests. */ if (data->inlineSigned) { StrAllocCopy(data->buffer, (char *) state->line_buf); data->bufferSize = line_buf_len; } lo_GetScriptFromURL(data, script_type); } else { JSPrincipals *principals = NULL; ETEvalStuff * stuff; if (data) { principals = LM_NewJSPrincipals(NULL, data->id, data->codebase); if (untransformed && !LM_SetUntransformedSource(principals, untransformed, (char *) state->line_buf)) { top_state->out_of_memory = TRUE; } lo_DestroyScriptData(data); } /* * send the buffer off to be evaluated */ #ifdef DEBUG_ScriptPlugin if (script_type == SCRIPT_TYPE_PLUGIN) { XP_ASSERT(mimebuf == NULL); npl_ScriptPlugin(context, state, tag, line_buf_len,top_state->mimetype); lo_unblock_script_tag(context, TRUE); } else #endif /* DEBUG_ScriptPlugin */ stuff = (ETEvalStuff *) XP_NEW_ZAP(ETEvalStuff); if (!stuff) goto end_tag_out; stuff->len = line_buf_len; stuff->line_no = top_state->script_lineno; if (scope_to) stuff->scope_to = XP_STRDUP(scope_to); else stuff->scope_to = NULL; stuff->want_result = JS_FALSE; stuff->data = context; stuff->version = top_state->version; stuff->principals = principals; ET_EvaluateScript(context, (char *) state->line_buf, stuff, lo_ScriptEvalExitFn); } /* Reset version accumulator */ top_state->version = JSVERSION_UNKNOWN; } } } end_tag_out: /* * If we got a </SCRIPT> and still have scriptData set here, it must * be left over from an error case above, so we free it. */ if (top_state->scriptData) { XP_ASSERT(!top_state->layout_blocking_element); lo_DestroyScriptData(top_state->scriptData); top_state->scriptData = NULL; } XP_FREEIF(untransformed); } }
/* evaluate the buffer encompassed by the style attribute on any tag. * this will be JSS or CSS * * Returns TRUE if it needs to block layout * Returns FALSE if not. */ XP_Bool lo_ProcessStyleAttribute(MWContext *context, lo_DocState *state, PA_Tag *tag, char *script_buff) { lo_TopState *top_state; char *scope_to = NULL; int32 script_buff_len; char *new_id; XP_Bool in_double_quote=FALSE, in_single_quote=FALSE; char *ptr, *end; ETEvalStuff * stuff; if (!state) { XP_FREEIF(script_buff); return FALSE; } if (!script_buff) return FALSE; /* @@@ A bit of a hack. * Get rid of the style attribute in the tag->data so that we don't * go circular * * get rid of STYLE by rewriting it as SYTLE so that the parser * ignores it :) */ for (ptr=(char*)tag->data, end = ptr+tag->data_len; ptr < end; ptr++) { if (*ptr == '"') { in_double_quote = !in_double_quote; } else if (*ptr == '\'') { in_single_quote = !in_single_quote; } else if (!in_single_quote && !in_double_quote && !strncasecomp(ptr, PARAM_STYLE, sizeof(PARAM_STYLE)-1)) { *ptr = 'T'; /* ttyle NOT style */ break; } } script_buff_len = XP_STRLEN(script_buff); top_state = state->top_state; /* get the tag ID if it has one */ new_id = (char *)lo_FetchParamValue(context, tag, PARAM_ID); if (!new_id) new_id = PR_smprintf(NSIMPLICITID"%ld", top_state->tag_count); if (!new_id) return FALSE; if (top_state->default_style_script_type == SCRIPT_TYPE_JSSS || top_state->default_style_script_type == SCRIPT_TYPE_MOCHA) { StrAllocCopy(scope_to, "document.ids."); StrAllocCat(scope_to, new_id); if (!scope_to) { XP_FREE(new_id); return(FALSE); } } else if (top_state->default_style_script_type == SCRIPT_TYPE_CSS) { char *new_jss_buff; int32 new_jss_buff_len; char *new_css_buff; int32 new_css_buff_len; /* scope the css to the ns implicit ID */ new_css_buff = PR_smprintf("#%s { %s }", new_id, script_buff); XP_FREE(script_buff); if (!new_css_buff) { XP_FREE(new_id); return FALSE; } new_css_buff_len = XP_STRLEN(new_css_buff); /* convert to JSS */ CSS_ConvertToJS(new_css_buff, new_css_buff_len, &new_jss_buff, &new_jss_buff_len); XP_FREE(new_css_buff); if (!new_jss_buff) { XP_FREE(new_id); return FALSE; } script_buff = new_jss_buff; script_buff_len = new_jss_buff_len; } else { /* unknown script type, punt */ XP_FREE(script_buff); XP_FREE(new_id); return FALSE; } /* not needed anymore */ XP_FREE(new_id); stuff = (ETEvalStuff *) XP_NEW_ZAP(ETEvalStuff); if (!stuff) { /* what do we free here? */ XP_FREE(new_id); return FALSE; } if (lo_CloneTagAndBlockLayout(context, state, tag)) { tag->type = P_UNKNOWN; stuff->len = XP_STRLEN(script_buff); stuff->line_no = top_state->script_lineno; stuff->scope_to = scope_to; stuff->want_result = JS_FALSE; stuff->data = context; stuff->version = top_state->version; stuff->principals = NULL; ET_EvaluateScript(context, script_buff, stuff, lo_StyleEvalExitFn); /* don't free scope_to, ET_EvaluateScript has taken possession */ XP_FREE(script_buff); return TRUE; } XP_FREEIF(scope_to); XP_FREE(script_buff); return FALSE; }