void stat_user(unsigned char **p, int *l, struct stat *stp, int g) { #ifdef FS_UNIX_USERS struct passwd *pwd; struct group *grp; int id; unsigned char *pp; int i; if (!stp) { add_to_str(p, l, " "); return; } id = !g ? stp->st_uid : stp->st_gid; pp = !g ? last_user : last_group; if (!g && id == last_uid && last_uid != -1) goto a; if (g && id == last_gid && last_gid != -1) goto a; if (!g) { if (!(pwd = getpwuid(id)) || !pwd->pw_name) sprintf(pp, "%d", id); else sprintf(pp, "%.8s", pwd->pw_name); last_uid = id; } else { if (!(grp = getgrgid(id)) || !grp->gr_name) sprintf(pp, "%d", id); else sprintf(pp, "%.8s", grp->gr_name); last_gid = id; } a: add_to_str(p, l, pp); for (i = strlen(pp); i < 8; i++) add_chr_to_str(p, l, ' '); add_chr_to_str(p, l, ' '); #endif }
void add_conv_str(unsigned char **s, int *l, unsigned char *b, int ll, int encode_special) { for (; ll > 0; ll--, b++) { if ((unsigned char)*b < ' ') continue; if (special_char(*b) && encode_special == 1) { unsigned char h[4]; sprintf(cast_char h, "%%%02X", (unsigned)*b & 0xff); add_to_str(s, l, h); } else if (*b == '%' && encode_special <= -1 && ll > 2 && ((b[1] >= '0' && b[1] <= '9') || (b[1] >= 'A' && b[1] <= 'F') || (b[1] >= 'a' && b[1] <= 'f'))) { unsigned char h = 0; int i; for (i = 1; i < 3; i++) { if (b[i] >= '0' && b[i] <= '9') h = h * 16 + b[i] - '0'; if (b[i] >= 'A' && b[i] <= 'F') h = h * 16 + b[i] - 'A' + 10; if (b[i] >= 'a' && b[i] <= 'f') h = h * 16 + b[i] - 'a' + 10; } if (h >= ' ') add_chr_to_str(s, l, h); ll -= 2; b += 2; } else if (*b == ' ' && (!encode_special || encode_special == -1)) { add_to_str(s, l, cast_uchar " "); } else if (accept_char(*b) || encode_special == -2) { add_chr_to_str(s, l, *b); } else { add_to_str(s, l, cast_uchar "&#"); add_num_to_str(s, l, (int)*b); add_chr_to_str(s, l, ';'); } } }
char *tempnam(const char *dir, const char *pfx) { static int counter = 0; unsigned char *d, *s, *a; int l; if (!(d = cast_uchar getenv("TMPDIR"))) { if (dir) d = cast_uchar dir; else if (!(d = cast_uchar getenv("TMP")) && !(d = cast_uchar getenv("TEMP"))) { #ifdef P_tmpdir d = cast_uchar(P_tmpdir); #else d = cast_uchar "/tmp"; #endif } } l = 0; s = init_str(); add_to_str(&s, &l, d); if (s[0] && s[strlen(cast_const_char s) - 1] != '/') add_chr_to_str(&s, &l, '/'); add_to_str(&s, &l, cast_uchar pfx); add_num_to_str(&s, &l, counter++); a = cast_uchar strdup(cast_const_char s); mem_free(s); return cast_char a; }
void stat_date(unsigned char **p, int *l, struct stat *stp) { time_t current_time = time(NULL); time_t when; struct tm *when_local; unsigned char *fmt; unsigned char str[13]; int wr; if (!stp) { add_to_str(p, l, " "); return; } when = stp->st_mtime; when_local = localtime(&when); if (current_time > when + 6L * 30L * 24L * 60L * 60L || current_time < when - 60L * 60L) fmt = "%b %e %Y"; else fmt = "%b %e %H:%M"; #ifdef HAVE_STRFTIME wr = strftime(str, 13, fmt, when_local); #else wr = 0; #endif while (wr < 12) str[wr++] = ' '; str[12] = 0; add_to_str(p, l, str); add_chr_to_str(p, l, ' '); }
void ftp_got_user_info(struct connection *c, struct read_buffer *rb) { int g = get_ftp_response(c, rb, 0); if (g == -1) { setcstate(c, S_FTP_ERROR); abort_connection(c); return; } if (!g) { read_from_socket(c, c->sock1, rb, ftp_got_user_info); return; } if (g >= 530 && g < 540) { setcstate(c, S_FTP_LOGIN); retry_connection(c); return; } if (g >= 400) { setcstate(c, S_FTP_UNAVAIL); retry_connection(c); return; } if (g >= 200 && g < 300) { if (ftp_options.fast_ftp) ftp_dummy_info(c, rb); else ftp_send_retr_req(c, S_GETH); } else { if (ftp_options.fast_ftp) ftp_pass_info(c, rb); else { unsigned char *login; unsigned char *u; int logl = 0; login = init_str(); add_to_str(&login, &logl, "PASS "); if ((u = get_pass(c->url)) && *u) add_to_str(&login, &logl, u); else add_to_str(&login, &logl, ftp_options.anon_pass); if (u) mem_free(u); add_to_str(&login, &logl, "\r\n"); write_to_socket(c, c->sock1, login, strlen(login), ftp_sent_passwd); mem_free(login); setcstate(c, S_LOGIN); } } }
void add_graphics_drivers(unsigned char **s, int *l) { struct graphics_driver **gd; for (gd = graphics_drivers; *gd; gd++) { if (gd != graphics_drivers) add_to_str(s, l, cast_uchar ", "); add_to_str(s, l, (*gd)->name); } }
void redraw_screen(struct terminal *term) { int x, y, p = 0; int cx = term->lcx, cy = term->lcy; unsigned char *a; int attrib = -1; int mode = -1; int l = 0; struct term_spec *s; if (!term->dirty || (term->master && is_blocked())) return; a = init_str(); s = term->spec; for (y = 0; y < term->y; y++) for (x = 0; x < term->x; x++, p++) { if (y == term->y - 1 && x == term->x - 1) break; if (term->screen[p] == term->last_screen[p]) continue; if ((term->screen[p] & 0x3800) == (term->last_screen[p] & 0x3800) && ((term->screen[p] & 0xff) == 0 || (term->screen[p] & 0xff) == 1 || (term->screen[p] & 0xff) == ' ') && ((term->last_screen[p] & 0xff) == 0 || (term->last_screen[p] & 0xff) == 1 || (term->last_screen[p] & 0xff) == ' ') && (x != term->cx || y != term->cy)) continue; term->last_screen[p] = term->screen[p]; if (cx == x && cy == y) goto pc;/*PRINT_CHAR(p)*/ else if (cy == y && x - cx < 10 && x - cx > 0) { int i; for (i = x - cx; i >= 0; i--) PRINT_CHAR(p - i); } else { add_to_str(&a, &l, "\033["); add_num_to_str(&a, &l, y + 1); add_to_str(&a, &l, ";"); add_num_to_str(&a, &l, x + 1); add_to_str(&a, &l, "H"); cx = x; cy = y; pc: PRINT_CHAR(p); } } if (l) { if (s->col) add_to_str(&a, &l, "\033[37;40m"); add_to_str(&a, &l, "\033[0m"); if (s->mode == TERM_LINUX && s->m11_hack) add_to_str(&a, &l, "\033[10m"); if (s->mode == TERM_VT100) add_to_str(&a, &l, "\x0f"); } term->lcx = cx; term->lcy = cy; if (term->cx != term->lcx || term->cy != term->lcy) { term->lcx = term->cx; term->lcy = term->cy; add_to_str(&a, &l, "\033["); add_num_to_str(&a, &l, term->cy + 1); add_to_str(&a, &l, ";"); add_num_to_str(&a, &l, term->cx + 1); add_to_str(&a, &l, "H"); } if (l && term->master) want_draw(); hard_write(term->fdout, a, l); if (l && term->master) done_draw(); mem_free(a); term->dirty = 0; }
void add_png_version(unsigned char **s, int *l) { add_to_str(s, l, cast_uchar "PNG ("); #ifdef HAVE_PNG_GET_LIBPNG_VER add_to_str(s, l, cast_uchar png_get_libpng_ver(NULL)); #else add_to_str(s, l, cast_uchar PNG_LIBPNG_VER_STRING); #endif add_to_str(s, l, cast_uchar ")"); }
static void ftp_login(struct connection *c) { unsigned char *login; unsigned char *u; int logl = 0; set_timeout(c); login = init_str(); add_to_str(&login, &logl, cast_uchar "USER "); if ((u = get_user_name(c->url)) && *u) add_to_str(&login, &logl, u); else add_to_str(&login, &logl, cast_uchar "anonymous"); if (u) mem_free(u); if (ftp_options.fast_ftp) { struct ftp_connection_info *fi; add_to_str(&login, &logl, cast_uchar "\r\nPASS "); if ((u = get_pass(c->url)) && *u) add_to_str(&login, &logl, u); else add_to_str(&login, &logl, ftp_options.anon_pass); if (u) mem_free(u); add_to_str(&login, &logl, cast_uchar "\r\n"); if (!(fi = add_file_cmd_to_str(c))) { mem_free(login); return; } add_to_str(&login, &logl, fi->cmdbuf); } else add_to_str(&login, &logl, cast_uchar "\r\n"); write_to_socket(c, c->sock1, login, strlen(cast_const_char login), ftp_logged); mem_free(login); setcstate(c, S_SENT); }
unsigned char *list_graphics_drivers(void) { unsigned char *d = init_str(); int l = 0; struct graphics_driver **gd; for (gd = graphics_drivers; *gd; gd++) { if (l) add_to_str(&d, &l, " "); add_to_str(&d, &l, (*gd)->name); } return d; }
void stat_links(unsigned char **p, int *l, struct stat *stp) { #ifdef FS_UNIX_HARDLINKS unsigned char lnk[64]; if (!stp) add_to_str(p, l, " "); else { sprintf(lnk, "%3d ", (int)stp->st_nlink); add_to_str(p, l, lnk); } #endif }
void stat_size(unsigned char **p, int *l, struct stat *stp) { unsigned char size[64]; if (!stp) z: add_to_str(p, l, " "); else { if ((long)(unsigned long)stp->st_size == stp->st_size) { sprintf(size, "%8lu ", (unsigned long)stp->st_size); add_to_str(p, l, size); } else goto z; } }
unsigned char *make_html_font_name(int attr) { unsigned char *str; int len; str=init_str();len=0; add_to_str(&str, &len, G_HTML_DEFAULT_FAMILY); add_to_str(&str, &len, attr & AT_BOLD ? "-bold" : "-medium"); add_to_str(&str, &len, attr & AT_ITALIC ? "-italic-serif" : "-roman-serif"); add_to_str(&str, &len, attr & AT_FIXED ? "-mono" : "-vari"); return str; }
unsigned char *translate_hashbang(unsigned char *up) { unsigned char *u, *p, *dp, *data, *post_seq; int q; unsigned char *r; int rl; if (!strstr(cast_const_char up, "#!") && !strstr(cast_const_char up, "#%21")) return up; u = stracpy(up); p = extract_position(u); if (!p) { free_u_ret_up: mem_free(u); return up; } if (p[0] == '!') dp = p + 1; else if (!casecmp(p, cast_uchar "%21", 3)) dp = p + 3; else { mem_free(p); goto free_u_ret_up; } if (!(post_seq = cast_uchar strchr(cast_const_char u, POST_CHAR))) post_seq = cast_uchar strchr(cast_const_char u, 0); data = get_url_data(u); if (!data) data = u; r = init_str(); rl = 0; add_bytes_to_str(&r, &rl, u, post_seq - u); q = (int)strlen(cast_const_char data); if (q && (data[q - 1] == '&' || data[q - 1] == '?')) ; else if (strchr(cast_const_char data, '?')) add_chr_to_str(&r, &rl, '&'); else add_chr_to_str(&r, &rl, '?'); add_to_str(&r, &rl, cast_uchar "_escaped_fragment_="); for (; *dp; dp++) { unsigned char c = *dp; if (c <= 0x20 || c == 0x23 || c == 0x25 || c == 0x26 || c == 0x2b || c >= 0x7f) { unsigned char h[4]; sprintf(cast_char h, "%%%02X", c); add_to_str(&r, &rl, h); } else { add_chr_to_str(&r, &rl, c); } } add_to_str(&r, &rl, post_seq); mem_free(u); mem_free(p); mem_free(up); return r; }
void finger_send_request(struct connection *c) { unsigned char *req = init_str(); int rl = 0; unsigned char *user; add_to_str(&req, &rl, "/W"); if ((user = get_user_name(c->url))) { add_to_str(&req, &rl, " "); add_to_str(&req, &rl, user); mem_free(user); } add_to_str(&req, &rl, "\r\n"); write_to_socket(c, c->sock1, req, rl, finger_sent_request); mem_free(req); setcstate(c, S_SENT); }
void add_cookies(unsigned char **s, int *l, unsigned char *url) { int nc = 0; struct c_domain *cd; struct cookie *c, *d; unsigned char *server = get_host_name(url); unsigned char *data = get_url_data(url); if (data > url) data--; foreach (cd, c_domains) if (is_in_domain(cd->domain, server)) goto ok; mem_free(server); return; ok: foreachback (c, all_cookies) if (is_in_domain(c->domain, server)) if (is_path_prefix(c->path, data)) { if (cookie_expired(c)) { d = c; c = c->prev; del_from_list(d); free_cookie(d); mem_free(d); continue; } if (c->secure && casecmp(url, cast_uchar "https://", 8)) continue; if (!nc) add_to_str(s, l, cast_uchar "Cookie: "), nc = 1; else add_to_str(s, l, cast_uchar "; "); add_to_str(s, l, c->name); if (c->value) { add_to_str(s, l, cast_uchar "="); add_to_str(s, l, c->value); } } if (nc) add_to_str(s, l, cast_uchar "\r\n"); mem_free(server); }
unsigned char *init_graphics(unsigned char *driver, unsigned char *param, unsigned char *display) { unsigned char *s = init_str(); int l = 0; struct graphics_driver **gd; #if defined(GRDRV_PMSHELL) && defined(GRDRV_X) if (is_xterm()) { static unsigned char swapped = 0; if (!swapped) { for (gd = graphics_drivers; *gd; gd++) { if (*gd == &pmshell_driver) *gd = &x_driver; else if (*gd == &x_driver) *gd = &pmshell_driver; } swapped = 1; } } #endif for (gd = graphics_drivers; *gd; gd++) { if (!driver || !*driver || !strcasecmp(cast_const_char (*gd)->name, cast_const_char driver)) { unsigned char *r; if ((!driver || !*driver) && (*gd)->flags & GD_NOAUTO) continue; if (!(r = init_graphics_driver(*gd, param, display))) { mem_free(s); return NULL; } if (!l) { if (!driver || !*driver) add_to_str(&s, &l, cast_uchar "Could not initialize any graphics driver. Tried the following drivers:\n"); else add_to_str(&s, &l, cast_uchar "Could not initialize graphics driver "); } add_to_str(&s, &l, (*gd)->name); add_to_str(&s, &l, cast_uchar ":\n"); add_to_str(&s, &l, r); mem_free(r); } } if (!l) { add_to_str(&s, &l, cast_uchar "Unknown graphics driver "); if (driver) add_to_str(&s, &l, driver); add_to_str(&s, &l, cast_uchar ".\nThe following graphics drivers are supported:\n"); add_graphics_drivers(&s, &l); add_to_str(&s, &l, cast_uchar "\n"); } return s; }
void add_url_to_str(unsigned char **str, int *l, unsigned char *url) { unsigned char *sp; for (sp = url; *sp && *sp != POST_CHAR; sp++) { if (*sp <= ' ') { char esc[4]; sprintf(esc, "%%%02X", (int)*sp); add_to_str(str, l, esc); } else if (*sp == '\\') { add_chr_to_str(str, l, '/'); } else { add_chr_to_str(str, l, *sp); } } }
static void x_update_driver_param(int w, int h) { int l=0; if (n_wins!=1)return; x_default_window_width=w; x_default_window_height=h; if (x_driver_param)mem_free(x_driver_param); x_driver_param=init_str(); add_num_to_str(&x_driver_param,&l,x_default_window_width); add_to_str(&x_driver_param,&l,"x"); add_num_to_str(&x_driver_param,&l,x_default_window_height); }
void stat_mode(unsigned char **p, int *l, struct stat *stp) { unsigned char c = '?'; if (stp) { if (0) ; #ifdef S_ISBLK else if (S_ISBLK(stp->st_mode)) c = 'b'; #endif #ifdef S_ISCHR else if (S_ISCHR(stp->st_mode)) c = 'c'; #endif else if (S_ISDIR(stp->st_mode)) c = 'd'; else if (S_ISREG(stp->st_mode)) c = '-'; #ifdef S_ISFIFO else if (S_ISFIFO(stp->st_mode)) c = 'p'; #endif #ifdef S_ISLNK else if (S_ISLNK(stp->st_mode)) c = 'l'; #endif #ifdef S_ISSOCK else if (S_ISSOCK(stp->st_mode)) c = 's'; #endif #ifdef S_ISNWK else if (S_ISNWK(stp->st_mode)) c = 'n'; #endif } add_chr_to_str(p, l, c); #ifdef FS_UNIX_RIGHTS { unsigned char rwx[10] = "---------"; if (stp) { int mode = stp->st_mode; setrwx(mode << 0, &rwx[0]); setrwx(mode << 3, &rwx[3]); setrwx(mode << 6, &rwx[6]); setst(mode, rwx); } add_to_str(p, l, rwx); } #endif add_chr_to_str(p, l, ' '); }
static void add_port_pasv(unsigned char **s, int *l, struct ftp_connection_info *inf, unsigned char *port_string) { if (!inf->pasv) { if (inf->eprt_epsv) { add_to_str(s, l, cast_uchar "EPRT "); add_to_str(s, l, port_string); } else { add_to_str(s, l, cast_uchar "PORT "); add_to_str(s, l, port_string); } } else { if (inf->eprt_epsv) { add_to_str(s, l, cast_uchar "EPSV"); } else { add_to_str(s, l, cast_uchar "PASV"); } } add_to_str(s, l, cast_uchar "\r\n"); }
void ftp_send_retr_req(struct connection *c, int state) { struct ftp_connection_info *fi; unsigned char *login; int logl = 0; set_timeout(c); login = init_str(); if (!c->info && !(fi = add_file_cmd_to_str(c))) { mem_free(login); return; } else fi = c->info; if (ftp_options.fast_ftp) a:add_to_str(&login, &logl, fi->cmdbuf); else { unsigned char *nl = strchr(fi->cmdbuf, '\n'); if (!nl) goto a; nl++; add_bytes_to_str(&login, &logl, fi->cmdbuf, nl - fi->cmdbuf); memmove(fi->cmdbuf, nl, strlen(nl) + 1); } write_to_socket(c, c->sock1, login, strlen(login), ftp_retr_1); mem_free(login); setcstate(c, state); }
/* initiate connection with X server */ static unsigned char * x_init_driver(unsigned char *param, unsigned char *display) { XGCValues gcv; XSetWindowAttributes win_attr; XVisualInfo vinfo; int misordered=-1; n_wins=0; #if defined(HAVE_SETLOCALE) && defined(LC_ALL) setlocale(LC_ALL,""); #endif #ifdef X_DEBUG { unsigned char txt[256]; sprintf(txt,"x_init_driver(%s, %s)\n",param, display); MESSAGE(txt); } #endif x_input_encoding=-1; #if defined(HAVE_NL_LANGINFO) && defined(HAVE_LANGINFO_H) && defined(CODESET) { unsigned char *cp; cp=nl_langinfo(CODESET); x_input_encoding=get_cp_index(cp); } #endif if (x_input_encoding<0)x_driver.flags|=GD_NEED_CODEPAGE; if (!display||!(*display))display=0; /* X documentation says on XOpenDisplay(display_name) : display_name Specifies the hardware display name, which determines the dis- play and communications domain to be used. On a POSIX-confor- mant system, if the display_name is NULL, it defaults to the value of the DISPLAY environment variable. But OS/2 has problems when display_name is NULL ... */ if (!display)display=getenv("DISPLAY"); #ifndef __linux__ /* on Linux, do not assume XWINDOW present if $DISPLAY is not set --- rather open links on svgalib or framebuffer console */ if (!display)display=":0.0"; /* needed for MacOS X */ #endif x_display=XOpenDisplay(display); if (!x_display) { unsigned char *err=init_str(); int l=0; add_to_str(&err,&l,"Can't open display \""); add_to_str(&err,&l,display?display:(unsigned char *)"(null)"); add_to_str(&err,&l,"\"\n"); return err; } x_hash_table_init(); x_bitmap_bit_order=BitmapBitOrder(x_display); x_fd=XConnectionNumber(x_display); x_screen=DefaultScreen(x_display); x_display_height=DisplayHeight(x_display,x_screen); x_display_width=DisplayWidth(x_display,x_screen); x_root_window=RootWindow(x_display,x_screen); x_default_window_width=x_display_width-50; x_default_window_height=x_display_height-50; x_driver_param=NULL; if (param) { char *p, *e, *f; int w,h; x_driver_param=stracpy(param); for (p=x_driver_param;(*p)&&(*p)!='x'&&(*p)!='X';p++); if (!(*p))goto done; *p=0; w=strtoul(x_driver_param,&e,10); h=strtoul(p+1,&f,10); if (!(*e)&&!(*f)&&w&&h){x_default_window_width=w;x_default_window_height=h;} *p='x'; done:; } /* find best visual */ { #define DEPTHS 5 #define CLASSES 2 int depths[DEPTHS]={24, 16, 15, 8, 4}; int classes[CLASSES]={TrueColor, PseudoColor}; /* FIXME: dodelat DirectColor */ int a,b; for (a=0;a<DEPTHS;a++) for (b=0;b<CLASSES;b++) { if (XMatchVisualInfo(x_display, x_screen,depths[a],classes[b], &vinfo)) { x_default_visual=vinfo.visual; x_depth=vinfo.depth; /* determine bytes per pixel */ { XPixmapFormatValues *pfm; int n,i; pfm=XListPixmapFormats(x_display,&n); for (i=0;i<n;i++) if (pfm[i].depth==x_depth) { x_bitmap_bpp=pfm[i].bits_per_pixel<8?1:((pfm[i].bits_per_pixel)>>3); x_bitmap_scanline_pad=(pfm[i].scanline_pad)>>3; XFree(pfm); goto bytes_per_pixel_found; } if(n) XFree(pfm); continue; } bytes_per_pixel_found: /* test misordered flag */ switch(x_depth) { case 4: case 8: if (x_bitmap_bpp!=1)break; if (vinfo.red_mask>=vinfo.green_mask&&vinfo.green_mask>=vinfo.blue_mask) { misordered=0; goto visual_found; } break; case 15: case 16: if (x_bitmap_bpp!=2)break; if (x_bitmap_bit_order==MSBFirst&&vinfo.red_mask>vinfo.green_mask&&vinfo.green_mask>vinfo.blue_mask) { misordered=256; goto visual_found; } if (x_bitmap_bit_order==MSBFirst)break; if (vinfo.red_mask>vinfo.green_mask&&vinfo.green_mask>vinfo.blue_mask) { misordered=0; goto visual_found; } break; case 24: if (x_bitmap_bpp!=3&&x_bitmap_bpp!=4) break; if (vinfo.red_mask<vinfo.green_mask&&vinfo.green_mask<vinfo.blue_mask) { misordered=256; goto visual_found; } if (x_bitmap_bit_order==MSBFirst&&vinfo.red_mask>vinfo.green_mask&&vinfo.green_mask>vinfo.blue_mask) { misordered=512; goto visual_found; } if (vinfo.red_mask>vinfo.green_mask&&vinfo.green_mask>vinfo.blue_mask) { misordered=0; goto visual_found; } break; } } }
void file_func(struct connection *c) { struct cache_entry *e; unsigned char *file, *name, *head; int fl; DIR *d; int h, r; struct stat stt; if (anonymous && !anonymousGinga) { setcstate(c, S_BAD_URL); abort_connection(c); return; } if (!(name = get_filename(c->url))) { setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } if (anonymousGinga && !allowedPath(name)){ setcstate(c, S_BAD_URL); abort_connection(c); return; } if (stat(name, &stt)) { mem_free(name); setcstate(c, -errno); abort_connection(c); return; } if (!S_ISDIR(stt.st_mode) && !S_ISREG(stt.st_mode)) { mem_free(name); setcstate(c, S_FILE_TYPE); abort_connection(c); return; } if ((h = open(name, O_RDONLY | O_NOCTTY)) == -1) { int er = errno; if ((d = opendir(name))) goto dir; mem_free(name); setcstate(c, -er); abort_connection(c); return; } set_bin(h); if (S_ISDIR(stt.st_mode)) { struct dirs *dir; int dirl; int i; struct dirent *de; d = opendir(name); close(h); if (!d) { mem_free(name); setcstate(c, -errno); abort_connection(c); return; } dir: dir = DUMMY, dirl = 0; if (name[0] && !dir_sep(name[strlen(name) - 1])) { if (get_cache_entry(c->url, &e)) { mem_free(name); closedir(d); setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } c->cache = e; if (e->redirect) mem_free(e->redirect); e->redirect = stracpy(c->url); e->redirect_get = 1; add_to_strn(&e->redirect, "/"); mem_free(name); closedir(d); goto end; } last_uid = -1; last_gid = -1; file = init_str(); fl = 0; add_to_str(&file, &fl, "<html><head><title>"); add_conv_str(&file, &fl, name, strlen(name), -1); add_to_str(&file, &fl, "</title></head><body><h2>Directory "); add_conv_str(&file, &fl, name, strlen(name), -1); add_to_str(&file, &fl, "</h2><pre>"); while ((de = readdir(d))) { struct stat stt, *stp; unsigned char **p; int l; unsigned char *n; if (!strcmp(de->d_name, ".")) continue; if ((unsigned)dirl > MAXINT / sizeof(struct dirs) - 1) overalloc(); dir = mem_realloc(dir, (dirl + 1) * sizeof(struct dirs)); dir[dirl].f = stracpy(de->d_name); *(p = &dir[dirl++].s) = init_str(); l = 0; n = stracpy(name); add_to_strn(&n, de->d_name); #ifdef FS_UNIX_SOFTLINKS if (lstat(n, &stt)) #else if (stat(n, &stt)) #endif stp = NULL; else stp = &stt; mem_free(n); stat_mode(p, &l, stp); stat_links(p, &l, stp); stat_user(p, &l, stp, 0); stat_user(p, &l, stp, 1); stat_size(p, &l, stp); stat_date(p, &l, stp); } closedir(d); if (dirl) qsort(dir, dirl, sizeof(struct dirs), (int(*)(const void *, const void *))comp_de); for (i = 0; i < dirl; i++) { unsigned char *lnk = NULL; #ifdef FS_UNIX_SOFTLINKS if (dir[i].s[0] == 'l') { unsigned char *buf = NULL; int size = 0; int r; unsigned char *n = stracpy(name); add_to_strn(&n, dir[i].f); do { if (buf) mem_free(buf); size += ALLOC_GR; if ((unsigned)size > MAXINT) overalloc(); buf = mem_alloc(size); r = readlink(n, buf, size); } while (r == size); if (r == -1) goto yyy; buf[r] = 0; lnk = buf; goto xxx; yyy: mem_free(buf); xxx: mem_free(n); } #endif /*add_to_str(&file, &fl, " ");*/ add_to_str(&file, &fl, dir[i].s); add_to_str(&file, &fl, "<a href=\""); add_conv_str(&file, &fl, dir[i].f, strlen(dir[i].f), 1); if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "/"); else if (lnk) { struct stat st; unsigned char *n = stracpy(name); add_to_strn(&n, dir[i].f); if (!stat(n, &st)) if (S_ISDIR(st.st_mode)) add_to_str(&file, &fl, "/"); mem_free(n); } add_to_str(&file, &fl, "\">"); /*if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "<font color=\"yellow\">");*/ add_conv_str(&file, &fl, dir[i].f, strlen(dir[i].f), 0); /*if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "</font>");*/ add_to_str(&file, &fl, "</a>"); if (lnk) { add_to_str(&file, &fl, " -> "); add_to_str(&file, &fl, lnk); mem_free(lnk); } add_to_str(&file, &fl, "\n"); } mem_free(name); for (i = 0; i < dirl; i++) mem_free(dir[i].s), mem_free(dir[i].f); mem_free(dir); add_to_str(&file, &fl, "</pre></body></html>\n"); head = stracpy("\r\nContent-Type: text/html\r\n"); } else { mem_free(name); /* + !stt.st_size is there because of bug in Linux. Read returns -EACCES when reading 0 bytes to invalid address */ if (stt.st_size > MAXINT) { close(h); setcstate(c, S_LARGE_FILE); abort_connection(c); return; } file = mem_alloc(stt.st_size + !stt.st_size); if ((r = read(h, file, stt.st_size)) != stt.st_size) { mem_free(file); close(h); setcstate(c, r == -1 ? -errno : S_FILE_ERROR); abort_connection(c); return; } close(h); fl = stt.st_size; head = stracpy(""); } if (get_cache_entry(c->url, &e)) { mem_free(file); setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } if (e->head) mem_free(e->head); e->head = head; c->cache = e; add_fragment(e, 0, file, fl); truncate_entry(e, fl, 1); mem_free(file); end: c->cache->incomplete = 0; setcstate(c, S_OK); abort_connection(c); }
static struct ftp_connection_info *add_file_cmd_to_str(struct connection *c) { unsigned char *d = get_url_data(c->url); unsigned char *de; int del; unsigned char port_string[50]; struct ftp_connection_info *inf, *inf2; unsigned char *s; int l; if (!d) { internal("get_url_data failed"); setcstate(c, S_INTERNAL); abort_connection(c); return NULL; } de = init_str(), del = 0; add_conv_str(&de, &del, d, strlen(cast_const_char d), -2); d = de; inf = mem_alloc(sizeof(struct ftp_connection_info)); memset(inf, 0, sizeof(struct ftp_connection_info)); l = 0; s = init_str(); inf->pasv = ftp_options.passive_ftp; #ifdef LINKS_2 if (*c->socks_proxy) inf->pasv = 1; if (ftp_options.eprt_epsv || is_ipv6(c->sock1)) inf->eprt_epsv = 1; #endif c->info = inf; if (!inf->pasv) { int ps; #ifdef SUPPORT_IPV6 if (is_ipv6(c->sock1)) { ps = get_pasv_socket_ipv6(c, c->sock1, &c->sock2, port_string); if (ps) { mem_free(d); mem_free(s); return NULL; } } else #endif { unsigned char pc[6]; ps = get_pasv_socket(c, c->sock1, &c->sock2, pc); if (ps) { mem_free(d); mem_free(s); return NULL; } if (inf->eprt_epsv) sprintf(cast_char port_string, "|1|%d.%d.%d.%d|%d|", pc[0], pc[1], pc[2], pc[3], (pc[4] << 8) | pc[5]); else sprintf(cast_char port_string, "%d,%d,%d,%d,%d,%d", pc[0], pc[1], pc[2], pc[3], pc[4], pc[5]); } if (strlen(cast_const_char port_string) >= sizeof(port_string)) internal("buffer overflow in get_pasv_socket_ipv6: %d > %d", (int)strlen(cast_const_char port_string), (int)sizeof(port_string)); } #ifdef HAVE_IPTOS if (ftp_options.set_tos) { int rx; int on = IPTOS_THROUGHPUT; EINTRLOOP(rx, setsockopt(c->sock2, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int))); } #endif if (!(de = cast_uchar strchr(cast_const_char d, POST_CHAR))) de = d + strlen(cast_const_char d); if (d == de || de[-1] == '/') { inf->dir = 1; inf->pending_commands = 4; add_to_str(&s, &l, cast_uchar "TYPE A\r\n"); add_port_pasv(&s, &l, inf, port_string); add_to_str(&s, &l, cast_uchar "CWD /"); add_bytes_to_str(&s, &l, d, de - d); add_to_str(&s, &l, cast_uchar "\r\nLIST\r\n"); c->from = 0; } else { inf->dir = 0; inf->pending_commands = 3; add_to_str(&s, &l, cast_uchar "TYPE I\r\n"); add_port_pasv(&s, &l, inf, port_string); if (c->from && c->no_cache < NC_IF_MOD) { add_to_str(&s, &l, cast_uchar "REST "); add_num_to_str(&s, &l, c->from); add_to_str(&s, &l, cast_uchar "\r\n"); inf->rest_sent = 1; inf->pending_commands++; } else c->from = 0; add_to_str(&s, &l, cast_uchar "RETR /"); add_bytes_to_str(&s, &l, d, de - d); add_to_str(&s, &l, cast_uchar "\r\n"); } inf->opc = inf->pending_commands; if ((unsigned)l > MAXINT - sizeof(struct ftp_connection_info) - 1) overalloc(); inf2 = mem_realloc(inf, sizeof(struct ftp_connection_info) + l + 1); strcpy(cast_char (inf = inf2)->cmdbuf, cast_const_char s); mem_free(s); c->info = inf; mem_free(d); return inf; }
unsigned char *init_graphics(unsigned char *driver, unsigned char *param, unsigned char *display) { unsigned char *s = init_str(); int l = 0; struct graphics_driver **gd; for (gd = graphics_drivers; *gd; gd++) { if (!driver || !*driver || !strcasecmp((*gd)->name, driver)) { unsigned char *r; if ((!driver || !*driver) && (*gd)->flags & GD_NOAUTO) continue; if (!(r = init_graphics_driver(*gd, param, display))) { mem_free(s); drv = *gd; F = 1; return NULL; } if (!l) { if (!driver || !*driver) add_to_str(&s, &l, "Could not initialize any graphics driver. Tried the following drivers:\n"); else add_to_str(&s, &l, "Could not initialize graphics driver "); } add_to_str(&s, &l, (*gd)->name); add_to_str(&s, &l, ":\n"); add_to_str(&s, &l, r); mem_free(r); } } if (!l) { add_to_str(&s, &l, "Unknown graphics driver "); if (driver) add_to_str(&s, &l, driver); add_to_str(&s, &l, ".\nThe following graphics drivers are supported:\n"); for (gd = graphics_drivers; *gd; gd++) { if (gd != graphics_drivers) add_to_str(&s, &l, ", "); add_to_str(&s, &l, (*gd)->name); } add_to_str(&s, &l, "\n"); } return s; }
struct ftp_connection_info *add_file_cmd_to_str(struct connection *c) { unsigned char *d = get_url_data(c->url); unsigned char *de; int del; unsigned char pc[6]; int ps; struct ftp_connection_info *inf, *inf2; unsigned char *s; int l; if (!d) { internal("get_url_data failed"); setcstate(c, S_INTERNAL); abort_connection(c); return NULL; } de = init_str(), del = 0; add_conv_str(&de, &del, d, strlen(d), -2); d = de; inf = mem_alloc(sizeof(struct ftp_connection_info)); memset(inf, 0, sizeof(struct ftp_connection_info)); l = 0; s = init_str(); inf->pasv = ftp_options.passive_ftp; if (*c->socks_proxy) inf->pasv = 1; c->info = inf; if (!inf->pasv) if ((ps = get_pasv_socket(c, c->sock1, &c->sock2, pc))) { mem_free(d); return NULL; } #ifdef HAVE_IPTOS if (ftp_options.set_tos) { int on = IPTOS_THROUGHPUT; setsockopt(c->sock2, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)); } #endif if (!(de = strchr(d, POST_CHAR))) de = d + strlen(d); if (d == de || de[-1] == '/') { inf->dir = 1; inf->pending_commands = 4; add_to_str(&s, &l, "TYPE A\r\n"); if (!inf->pasv) { add_to_str(&s, &l, "PORT "); add_num_to_str(&s, &l, pc[0]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[1]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[2]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[3]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[4]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[5]); add_to_str(&s, &l, "\r\n"); } else { add_to_str(&s, &l, "PASV\r\n"); } add_to_str(&s, &l, "CWD /"); add_bytes_to_str(&s, &l, d, de - d); add_to_str(&s, &l, "\r\nLIST\r\n"); c->from = 0; } else { inf->dir = 0; inf->pending_commands = 3; add_to_str(&s, &l, "TYPE I\r\n"); if (!inf->pasv) { add_to_str(&s, &l, "PORT "); add_num_to_str(&s, &l, pc[0]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[1]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[2]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[3]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[4]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[5]); add_to_str(&s, &l, "\r\n"); } else { add_to_str(&s, &l, "PASV\r\n"); } if (c->from && c->no_cache < NC_IF_MOD) { add_to_str(&s, &l, "REST "); add_num_to_str(&s, &l, c->from); add_to_str(&s, &l, "\r\n"); inf->rest_sent = 1; inf->pending_commands++; } else c->from = 0; add_to_str(&s, &l, "RETR /"); add_bytes_to_str(&s, &l, d, de - d); add_to_str(&s, &l, "\r\n"); } inf->opc = inf->pending_commands; if ((unsigned)l > MAXINT - sizeof(struct ftp_connection_info) - 1) overalloc(); inf2 = mem_realloc(inf, sizeof(struct ftp_connection_info) + l + 1); strcpy((inf = inf2)->cmdbuf, s); mem_free(s); c->info = inf; mem_free(d); return inf; }
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); }
void http_got_header(struct connection *c, struct read_buffer *rb) { int cf; int state = c->state != S_PROC ? S_GETH : S_PROC; unsigned char *head; unsigned char *cookie, *ch; int a, h, version; unsigned char *d; struct cache_entry *e; struct http_connection_info *info; unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url); set_timeout(c); info = c->info; if (rb->close == 2) { unsigned char *h; if (!c->tries && (h = get_host_name(host))) { if (info->bl_flags & BL_NO_CHARSET) { del_blacklist_entry(h, BL_NO_CHARSET); } else { add_blacklist_entry(h, BL_NO_CHARSET); c->tries = -1; } mem_free(h); } setcstate(c, S_CANT_READ); retry_connection(c); return; } rb->close = 0; again: if ((a = get_header(rb)) == -1) { setcstate(c, S_HTTP_ERROR); abort_connection(c); return; } if (!a) { read_from_socket(c, c->sock1, rb, http_got_header); setcstate(c, state); return; } if (a != -2) { head = mem_alloc(a + 1); memcpy(head, rb->data, a); head[a] = 0; kill_buffer_data(rb, a); } else { head = stracpy("HTTP/0.9 200 OK\r\nContent-Type: text/html\r\n\r\n"); } if (get_http_code(head, &h, &version) || h == 101) { mem_free(head); setcstate(c, S_HTTP_ERROR); abort_connection(c); return; } if (check_http_server_bugs(host, c->info, head) && is_connection_restartable(c)) { mem_free(head); setcstate(c, S_RESTART); retry_connection(c); return; } ch = head; while ((cookie = parse_http_header(ch, "Set-Cookie", &ch))) { unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url); set_cookie(NULL, host, cookie); mem_free(cookie); } if (h == 100) { mem_free(head); state = S_PROC; goto again; } if (h < 200) { mem_free(head); setcstate(c, S_HTTP_ERROR); abort_connection(c); return; } if (h == 204) { mem_free(head); setcstate(c, S_HTTP_204); http_end_request(c, 0); return; } if (h == 304) { mem_free(head); setcstate(c, S_OK); http_end_request(c, 1); return; } if ((h == 500 || h == 502 || h == 503 || h == 504) && http_bugs.retry_internal_errors && is_connection_restartable(c)) { /* !!! FIXME: wait some time ... */ mem_free(head); setcstate(c, S_RESTART); retry_connection(c); return; } if (!c->cache && get_cache_entry(c->url, &c->cache)) { mem_free(head); setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } e = c->cache; e->http_code = h; if (e->head) mem_free(e->head); e->head = head; if ((d = parse_http_header(head, "Expires", NULL))) { time_t t = parse_http_date(d); if (t && e->expire_time != 1) e->expire_time = t; mem_free(d); } if ((d = parse_http_header(head, "Pragma", NULL))) { if (!casecmp(d, "no-cache", 8)) e->expire_time = 1; mem_free(d); } if ((d = parse_http_header(head, "Cache-Control", NULL))) { char *f = d; while (1) { while (*f && (*f == ' ' || *f == ',')) f++; if (!*f) break; if (!casecmp(f, "no-cache", 8) || !casecmp(f, "must-revalidate", 15)) { e->expire_time = 1; } if (!casecmp(f, "max-age=", 8)) { if (e->expire_time != 1) e->expire_time = time(NULL) + atoi(f + 8); } while (*f && *f != ',') f++; } mem_free(d); } #ifdef HAVE_SSL if (c->ssl) { int l = 0; if (e->ssl_info) mem_free(e->ssl_info); e->ssl_info = init_str(); add_num_to_str(&e->ssl_info, &l, SSL_get_cipher_bits(c->ssl, NULL)); add_to_str(&e->ssl_info, &l, "-bit "); add_to_str(&e->ssl_info, &l, SSL_get_cipher_version(c->ssl)); add_to_str(&e->ssl_info, &l, " "); add_to_str(&e->ssl_info, &l, (unsigned char *)SSL_get_cipher_name(c->ssl)); } #endif if (e->redirect) mem_free(e->redirect), e->redirect = NULL; if (h == 301 || h == 302 || h == 303 || h == 307) { if ((h == 302 || h == 307) && !e->expire_time) e->expire_time = 1; if ((d = parse_http_header(e->head, "Location", NULL))) { unsigned char *user, *ins; unsigned char *newuser, *newpassword; if (!parse_url(d, NULL, &user, NULL, NULL, NULL, &ins, NULL, NULL, NULL, NULL, NULL, NULL) && !user && ins && (newuser = get_user_name(host))) { if (*newuser) { int ins_off = ins - d; newpassword = get_pass(host); if (!newpassword) newpassword = stracpy(""); add_to_strn(&newuser, ":"); add_to_strn(&newuser, newpassword); add_to_strn(&newuser, "@"); extend_str(&d, strlen(newuser)); ins = d + ins_off; memmove(ins + strlen(newuser), ins, strlen(ins) + 1); memcpy(ins, newuser, strlen(newuser)); mem_free(newpassword); } mem_free(newuser); } if (e->redirect) mem_free(e->redirect); e->redirect = d; e->redirect_get = h == 303; } } if (!e->expire_time && strchr(c->url, POST_CHAR)) e->expire_time = 1; info->close = 0; info->length = -1; info->version = version; if ((d = parse_http_header(e->head, "Connection", NULL)) || (d = parse_http_header(e->head, "Proxy-Connection", NULL))) { if (!strcasecmp(d, "close")) info->close = 1; mem_free(d); } else if (version < 11) info->close = 1; cf = c->from; c->from = 0; if ((d = parse_http_header(e->head, "Content-Range", NULL))) { if (strlen(d) > 6) { d[5] = 0; if (!(strcasecmp(d, "bytes")) && d[6] >= '0' && d[6] <= '9') { #if defined(HAVE_STRTOLL) long long f = strtoll(d + 6, NULL, 10); #elif defined(HAVE_STRTOQ) longlong f = strtoq(d + 6, NULL, 10); #else long f = strtol(d + 6, NULL, 10); if (f == MAXLONG) f = -1; #endif if (f >= 0 && (off_t)f >= 0 && (off_t)f == f) c->from = f; } } mem_free(d); } if (cf && !c->from && !c->unrestartable) c->unrestartable = 1; if (c->from > cf || c->from < 0) { setcstate(c, S_HTTP_ERROR); abort_connection(c); return; } if ((d = parse_http_header(e->head, "Content-Length", NULL))) { unsigned char *ep; #if defined(HAVE_STRTOLL) long long l = strtoll(d, (char **)(void *)&ep, 10); #elif defined(HAVE_STRTOQ) longlong l = strtoq(d, (char **)(void *)&ep, 10); #else long l = strtol(d, (char **)(void *)&ep, 10); if (l == MAXLONG) l = -1; #endif if (!*ep && l >= 0 && (off_t)l >= 0 && (off_t)l == l) { if (!info->close || version >= 11) info->length = l; if (c->from + l >= 0) c->est_length = c->from + l; } mem_free(d); } if ((d = parse_http_header(e->head, "Accept-Ranges", NULL))) { if (!strcasecmp(d, "none") && !c->unrestartable) c->unrestartable = 1; mem_free(d); } else { if (!c->unrestartable && !c->from) c->unrestartable = 1; } if (info->bl_flags & BL_NO_RANGE && !c->unrestartable) c->unrestartable = 1; if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) { if (!strcasecmp(d, "chunked")) { info->length = -2; info->chunk_remaining = -1; } mem_free(d); } if (!info->close && info->length == -1) info->close = 1; if ((d = parse_http_header(e->head, "Last-Modified", NULL))) { if (e->last_modified && strcasecmp(e->last_modified, d)) { delete_entry_content(e); if (c->from) { c->from = 0; mem_free(d); setcstate(c, S_MODIFIED); retry_connection(c); return; } } if (!e->last_modified) e->last_modified = d; else mem_free(d); } if (!e->last_modified && (d = parse_http_header(e->head, "Date", NULL))) e->last_modified = d; if (info->length == -1 || (version < 11 && info->close)) rb->close = 1; read_http_data(c, rb); }