// finds disc item on disk (in work or cache), allocates and fills out memory struct for it disk_item * find_disk_item (const char * id, const boolean cache_item) { char path [EUCA_MAX_PATH]; if (cache_item) { snprintf (path, EUCA_MAX_PATH, "%s/%s/content", get_cache_dir(), id); } else { snprintf (path, EUCA_MAX_PATH, "%s/%s", get_work_dir(), id); } if (cache_item) { scan_cache (); // rebuilds cache state in memory based on disk return find_in_cache (path); } struct stat mystat; if (stat (path, &mystat)<0) { if (errno!=ENOENT) { // file not found logprintfl (EUCAERROR, "error: could not stat '%s'\n", path); } return NULL; } return alloc_disk_item (id, mystat.st_size, mystat.st_size, cache_item); }
/* * Unpin the given files list in the file cache * @params file_cache type file_cache, list of files to be pinned and its count num_files * @return void */ void file_cache_unpin_files(file_cache *fct, const char **files, int num_files) { // for each file in files // if file exists in cache then // a) decrease pin count // b) write to disk if dirty and pin count is 0 // else undefined behaviour size_t idx; for (idx = 0; idx < num_files; idx++) { // lockdown to prevent duplicate removals pthread_mutex_lock(&(fct->mutex)); // check if file exists in cache file *loc = find_in_cache(fct, files[idx]); // file found and it has been pinned before if (NULL != loc && loc->pins > 0) { (loc->pins)--; if (true == loc->dirty && 0 == loc->pins) { write_to_disk(loc); loc->dirty = false; } if (0 == loc->pins) { // also decrement the actual cached files count since this is technically a clean entry which can be reused for caching other files fct->actual_size--; } } pthread_mutex_unlock(&(fct->mutex)); } }
/* if the entry doesn't exist then create it and return it. otherwise just return it */ cache_entry* find_or_create_cache_entry(int tname) { cache_entry * entry; if((entry=find_in_cache(tname))) return entry; else return cache_create_entry(tname); }
/* * Pin given files of size num_files in the file_cache file_cache *fct * @params file_cache type file_cache, list of file names, number of files * @return void */ void file_cache_pin_files(file_cache *fct, const char **files, int num_files) { // for each file in files // if file exists in cache then increment pin count // else try to find a spot to fill the cache entry with file size_t idx; for (idx = 0; idx < num_files; idx++) { // check if file exists in cache, lock down to prevent duplicate additions pthread_mutex_lock(&(fct->mutex)); file *loc = find_in_cache(fct, files[idx]); // if file already present, then inc #pins if (NULL != loc) { (loc->pins)++; pthread_mutex_unlock(&(fct->mutex)); continue; } // else find a spot to fit the file int spot = findspot_in_cache(fct); // no spot found so continue to see if any other files have existing // pins that can be increased, else dont do anything if (spot == -1) { pthread_mutex_unlock(&(fct->mutex)); continue; } // previously something exists, need to write to disk if dirty and clear if (NULL != fct->file_struct[spot]) { if (true == fct->file_struct[spot]->dirty) { write_to_disk(fct->file_struct[spot]); } // clean the entry in cache free(fct->file_struct[idx]->content); fct->file_struct[idx]->content = NULL; // decrement actual cache size fct->actual_size--; // free that entry free(fct->file_struct[idx]); fct->file_struct[idx] = NULL; } // Yep! this can be improved by simply overwriting the old memory // allocate space fct->file_struct[idx] = malloc(sizeof(file)); // initialize name, pins, dirty flag and read contents fct->file_struct[idx]->file_name = files[idx]; fct->file_struct[idx]->pins = 1; fct->file_struct[idx]->dirty = false; // read contents read_from_disk(fct->file_struct[idx]); // increment cache size fct->actual_size++; pthread_mutex_unlock(&(fct->mutex)); } }
GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) { GdiFont *ret; int can_use_bitmap; LOGFONTW lf; FMAT2 dcmat; if((ret = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != ((void *)0)) return ret; return alloc_font(); }
/* refresh the cache for a specific quad */ void cache_refresh_entry(int tname) { cache_entry * entry; entry = find_in_cache(tname); /* opengl initialization code */ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, entry->tname); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, (void*)(entry->tdata)); glDisable(GL_TEXTURE_2D); }
/* * Get read only memory for the specified file in the file cache * @params file_cache type file_cache, the file to read * @return return read only memory or NULL if the file does not exist */ const char *file_cache_file_data(file_cache *fct, const char *file_name) { // Need a lock on cache because some other thread might try to clear the cache entry before we can even return the data pthread_mutex_lock(&(fct->mutex)); file *loc = find_in_cache(fct, file_name); const char *data; // found file and it has been pinned if (NULL != loc && loc->pins > 0) { data = (const char*)loc->content; } else { // undefined behavior data = NULL; } pthread_mutex_unlock(&(fct->mutex)); return data; }
/* Checks protocols headers for a suitable filename */ static unsigned char * get_content_filename(struct uri *uri, struct cache_entry *cached) { unsigned char *filename, *pos; if (!cached) cached = find_in_cache(uri); if (!cached || !cached->head) return NULL; pos = parse_header(cached->head, "Content-Disposition", NULL); if (!pos) return NULL; parse_header_param(pos, "filename", &filename, 1); mem_free(pos); if (!filename) return NULL; /* Remove start and ending quotes. */ if (filename[0] == '"') { int len = strlen(filename); if (len > 1 && filename[len - 1] == '"') { filename[len - 1] = 0; memmove(filename, filename + 1, len); } /* It was an empty quotation: "" */ if (!filename[1]) { mem_free(filename); return NULL; } } /* We don't want to add any directories from the path so make sure we * only add the filename. */ pos = get_filename_position(filename); if (!*pos) { mem_free(filename); return NULL; } if (pos > filename) memmove(filename, pos, strlen(pos) + 1); return filename; }
FileHolder Database_ResourceStorage::get_file_path(const std::string& key) { int ind = find_in_cache(key); if(ind >= 0) return FileCache[ind].file; guint32 entry_offset, entry_size; if(!ridx_file->lookup(key.c_str(), entry_offset, entry_size)) return FileHolder(); // key not found gchar *data = dict->GetData(entry_offset, entry_size); if(!data) return FileHolder(); std::string name_pattern; // in file name encoding if(!utf8_to_file_name(key, name_pattern)) return FileHolder(); std::string::size_type pos = name_pattern.find_last_of("."DB_DIR_SEPARATOR_S); if(pos != std::string::npos) { if(name_pattern[pos] == '.') name_pattern = name_pattern.substr(pos); else name_pattern.clear(); } else name_pattern.clear(); gint fd; FileHolder file(open_temp_file(name_pattern, fd)); if(file.empty()) return file; ssize_t write_size; #ifdef _WIN32 write_size = _write(fd, data+sizeof(guint32), entry_size); if (write_size == -1) { g_print("write error!\n"); } _close(fd); #else write_size = write(fd, data+sizeof(guint32), entry_size); if (write_size == -1) { g_print("write error!\n"); } close(fd); #endif ind = put_in_cache(key, file); return FileCache[ind].file; }
static ColorData* new_color (gboolean force_new) { int i = -1; ColorData *cd; /* XXX Try to find an equal one and return it */ if (!force_new) { cd = find_in_cache (&i); if (cd) return cd; } cd = alloc_color_data (); cd->api_index = -1; dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array); /* if i >= 0, it means we prepared a given slot to receive the new color */ if (i >= 0) merge_cache [i][0].color = cd; return cd; }
void show_http_error_document( struct session *ses, void *data ) { struct terminal *term = ses->tab->term; struct cache_entry *cached; struct cache_entry *cache = find_in_cache( &((int*)data)[1] ); unsigned char *str; cached = find_in_cache( &((int*)data)[1] ); if ( cached || get_cache_entry( &((int*)data)[1] ) ) { if ( 0 != 72 ) { if ( term && current_charset != get_terminal_codepage( term ) ) { bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) ); current_charset = get_terminal_codepage( term ); } gettext( "HTTP error %03d" ); } if ( init_string( ebp_32 ) == 0 ) { if ( asprintfa( (char*)gettext( "HTTP error %03d" ) ) ) mem_free( (void*)asprintfa( (char*)gettext( "HTTP error %03d" ) ) ); } else { add_format_to_string( (struct string*)asprintfa( (char*)gettext( "HTTP error %03d" ) ), asprintfa( (char*)gettext( "HTTP error %03d" ) ) ); if ( 0 != 32 ) { if ( term && current_charset != get_terminal_codepage( term ) ) { bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) ); current_charset = get_terminal_codepage( term ); } gettext( " An error occurred on the server while fetching the document you\n requested. However, the server did not send back any explanation of what\n happened, so it is unknown what went wrong. Please contact the web\n server administrator about this, if you believe that this error should\n not occur since it is not a nice behaviour from the web server at all\n and indicates that there is some much deeper problem with the web server\n software.\n" ); } add_format_to_string( ebp_32, gettext( " An error occurred on the server while fetching the document you\n requested. However, the server did not send back any explanation of what\n happened, so it is unknown what went wrong. Please contact the web\n server administrator about this, if you believe that this error should\n not occur since it is not a nice behaviour from the web server at all\n and indicates that there is some much deeper problem with the web server\n software.\n" ) ); add_format_to_string( " </p>\n <p>\n URI: <a href=\"%s\">%s</a>\n", *(int*)(((int*)data)[1]) ); add_format_to_string( ebp_32, " </p>\n <hr />\n </body>\n</html>\n" ); if ( asprintfa( (char*)gettext( "HTTP error %03d" ) ) ) mem_free( (void*)asprintfa( (char*)gettext( "HTTP error %03d" ) ) ); str[0] = ebp_32; if ( ebp_32 ) { int gettext_codepage = get_terminal_codepage( term ); if ( cached ) delete_entry_content( &cache[0] ); if ( cache->content_type ) mem_free( (void*)cache->content_type ); cache->content_type = stracpy( "text/html" ); if ( cache->head ) mem_free( (void*)cache->head ); cache->head = straconcat( "\r\nContent-Type: text/html; charset=" ); add_fragment( &cache[0], (long long)0, &str[0] ); mem_free( &str[0] ); draw_formatted( ses, 1 ); } } } done_uri( &((int*)data)[1] ); mem_free( &((int*)data)[0] ); return; }
void http_send_header(struct connection *c) { static unsigned char *accept_charset = NULL; struct http_connection_info *info; int http10 = http_bugs.http10; struct cache_entry *e = NULL; unsigned char *hdr; unsigned char *h, *u; int l = 0; int la; unsigned char *post; unsigned char *host; find_in_cache(c->url, &c->cache); host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url); set_timeout(c); info = mem_calloc(sizeof(struct http_connection_info)); c->info = info; if ((h = get_host_name(host))) { info->bl_flags = get_blacklist_flags(h); mem_free(h); } if (info->bl_flags & BL_HTTP10) http10 = 1; info->http10 = http10; post = strchr(host, POST_CHAR); if (post) post++; hdr = init_str(); if (!post) add_to_str(&hdr, &l, "GET "); else { add_to_str(&hdr, &l, "POST "); c->unrestartable = 2; } if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "/"); if (!(u = get_url_data(c->url))) { mem_free(hdr); setcstate(c, S_BAD_URL); http_end_request(c, 0); return; } if (post && post < u) { mem_free(hdr); setcstate(c, S_BAD_URL); http_end_request(c, 0); return; } add_url_to_str(&hdr, &l, u); if (!http10) add_to_str(&hdr, &l, " HTTP/1.1\r\n"); else add_to_str(&hdr, &l, " HTTP/1.0\r\n"); if ((h = get_host_name(host))) { add_to_str(&hdr, &l, "Host: "); add_to_str(&hdr, &l, h); mem_free(h); if ((h = get_port_str(host))) { add_to_str(&hdr, &l, ":"); add_to_str(&hdr, &l, h); mem_free(h); } add_to_str(&hdr, &l, "\r\n"); } add_to_str(&hdr, &l, "User-Agent: "); if (!(*http_bugs.fake_useragent)) { add_to_str(&hdr, &l, "Links (" VERSION_STRING "; "); add_to_str(&hdr, &l, system_name); if (!F && !list_empty(terminals)) { struct terminal *t = terminals.prev; if (!t->spec->braille) { add_to_str(&hdr, &l, "; "); add_num_to_str(&hdr, &l, t->x); add_to_str(&hdr, &l, "x"); add_num_to_str(&hdr, &l, t->y); } else { add_to_str(&hdr, &l, "; braille"); } } #ifdef G if (F && drv) { add_to_str(&hdr, &l, "; "); add_to_str(&hdr, &l, drv->name); } #endif add_to_str(&hdr, &l, ")\r\n"); } else { add_to_str(&hdr, &l, http_bugs.fake_useragent); add_to_str(&hdr, &l, "\r\n"); } switch (http_bugs.referer) { case REFERER_FAKE: add_to_str(&hdr, &l, "Referer: "); add_to_str(&hdr, &l, http_bugs.fake_referer); add_to_str(&hdr, &l, "\r\n"); break; case REFERER_SAME_URL: add_to_str(&hdr, &l, "Referer: "); add_url_to_str(&hdr, &l, host); add_to_str(&hdr, &l, "\r\n"); break; case REFERER_REAL_SAME_SERVER: { unsigned char *h, *j; int brk = 1; if ((h = get_host_name(host))) { if ((j = get_host_name(c->prev_url))) { if (!strcasecmp(h, j)) brk = 0; mem_free(j); } mem_free(h); } if (brk) break; /* fall through */ } case REFERER_REAL: { unsigned char *ref; unsigned char *user, *ins; int ulen; if (!(c->prev_url)) break; /* no referrer */ ref = stracpy(c->prev_url); if (!parse_url(ref, NULL, &user, &ulen, NULL, NULL, &ins, NULL, NULL, NULL, NULL, NULL, NULL) && ulen && ins) { memmove(user, ins, strlen(ins) + 1); } add_to_str(&hdr, &l, "Referer: "); add_url_to_str(&hdr, &l, ref); add_to_str(&hdr, &l, "\r\n"); mem_free(ref); } break; } add_to_str(&hdr, &l, "Accept: */*\r\n"); #if defined(HAVE_ZLIB) || defined(HAVE_BZIP2) if (!http_bugs.no_compression && !(info->bl_flags & BL_NO_COMPRESSION)) { int q = strlen(c->url); if (q >= 2 && !strcasecmp(c->url + q - 2, ".Z")) goto skip_compress; if (q >= 3 && !strcasecmp(c->url + q - 3, ".gz")) goto skip_compress; if (q >= 4 && !strcasecmp(c->url + q - 4, ".bz2")) goto skip_compress; add_to_str(&hdr, &l, "Accept-Encoding: "); #if defined(HAVE_ZLIB) add_to_str(&hdr, &l, "gzip, deflate, "); #endif #if defined(HAVE_BZIP2) add_to_str(&hdr, &l, "bzip2, "); #endif hdr[l-2] = '\r'; hdr[l-1] = '\n'; skip_compress: ; } #endif if (!(accept_charset)) { int i; unsigned char *cs, *ac; int aclen = 0; ac = init_str(); for (i = 0; (cs = get_cp_mime_name(i)); i++) { if (aclen) add_to_str(&ac, &aclen, ", "); else add_to_str(&ac, &aclen, "Accept-Charset: "); add_to_str(&ac, &aclen, cs); } if (aclen) add_to_str(&ac, &aclen, "\r\n"); if ((accept_charset = malloc(strlen(ac) + 1))) strcpy(accept_charset, ac); else accept_charset = ""; mem_free(ac); } if (!(info->bl_flags & BL_NO_CHARSET) && !http_bugs.no_accept_charset) add_to_str(&hdr, &l, accept_charset); if (!(info->bl_flags & BL_NO_ACCEPT_LANGUAGE)) { add_to_str(&hdr, &l, "Accept-Language: "); la = l; add_to_str(&hdr, &l, _(TEXT(T__ACCEPT_LANGUAGE), NULL)); add_to_str(&hdr, &l, ", "); if (!strstr(hdr + la, "en,") && !strstr(hdr + la, "en;")) add_to_str(&hdr, &l, "en;q=0.2, "); add_to_str(&hdr, &l, "*;q=0.1\r\n"); } if (!http10) { if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "Connection: "); else add_to_str(&hdr, &l, "Proxy-Connection: "); if (!post || !http_bugs.bug_post_no_keepalive) add_to_str(&hdr, &l, "Keep-Alive\r\n"); else add_to_str(&hdr, &l, "close\r\n"); } if ((e = c->cache)) { int code, vers; if (get_http_code(e->head, &code, &vers) || code >= 400) goto skip_ifmod_and_range; if (!e->incomplete && e->head && c->no_cache <= NC_IF_MOD) { unsigned char *m; if (e->last_modified) m = stracpy(e->last_modified); else if ((m = parse_http_header(e->head, "Date", NULL))) ; else if ((m = parse_http_header(e->head, "Expires", NULL))) ; else goto skip_ifmod; add_to_str(&hdr, &l, "If-Modified-Since: "); add_to_str(&hdr, &l, m); add_to_str(&hdr, &l, "\r\n"); mem_free(m); } skip_ifmod: ; } if (c->from && (c->est_length == -1 || c->from < c->est_length) && c->no_cache < NC_IF_MOD && !(info->bl_flags & BL_NO_RANGE)) { /* If the cached entity is compressed and we turned off compression, request the whole file */ if ((info->bl_flags & BL_NO_COMPRESSION || http_bugs.no_compression) && e) { unsigned char *d; if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) { mem_free(d); goto skip_range; } } add_to_str(&hdr, &l, "Range: bytes="); add_num_to_str(&hdr, &l, c->from); add_to_str(&hdr, &l, "-\r\n"); skip_range: ; } skip_ifmod_and_range: if (c->no_cache >= NC_PR_NO_CACHE) add_to_str(&hdr, &l, "Pragma: no-cache\r\nCache-Control: no-cache\r\n"); if ((h = get_auth_string(c->url))) { add_to_str(&hdr, &l, h); mem_free(h); } if (post) { unsigned char *pd = strchr(post, '\n'); if (pd) { add_to_str(&hdr, &l, "Content-Type: "); add_bytes_to_str(&hdr, &l, post, pd - post); add_to_str(&hdr, &l, "\r\n"); post = pd + 1; } add_to_str(&hdr, &l, "Content-Length: "); add_num_to_str(&hdr, &l, strlen(post) / 2); add_to_str(&hdr, &l, "\r\n"); } send_cookies(&hdr, &l, host); add_to_str(&hdr, &l, "\r\n"); if (post) { while (post[0] && post[1]) { int h1, h2; h1 = post[0] <= '9' ? (unsigned)post[0] - '0' : post[0] >= 'A' ? upcase(post[0]) - 'A' + 10 : 0; if (h1 < 0 || h1 >= 16) h1 = 0; h2 = post[1] <= '9' ? (unsigned)post[1] - '0' : post[1] >= 'A' ? upcase(post[1]) - 'A' + 10 : 0; if (h2 < 0 || h2 >= 16) h2 = 0; add_chr_to_str(&hdr, &l, h1 * 16 + h2); post += 2; } } write_to_socket(c, c->sock1, hdr, l, http_get_header); mem_free(hdr); setcstate(c, S_SENT); }
int sectorcache_lookup(__u32 ioblkID, int len, struct preq_spec *preq) { char key[25]; char *content = NULL; char *dummystring = NULL; UNUSED(len); sprintf(key, "%u", ioblkID); #if defined(SIMREPLAY_DEBUG_SS_DONE) print_lrucache_stat(); #endif if (!collectformat && disksimflag) dummystring = find_in_cache(key); else { content = find_in_cache(key); UNUSED(dummystring); } /* If preadwritedump traces & disk-simulated, now we use file * for storing cache content physically to save memory usage. */ if (!collectformat && disksimflag) { char skey[20]; if (dummystring) /* found in sectorcache */ { //printf("dummystring=%s\n", dummystring); assert(strcmp(dummystring, "cf")==0); strcpy(skey, preq->blkidkey); content = malloc(BLKSIZE); if (content == NULL) VOID_ERR("malloc failed\n"); cachefile_fetch((unsigned char*)content, preq->blkidkey, BLKSIZE); } else { content = NULL; } } if (content) { if (!disksimflag) /* Found content when disk not simulated */ { assert(0); /* not expected */ if (DISKSIM_RUNTIMEMAP_COLLECTFORMAT_VMBUNCHREPLAY || DISKSIM_RUNTIMEMAP_COLLECTFORMAT_PIOEVENTSREPLAY || DISKSIM_VANILLA_COLLECTFORMAT_VMBUNCHREPLAY || DISKSIM_VANILLA_COLLECTFORMAT_PIOEVENTSREPLAY) { preq->content = malloc(MD5HASHLEN_STR-1); memcpy(preq->content, content, MD5HASHLEN_STR-1); //preq->content[HASHLEN_STR-1] = '\0'; no null char } else { preq->content = malloc(BLKSIZE); if (preq->content == NULL) VOID_ERR("malloc failed\n"); memcpy(preq->content, content, BLKSIZE); } } else if (preq->rw) /* Disk is simulated and this is read request */ { assert(preq->content != NULL); #ifndef INCONSISTENT_TRACES /* If all reads & writes enabled, then these asserts should work, * but if only reads are enabled, it is possible that a 2nd read * request reads (new) content that was written just before * and hence is not present in cache. * * Note that the trace itself may have some records missing, * because of which this assert may fail. This was tested * and found to be true. So in the actual replay run, dont rely on * these asserts. Instead if content is found in cache, then * discard the content in the trace, & use the found one instead! * Therefore, these are commented by #define INCONSISTENT_TRACES! */ if ((DISKSIM_RUNTIMEMAP_COLLECTFORMAT_VMBUNCHREPLAY || DISKSIM_RUNTIMEMAP_COLLECTFORMAT_PIOEVENTSREPLAY || DISKSIM_VANILLA_COLLECTFORMAT_PIOEVENTSREPLAY || DISKSIM_VANILLA_COLLECTFORMAT_VMBUNCHREPLAY) && read_enabled && write_enabled) { if (memcmp(preq->content, content, MD5HASHLEN_STR-1)!=0) printf("%s: assert fail for ioblkID=%u\n",__FUNCTION__, ioblkID); assert(memcmp(preq->content, content, MD5HASHLEN_STR-1)==0); } else if (read_enabled && write_enabled) assert(memcmp(preq->content, content, BLKSIZE)==0); #else if (DISKSIM_RUNTIMEMAP_COLLECTFORMAT_VMBUNCHREPLAY || DISKSIM_RUNTIMEMAP_COLLECTFORMAT_PIOEVENTSREPLAY || DISKSIM_VANILLA_COLLECTFORMAT_VMBUNCHREPLAY || DISKSIM_VANILLA_COLLECTFORMAT_PIOEVENTSREPLAY) memcpy(preq->content, content, MD5HASHLEN_STR-1); else memcpy(preq->content, content, BLKSIZE); #endif } if (!collectformat && disksimflag) { /* content was newly allocated, and not just a pointer into * the cache, if we are here. So free it. */ free(content); } return 1; } else { if (!disksimflag) { assert(REALDISK_SCANNING_NOCOLLECTFORMAT_VMBUNCHREPLAY); preq->content = NULL; } return 0; } }
void ses_goto(struct session *ses, struct uri *uri, unsigned char *target_frame, struct location *target_location, enum cache_mode cache_mode, enum task_type task_type, int redir) { /* [gettext_accelerator_context(ses_goto)] */ struct task *task; int referrer_incomplete = 0; int malicious_uri = 0; int confirm_submit = uri->form && get_opt_bool("document.browse.forms" ".confirm_submit", ses); unsigned char *m1 = NULL, *message = NULL; struct memory_list *mlist = NULL; if (ses->doc_view && ses->doc_view->document && ses->doc_view->document->refresh) { kill_document_refresh(ses->doc_view->document->refresh); } assertm(!ses->loading_uri, "Buggy URI reference counting"); /* Reset the redirect counter if this is not a redirect. */ if (!redir) { ses->redirect_cnt = 0; } /* Figure out whether to confirm submit or not */ /* Only confirm submit if we are posting form data or a misleading URI * was detected. */ /* Note uri->post might be empty here but we are still supposely * posting form data so this should be more correct. */ if (uri->user && uri->userlen && get_opt_bool("document.browse.links.warn_malicious", ses) && check_malicious_uri(uri)) { malicious_uri = 1; confirm_submit = 1; } else if (uri->form) { /* First check if the referring URI was incomplete. It * indicates that the posted form data might be incomplete too. * See bug 460. */ if (ses->referrer) { struct cache_entry *cached; cached = find_in_cache(ses->referrer); referrer_incomplete = (cached && cached->incomplete); } if (referrer_incomplete) { confirm_submit = 1; } else if (get_validated_cache_entry(uri, cache_mode)) { confirm_submit = 0; } } if (!confirm_submit) { ses_load(ses, get_uri_reference(uri), target_frame, target_location, cache_mode, task_type); return; } task = mem_alloc(sizeof(*task)); if (!task) return; task->ses = ses; task->uri = get_uri_reference(uri); task->cache_mode = cache_mode; task->session_task.type = task_type; task->session_task.target.frame = null_or_stracpy(target_frame); task->session_task.target.location = target_location; if (malicious_uri) { unsigned char *host = memacpy(uri->host, uri->hostlen); unsigned char *user = memacpy(uri->user, uri->userlen); unsigned char *uristring = get_uri_string(uri, URI_PUBLIC); message = msg_text(ses->tab->term, N_("The URL you are about to follow might be maliciously " "crafted in order to confuse you. By following the URL " "you will be connecting to host \"%s\" as user \"%s\".\n\n" "Do you want to go to URL %s?"), host, user, uristring); mem_free_if(host); mem_free_if(user); mem_free_if(uristring); } else if (redir) { m1 = N_("Do you want to follow the redirect and post form data " "to URL %s?"); } else if (referrer_incomplete) { m1 = N_("The form data you are about to post might be incomplete.\n" "Do you want to post to URL %s?"); } else if (task_type == TASK_FORWARD) { m1 = N_("Do you want to post form data to URL %s?"); } else { m1 = N_("Do you want to repost form data to URL %s?"); } if (!message && m1) { unsigned char *uristring = get_uri_string(uri, URI_PUBLIC); message = msg_text(ses->tab->term, m1, uristring); mem_free_if(uristring); } add_to_ml(&mlist, task, (void *) NULL); if (task->session_task.target.frame) add_to_ml(&mlist, task->session_task.target.frame, (void *) NULL); msg_box(ses->tab->term, mlist, MSGBOX_FREE_TEXT, N_("Warning"), ALIGN_CENTER, message, task, 2, MSG_BOX_BUTTON(N_("~Yes"), post_yes, B_ENTER), MSG_BOX_BUTTON(N_("~No"), post_no, B_ESC)); }
/* Performs a multiple dispatch using the candidates held in the passed * dispatcher and using the arguments in the passed capture. */ PMC *nqp_multi_dispatch(PARROT_INTERP, PMC *dispatcher, PMC *capture) { NQP_md_cache *disp_cache; PMC *dispatchees, *cache_result; INTVAL type_mismatch, possibles_count, type_check_count, num_candidates, num_args; candidate_info **possibles, **candidates, **cur_candidate; /* Count arguments. */ num_args = VTABLE_elements(interp, capture); /* See if the dispatcher cache will resolve it right off. */ disp_cache = get_dispatch_cache(interp, dispatcher); cache_result = find_in_cache(interp, disp_cache, capture, num_args); if (!PMC_IS_NULL(cache_result)) return cache_result; /* Get list and number of dispatchees. */ dispatchees = get_dispatchees(interp, dispatcher); num_candidates = VTABLE_elements(interp, dispatchees); /* Initialize dispatcher state. */ possibles_count = 0; possibles = mem_allocate_n_typed(num_candidates, candidate_info *); /* Get sorted candidate list. */ candidates = sort_candidates(interp, dispatchees); cur_candidate = candidates; /* Iterate over the candidates and collect best ones; terminate * when we see two nulls (may break out earlier). */ while (1) { INTVAL i; if (*cur_candidate == NULL) { /* If we have some possible candidate(s), we're done in this loop. */ if (possibles_count) break; /* Otherwise, we keep looping and looking, unless we really hit the end. */ if (cur_candidate[1]) { cur_candidate++; continue; } else { break; } } /* Check if it's admissable by arity. */ if (num_args < (*cur_candidate)->min_arity || num_args > (*cur_candidate)->max_arity) { cur_candidate++; continue; } /* Check if it's admissable by type. */ type_check_count = (*cur_candidate)->num_types > num_args ? num_args : (*cur_candidate)->num_types; type_mismatch = 0; for (i = 0; i < type_check_count; i++) { PMC * const param = VTABLE_get_pmc_keyed_int(interp, capture, i); PMC * const param_type = param->vtable->base_type == smo_id ? STABLE(param)->WHAT : PMCNULL; PMC * const type_obj = (*cur_candidate)->types[i]; INTVAL const definedness = (*cur_candidate)->definednesses[i]; if (param_type != type_obj && !is_narrower_type(interp, param_type, type_obj)) { type_mismatch = 1; break; } if (definedness) { /* Have a constraint on the definedness. */ INTVAL defined = param->vtable->base_type == smo_id ? IS_CONCRETE(param) : VTABLE_defined(interp, param); if ((!defined && definedness == DEFINED_ONLY) || (defined && definedness == UNDEFINED_ONLY)) { type_mismatch = 1; break; } } } if (type_mismatch) { cur_candidate++; continue; } /* If we get here, it's an admissable candidate; add to list. */ possibles[possibles_count] = *cur_candidate; possibles_count++; cur_candidate++; } /* Cache the result if there's a single chosen one. */ if (possibles_count == 1) { add_to_cache(interp, disp_cache, capture, num_args, possibles[0]->sub); } /* Need a unique candidate. */ if (possibles_count == 1) { PMC *result = possibles[0]->sub; mem_sys_free(candidates); mem_sys_free(possibles); return result; } else if (possibles_count == 0) { /* Get signatures of all possible candidates. We dump them in the * order in which we search for them. */ PMC *fail_cand = candidates[0]->sub; STRING *signatures = Parrot_str_new(interp, "", 0); cur_candidate = candidates; while (1) { if (!cur_candidate[0] && !cur_candidate[1]) break; /* XXX TODO: add sig dumping. if (cur_candidate[0]) signatures = dump_signature(interp, signatures, (*cur_candidate)->sub); */ cur_candidate++; } mem_sys_free(candidates); mem_sys_free(possibles); Parrot_ex_throw_from_c_args(interp, NULL, 1, "No applicable candidates found to dispatch to for '%Ss'. Available candidates are:\n%Ss", VTABLE_get_string(interp, fail_cand), signatures); } else { /* Get signatures of ambiguous candidates. */ STRING *signatures = Parrot_str_new(interp, "", 0); INTVAL i; /* XXX TODO: sig dumping for (i = 0; i < possibles_count; i++) signatures = dump_signature(interp, signatures, possibles[i]->sub); */ mem_sys_free(candidates); mem_sys_free(possibles); Parrot_ex_throw_from_c_args(interp, NULL, 1, "Ambiguous dispatch to multi '%Ss'. Ambiguous candidates had signatures:\n%Ss", VTABLE_get_string(interp, candidates[0]->sub), signatures); } }