📄 jsint.c
字号:
/* jsint.c * (c) 2002 Mikulas Patocka (Vrxni Ideolog), Petr 'Brain' Kulhavy * This file is a part of the Links program, relased under GPL. *//* * Ve vsech upcallech plati, ze pokud dostanu ID nejakeho objektu, tak * javascript ma k tomu objektu pristupova prava. Jinymi slovy pristupova prava * se testuji v upcallech jen, aby se neco neproneslo vratnici ven. Dovnitr se * muze donaset vsechno, co si javascript donese, na to ma prava. * * Navic vsechny upcally dostanou pointer na f_data_c, kde bezi javascript, * takze se bude moci testovat, zda javascript nesaha na f_data_c, ke kteremu * nema pristupova prava. * * Brain *//* Uctovani pameti: * js_mem_alloc/js_mem_free se bude pouzivat na struktury fax_me_tender * dale se bude pouzivat take ve funkcich pro praci s cookies, protoze string * cookies v javascript_context se tez alokuje pomoci js_mem_alloc/js_mem_free. */ /* Retezce: vsechny retezce v ramci javascriptu jsou predavany v kodovani f_data->cp (tedy tak, jak prisly v dokumentu ze site) */#include "links.h" tcount jsint_execute_seq = 0;#ifdef JS#include "struct.h"#include "ipret.h"#include "builtin_keys.h"/*vypisuje to: jaky kod byl zarazen do fronty. jaky kod byl predan interpretu do js_execute_code. jaky kod byl vykonan a ukoncen intepretem jsint_done_execution#define TRACE_EXECUTE*/struct js_request { struct js_request *next; struct js_request *prev; int onclick_submit; /* >=0 (znamena cislo formulare) pokud tohle je request onclick handleru u submit tlacitka nebo onsubmit handleru */ int onsubmit; /* dtto pro submit handler */ struct event ev; /* event, ktery se ma poslat pri uspechu */ int write_pos; /* document.write position from END of document. -1 if document.write cannot be used */ int wrote; /* this request called document.write */ int len; tcount seq; unsigned char code[1];};/* set_cookies bude parsovat takhle: * +....=............;...............................+ <- tohle je strinzik * ^ ^ * najdu 1. rovnase a za nim 1. strednik, najdu nasledujici rovnase a * nasledujici strednik, pokud to bude platne (&'='<&';') a 2. jmeno bude * "expires", tak to je furt jedna cookie -> poslu Mikulasovi. * * kdyz ne, tak je to jina susenka a poslu to 1. Mikulasovi * * pokud najdu ';' a za nim whitespace, za kterym neni rovnase, tak od toho * stredniku je to garbaz, kterou vratim do strinziku (fd->js->ctx->cookies) *//* sets all cookies in fd>js->ctx->cookies *//* final_flush means, that set_cookies was called from jsint_done_execution *//* JESTLI V TYHLE FUNKCI BUDE NEJAKA BUGA, tak za to muze PerM, Clock a pan GNU, * ktery tady kolem rusili, ze jsem se nemohl soustredit. Takze se s * pripadnejma reklamacema obratte na ne! * * Brain *//* prototypes */void jsint_send_event(struct f_data_c *fd, struct event *ev);int jsint_create(struct f_data_c *);void jsint_done_execution(struct f_data_c *);int jsint_can_access(struct f_data_c *, struct f_data_c *);struct f_data_c *jsint_find_recursive(struct f_data_c *, long); /* line 89 */void *jsint_find_object(struct f_data_c *, long);long *add_id(long *, int *, long );long *add_fd_id(long *, int *, long, long, unsigned char *);void send_vodevri_v_novym_vokne(struct terminal *, void (*)(struct terminal *, unsigned char *, unsigned char *), struct session *);void add_all_recursive_in_fd(long **, int *, struct f_data_c *, struct f_data_c *);void jsint_set_cookies(struct f_data_c *fd, int final_flush){ unsigned char *str; unsigned char *next; unsigned char *eq1, *semic1, *eq2, *semic2; if(!(fd->js)||!(fd->js->ctx))internal("jsint_set_cookies called with NULL context.\n"); if (!(fd->js->ctx->cookies)||!(fd->rq))return; /* cookies string is empty, nothing to set */ str=fd->js->ctx->cookies; a_znova: eq1=strchr(str,'='); semic1=strchr(str,';'); if (!*str||(!final_flush&&!semic1)) /* na konci neni strednik a skript jeste bezi, takze to musime vratit do stringu a vypadnout */ { unsigned char *bla=NULL; if (*str)bla=stracpy1(str); js_mem_free(fd->js->ctx->cookies); fd->js->ctx->cookies=bla; return; } /* ted se v str bud vyskytuje strednik, nebo skript uz skoncil */ if (semic1&&eq1>semic1) /* '=' je za ';' takze to pred strednikem a strednik skipnem */ { str=semic1+1; goto a_znova; } next=semic1?semic1+1:str+strlen(str); if (!eq1) /* neni tam '=', takze to preskocime */ { str=next; goto a_znova; } /* ted by to mela bejt regulerni susenka */ next_par: eq2=NULL,semic2=NULL; if (semic1!=NULL) { eq2=strchr(semic1+1,'='); semic2=strchr(semic1+1,';'); } if (eq2&&semic1&&(final_flush||semic2)) { unsigned char *p=strstr(semic1+1,"expires"); if (!p)p=strstr(semic1+1,"Expires"); if (!p)p=strstr(semic1+1,"EXPIRES"); if (!p)p=strstr(semic1+1,"domain"); if (!p)p=strstr(semic1+1,"Domain"); if (!p)p=strstr(semic1+1,"DOMAIN"); if (!p)p=strstr(semic1+1,"path"); if (!p)p=strstr(semic1+1,"Path"); if (!p)p=strstr(semic1+1,"PATH"); if (!p)p=strstr(semic1+1,"comment"); if (!p)p=strstr(semic1+1,"Comment"); if (!p)p=strstr(semic1+1,"COMMENT"); if (!p)p=strstr(semic1+1,"max-age"); if (!p)p=strstr(semic1+1,"Max-age"); if (!p)p=strstr(semic1+1,"Max-Age"); if (!p)p=strstr(semic1+1,"MAX-AGE"); if (!p)p=strstr(semic1+1,"version"); if (!p)p=strstr(semic1+1,"Version"); if (!p)p=strstr(semic1+1,"VERSION"); if (p&&p>semic1&&p<eq2) /* za 1. prirazenim nasleduje "expires=", takze to je porad jedna susenka */ { next=semic2?semic2+1:str+strlen(str); semic1=semic2; goto next_par; } } if (*next)next[-1]=0; for (;*str&&WHITECHAR(*str);str++); /* skip whitechars */ /*debug("set_cookie: \"%s\"", str);*/ set_cookie(fd->ses->term, fd->rq->url, str); str=next; goto a_znova;}int jsint_object_type(long to_je_on_Padre){ return to_je_on_Padre&JS_OBJ_MASK;}int jsint_create(struct f_data_c *fd){ struct js_state *js; if (fd->js) internal("javascript state present"); js = mem_calloc(sizeof(struct js_state)); if (!(js->ctx = js_create_context(fd, ((fd->id)<<JS_OBJ_MASK_SIZE)|JS_OBJ_T_DOCUMENT))) { mem_free(js); return 1; } init_list(js->queue); fd->js = js; return 0;}void jsint_destroy(struct f_data_c *fd){ struct js_state *js = fd->js; fd->script_t = 0; if (!js) return; fd->js = NULL; pr(js_destroy_context(js->ctx)) return; if (js->src) mem_free(js->src); if (js->active) mem_free(js->active); js_zaflaknuto_pameti-=js->newdata; free_list(js->queue); mem_free(js);}/* for <a href="javascript:..."> */void javascript_func(struct session *ses, unsigned char *hlavne_ze_je_vecirek){ unsigned char *code=get_url_data(hlavne_ze_je_vecirek); jsint_execute_code(current_frame(ses),code,strlen(code),-1,-1,-1, NULL);}void jsint_send_event(struct f_data_c *fd, struct event *ev){ if (!ev || !ev->b) return; send_event(fd->ses, ev);}/* executes or queues javascript code in frame: write_pos is number of bytes from the position where document.write should write to the end of document write_pos == -1 if it is not from <SCRIPT> statement and cannot use document.write*//* data je cislo formulare pro onclick submit handler, jinak se nepouziva *//* ev je udalost, ktera se ma znovu poslat, pokud bylo vraceno true */void jsint_execute_code(struct f_data_c *fd, unsigned char *code, int len, int write_pos, int onclick_submit, int onsubmit, struct event *ev){ struct js_request *r, *q; for (;code&&len&&*code&&((*code)==' '||(*code)==9||(*code)==13||(*code)==10);code++,len--); /* FUJ !!!! if (!strncasecmp(code,"javascript:",strlen("javascript:")))code+=strlen("javascript:"); */ if (len >= 11 && !casecmp(code, "javascript:", 11)) code += 11, len -= 11; if (!js_enable) { jsint_send_event(fd, ev); return; }#ifdef TRACE_EXECUTE fprintf(stderr, "Submitted: ^^%.*s^^\n", len, code);#endif if (!fd->js && jsint_create(fd)) { jsint_send_event(fd, ev); return; } if ((unsigned)len > MAXINT - sizeof(struct js_request)) overalloc(); r = mem_calloc(sizeof(struct js_request) + len); r->seq = jsint_execute_seq++; r->write_pos = write_pos; r->len = len; r->onclick_submit = onclick_submit; r->onsubmit = onsubmit; memcpy(r->code, code, len); if (ev) memcpy(&r->ev, ev, sizeof(struct event)); if (write_pos == -1) { struct list_head *l = (struct list_head *)fd->js->queue.prev; add_to_list(*l, r); } else { /* add it beyond all <SCRIPT> requests but before non-<SCRIPT> ones */ foreach(q, fd->js->queue) if (q->write_pos == -1) break; q = q->prev; add_at_pos(q, r); } jsint_run_queue(fd);}void jsint_done_execution(struct f_data_c *fd){ struct js_request *r, *to_exec; struct js_state *js = fd->js; struct event ev = { 0, 0, 0, 0 }; if (!js) { internal("no js in frame"); return; } if (!js->active) { internal("jsint_done_execution: completion function called on inactive js"); return; }#ifdef TRACE_EXECUTE fprintf(stderr, "Done: ^^%.*s^^\n", js->active->len, js->active->code);#endif /* accept all cookies set by the script */ jsint_set_cookies(fd,1); /* js->active obsahuje request prave dobehnuteho skriptu */ /* dobehl onclick_handler a nezaplatil (vratil false), budou se dit veci */ if (js->active->ev.b && js->ctx->zaplatim) memcpy(&ev, &js->active->ev, sizeof(struct event)); if (js->active->onclick_submit >=0 && !js->ctx->zaplatim) { /* pokud je handler od stejneho formulare, jako je defered, tak odlozeny skok znicime a zlikvidujem prislusny onsubmit handler z fronty */ if (js->active->onclick_submit == fd->ses->defered_data) { foreach (r,js->queue) /* to je onsubmit od naseho formulare, tak ho smazem */ if (r->onsubmit == js->active->onclick_submit) { del_from_list(r); mem_free(r); break; /* zadny dalsi onsubmit tohoto formulare uz nebude */ } ses_destroy_defered_jump(fd->ses); } } if (js->active->write_pos == -1) mem_free(js->active), js->active = NULL; else { r = js->active; js->active = NULL; if (r->wrote) js->wrote = 1; jsint_scan_script_tags(fd); if (!f_is_finished(fd->f_data)) { fd->done = 0; fd->parsed_done = 0; } if (js->wrote && fd->script_t == -1) { fd->done = 0; fd->parsed_done = 0; fd_loaded(NULL, fd); js->wrote = 0; } mem_free(r); } to_exec = js->active; if (!to_exec && !list_empty(fd->js->queue)) to_exec = fd->js->queue.next; if (fd->ses->defered_url && (!to_exec || (to_exec->seq > fd->ses->defered_seq && to_exec->write_pos == -1))) { unsigned char *url, *target; url=stracpy(fd->ses->defered_url); target=stracpy(fd->ses->defered_url); goto_url_f(fd->ses,NULL,url,target,fd->ses->defered_target_base,fd->ses->defered_data,0,0,0); mem_free(url); mem_free(target); } else jsint_run_queue(fd); jsint_send_event(fd, &ev);}void jsint_run_queue(struct f_data_c *fd){ struct js_request *r; struct js_state *js = fd->js; if ((!fd->done && fd->f_data) || !js || js->active || list_empty(js->queue)) return; r = js->queue.next; del_from_list(r); js->active = r;#ifdef TRACE_EXECUTE fprintf(stderr, "Executing: ^^%.*s^^\n", r->len, r->code);#endif pr(js_execute_code(js->ctx, r->code, r->len, (void (*)(void *))jsint_done_execution)) {};}/* returns: 1 - source is modified by document.write 0 - original source*/int jsint_get_source(struct f_data_c *fd, unsigned char **start, unsigned char **end){ struct js_state *js = fd->js; if (!js || !js->src) return 0; if (start) *start = js->src; if (end) *end = js->src + js->srclen; return 1;}/* * tests if script running in frame "running" can access document in frame "accessed" * 0=no permission, 1=permission OK */int jsint_can_access(struct f_data_c *running, struct f_data_c *accessed){ int a; unsigned char *h1, *h2; if (!running || !accessed || !running->rq || !accessed->rq) return 0; h1 = get_host_name(running->rq->url); h2 = get_host_name(accessed->rq->url); a = !strcasecmp(h1, h2); mem_free(h1); mem_free(h2); return a;}/* doc_id is real document id, whithout any type *//* fd must be a valid pointer */struct f_data_c *jsint_find_recursive(struct f_data_c *fd, long doc_id){ struct f_data_c *sub, *fdd; if (fd->id == doc_id) return fd; foreach(sub, fd->subframes) { if ((fdd = jsint_find_recursive(sub, doc_id))) return fdd; } return NULL;}/* * This function finds document that has given ID */struct f_data_c *jsint_find_document(long doc_id){ struct f_data_c *fd; struct session *ses; int type=jsint_object_type(doc_id); if (type!=JS_OBJ_T_DOCUMENT&&type!=JS_OBJ_T_FRAME) {unsigned char txt[256]; snprintf(txt,256,"jsint_find_document called with type=%d\n",type);internal(txt);} doc_id>>=JS_OBJ_MASK_SIZE; foreach(ses, sessions) if ((fd = jsint_find_recursive(ses->screen, doc_id))) return fd; return NULL;}void jsint_destroy_document_description(struct f_data *f){ struct js_document_description *jsd; if (!f)return; jsd= f->js_doc; if (!jsd) return; f->js_doc = NULL; /* Pro Martina: vsecky polozky vyrobene vyse se tady zase musi uvolnit (jak kurtizana v rimskejch laznich) */ /* -------------- */ mem_free(jsd);}/* Document has just loaded. Scan for <SCRIPT> tags and execute each of them */void jsint_scan_script_tags(struct f_data_c *fd){ unsigned char *name, *attr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -