// ************************************************************************** // HTTPヘッダを受信して解析する。 // // 処理するのはGETのみ。GET以外のメソッドが来たらエラー // 今のところ、URIとuser_agent、Range、Hostを解析。 // URIは、URIデコードもやる。 // // return: 0 正常終了 // return: 0以外 エラー // ************************************************************************** static int http_header_receive(int accept_socket, HTTP_RECV_INFO *http_recv_info_p) { int result = 0; int recv_len; unsigned char line_buf[1024]; // 大きめに。 unsigned char work_buf[1024]; unsigned char work_buf2[1024]; unsigned char split1[1024]; unsigned char split2[1024]; int ret; int i; int j; // ================================ // 1行づつ HTTPヘッダを受信 // ================================ for (i=0;;i++) { // 1行受信 実行。 memset(line_buf, '\0', sizeof(line_buf)); recv_len = line_receive(accept_socket, line_buf, sizeof(line_buf)); // debug. 受信したヘッダ表示 debug_log_output("'%s'(%d byte)\n", line_buf, recv_len ); // 受信した内容をチェック。 if ( i != 0 && recv_len == 0 ) // 空行検知。ヘッダ受信終了。 { break; } else if ( recv_len < 0 ) // 受信失敗 { return ( -1 ); } // -------------------------- // GETメッセージチェック // -------------------------- if ( i == 0 ) // 1行目のみチェック { debug_log_output("URI Check start.'%s'\n", line_buf); // GET/POSTある? if (strncmp(line_buf, "GET ", 4) && strncmp(line_buf, "POST ", 5)) { debug_log_output("'GET' or 'POST' not found. error."); return ( -1 ); } strncpy(http_recv_info_p->request_method, line_buf, sizeof(http_recv_info_p->request_method)); cut_after_character(http_recv_info_p->request_method, ' '); // 最初のスペースまでを削除。 cut_before_character(line_buf, ' '); // 次にスペースが出てきたところの後ろまでを削除。 cut_after_character(line_buf, ' '); // =========================== // GETオプション部解析 // =========================== // REQUEST_URI用・Proxy用に値を保存 strncpy(http_recv_info_p->request_uri, line_buf, sizeof(http_recv_info_p->request_uri)); // '?'が存在するかチェック。 if ( strchr(line_buf, '?') != NULL ) { strncpy(work_buf, line_buf, sizeof(work_buf)); // '?'より前をカット cut_before_character(work_buf, '?' ); debug_log_output("work_buf = '%s'", work_buf ); while ( 1 ) { memset(split1, '\0', sizeof(split1)); memset(split2, '\0', sizeof(split2)); uri_decode(split1, sizeof(split1), work_buf, sizeof(work_buf) ); strcpy(work_buf, split1); // 最初に登場する'&'で分割 ret = sentence_split(work_buf, '&', split1, split2 ); if ( ret == 0 ) // 分割成功 { strncpy(work_buf, split2, sizeof(work_buf)); } else if (strlen(work_buf) > 0) // まだwork_bufに中身ある? { strncpy( split1, work_buf, sizeof(split1)); strncpy( work_buf, "", sizeof(work_buf)); } else // 処理終了 { break; } // ------------------------------------- // GETした内容 解析開始 // 超安直。いいのかこんな比較で。 // ------------------------------------- // URIデコード // uri_decode(work_buf2, sizeof(work_buf2), split1, sizeof(split1) ); strcpy(work_buf2, split1); // "page="あるか調査。 if (strncasecmp( work_buf2, "page=", strlen("page=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 http_recv_info_p->page = atoi(work_buf2); } continue; } // "menupage="あるか調査。 if (strncasecmp( work_buf2, "menupage=", strlen("menupage=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 http_recv_info_p->menupage = atoi(work_buf2); } continue; } // "title=" DVD title selection if (strncasecmp( work_buf2, "title=", strlen("title=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 http_recv_info_p->title = atoi(work_buf2); } continue; } if (strncasecmp( work_buf2, "width=", strlen("width=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 global_param.target_jpeg_width = atoi(work_buf2); } continue; } if (strncasecmp( work_buf2, "height=", strlen("height=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 global_param.target_jpeg_height = atoi(work_buf2); } continue; } // "action="あるか調査。 if (strncasecmp( work_buf2, "action=", strlen("action=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->action, work_buf2, sizeof(http_recv_info_p->action)); continue; } // "type=" allplay list type if (strncasecmp( work_buf2, "type=movie", strlen("type=movie") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_MOVIE; continue; } if (strncasecmp( work_buf2, "type=music", strlen("type=music") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_MUSIC; continue; } if (strncasecmp( work_buf2, "type=photo", strlen("type=photo") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_JPEG; continue; } if (strncasecmp( work_buf2, "type=soundtrack", strlen("type=soundtrack") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_MUSICLIST; continue; } if (strncasecmp( work_buf2, "type=slideshow", strlen("type=slideshow") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_PLAYLIST; continue; } // "option="あるか調査 if (strncasecmp( work_buf2, "option=", strlen("option=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->option, work_buf2, sizeof(http_recv_info_p->option)); continue; } // "alias="あるか調査 if (strncasecmp( work_buf2, "alias=", strlen("alias=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->alias, work_buf2, sizeof(http_recv_info_p->alias)); if (strncasecmp(http_recv_info_p->alias, "movie", strlen("movie")) == 0) http_recv_info_p->default_file_type = TYPE_MOVIE; else if (strncasecmp(http_recv_info_p->alias, "music", strlen("music")) == 0) http_recv_info_p->default_file_type = TYPE_MUSIC; else if (strncasecmp(http_recv_info_p->alias, "photo", strlen("photo")) == 0) http_recv_info_p->default_file_type = TYPE_JPEG; else http_recv_info_p->default_file_type = TYPE_UNKNOWN; continue; } if (strncasecmp( work_buf2, "lsearch=", strlen("lsearch=") ) == 0 ) { cut_before_character(work_buf2, '='); strcpy(http_recv_info_p->lsearch, work_buf2); strcpy(http_recv_info_p->recv_uri, work_buf2); continue; } // "search= if (strncasecmp( work_buf2, "search", strlen("search") ) == 0 ) { if (strncasecmp(work_buf2, "search_movie", strlen("search_movie")) == 0) { http_recv_info_p->search_type = TYPE_MOVIE; strcpy(http_recv_info_p->search_str, "_movie"); http_recv_info_p->default_file_type = TYPE_MOVIE; // printf("search movie for "); } else if (strncasecmp(work_buf2, "search_music", strlen("search_music")) == 0) { http_recv_info_p->search_type = TYPE_MUSIC; strcpy(http_recv_info_p->search_str, "_music"); http_recv_info_p->default_file_type = TYPE_MUSIC; // printf("search music for "); } else if (strncasecmp(work_buf2, "search_photo", strlen("search_photo")) == 0) { http_recv_info_p->search_type = TYPE_JPEG; strcpy(http_recv_info_p->search_str, "_photo"); http_recv_info_p->default_file_type = TYPE_JPEG; // printf("search photo for "); } else if (strncasecmp(work_buf2, "search_all", strlen("search_all")) == 0) { http_recv_info_p->search_type = TYPE_UNKNOWN; strcpy(http_recv_info_p->search_str, "_all"); http_recv_info_p->default_file_type = TYPE_UNKNOWN; // printf("search all for "); } else continue; cut_before_character(work_buf2, '='); strncpy(http_recv_info_p->search, work_buf2, sizeof(http_recv_info_p->search)); if (http_recv_info_p->search[0] == '\0') // everything qualifies strcpy(http_recv_info_p->search, ".*"); // printf("%s\n", http_recv_info_p->search); continue; } // "sort="あるか調査 if (strncasecmp( work_buf2, "sort=", strlen("sort=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->sort, work_buf2, sizeof(http_recv_info_p->sort)); continue; } // "dvdopt="あるか調査 if (strncasecmp( work_buf2, "dvdopt=", strlen("dvdopt=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->dvdopt, work_buf2, sizeof(http_recv_info_p->dvdopt)); continue; } // "focus="あるか調査 if (strncasecmp( work_buf2, "focus=", strlen("focus=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->focus, work_buf2, sizeof(http_recv_info_p->focus)); continue; } } } debug_log_output("http_recv_info_p->page = '%d'", http_recv_info_p->page); debug_log_output("http_recv_info_p->title = '%d'", http_recv_info_p->title); debug_log_output("http_recv_info_p->action = '%s'", http_recv_info_p->action); debug_log_output("http_recv_info_p->option = '%s'", http_recv_info_p->option); debug_log_output("http_recv_info_p->dvdopt = '%s'", http_recv_info_p->dvdopt); // URIデコード cut_after_character(line_buf, '?'); uri_decode(work_buf, sizeof(work_buf), line_buf, sizeof(line_buf) ); strncpy(line_buf, work_buf, sizeof(line_buf)); debug_log_output("URI(decoded):'%s'\n", line_buf); convert_language_code(line_buf, work_buf, sizeof(work_buf), CODE_AUTO, CODE_EUC); debug_log_output("URI(decoded,euc,FYI):'%s'\n", work_buf); // 構造体に保存 if (http_recv_info_p->lsearch[0] == '\0') strncpy(http_recv_info_p->recv_uri, line_buf, sizeof(http_recv_info_p->recv_uri)); continue; } // User-agent切り出し if ( strncasecmp(line_buf, HTTP_USER_AGENT, strlen(HTTP_USER_AGENT) ) == 0 ) { // ':'より前を切る cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); // 構造体に保存 strncpy( http_recv_info_p->user_agent, line_buf, sizeof(http_recv_info_p->user_agent)); // Set the skin name based on user agent, if desired for(j=0; j<global_param.alternate_skin_count; j++) { debug_log_output("Checking for '%s'", global_param.alternate_skin_match[j]); if(strstr(line_buf, global_param.alternate_skin_match[j]) != NULL) { strcpy(global_param.skin_name, global_param.alternate_skin_name[j]); debug_log_output("User agent matches alternate skin '%s'", global_param.skin_name); break; } } continue; } // Rangeあるかチェック if ( strncasecmp(line_buf, HTTP_RANGE, strlen(HTTP_RANGE) ) == 0 ) { debug_log_output("%s Detect.\n", HTTP_RANGE); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); // recv_range にRangeの中身保存 strncpy(http_recv_info_p->recv_range, line_buf, sizeof(http_recv_info_p->recv_range)); // '=' より前を切る cut_before_character(line_buf, '='); // '-'で前後に分割。 sentence_split(line_buf, '-', work_buf, work_buf2); debug_log_output("work_buf='%s'\n", work_buf); debug_log_output("work_buf2='%s'\n", work_buf2); // 値を文字列→数値変換 http_recv_info_p->range_start_pos = strtoull(work_buf, NULL, 10); if ( strlen(work_buf2) > 0 ) { http_recv_info_p->range_end_pos = strtoull(work_buf2, NULL, 10); } debug_log_output("range_start_pos=%d\n", http_recv_info_p->range_start_pos); debug_log_output("range_end_pos=%d\n", http_recv_info_p->range_end_pos); continue; } // Hostあるかチェック if ( strncasecmp(line_buf, HTTP_HOST, strlen(HTTP_HOST) ) == 0 ) { debug_log_output("%s Detect.\n", HTTP_HOST); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); strncpy(http_recv_info_p->recv_host, line_buf, sizeof(http_recv_info_p->recv_host)); if(NULL == strchr(http_recv_info_p->recv_host, ':')) { debug_log_output("CLIENT BUG: Host header field was missing port number - fixing"); snprintf(http_recv_info_p->recv_host + strlen(http_recv_info_p->recv_host), sizeof(http_recv_info_p->recv_host)-1, ":%d", global_param.server_port); debug_log_output("%s '%s'", HTTP_HOST, http_recv_info_p->recv_host); } continue; } if (strncasecmp(line_buf, HTTP_AUTHORIZATION, strlen(HTTP_AUTHORIZATION)) == 0) { debug_log_output("%s Detect.\n", HTTP_AUTHORIZATION); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); if (strncmp(line_buf, "Basic ", 6)) { debug_log_output("received '%s', is not supported.", line_buf); continue; } strncpy(http_recv_info_p->passwd, line_buf + 6, sizeof(http_recv_info_p->passwd)); continue; } // Content-Lengthあるかチェック if ( strncasecmp(line_buf, HTTP_CONTENT_LENGTH_STR, strlen(HTTP_CONTENT_LENGTH_STR) ) == 0 ) { debug_log_output("%s Detect.\n", HTTP_CONTENT_LENGTH_STR); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); /* recv_content_length は わざと long です. */ http_recv_info_p->recv_content_length = strtol(line_buf, NULL, 10); debug_log_output("Content-Length: %ld", http_recv_info_p->recv_content_length); continue; } } return result; }
static int parse_file (FILE * in, FILE * out, IspellMode_t mode, int countLines, gchar *dictionary) { EnchantBroker * broker; EnchantDict * dict; GString * str, * word = NULL; GSList * tokens, *token_ptr; gchar * lang; size_t pos, lineCount = 0; gboolean was_last_line = FALSE, corrected_something = FALSE, terse_mode = FALSE; if (mode == MODE_A) print_version (out); if (dictionary) { lang = convert_language_code (dictionary); } else { lang = enchant_get_user_language(); if(!lang) return 1; } /* Enchant will get rid of useless trailing garbage like de_DE@euro or de_DE.ISO-8859-15 */ broker = enchant_broker_init (); dict = enchant_broker_request_dict (broker, lang); if (!dict) { fprintf (stderr, "Couldn't create a dictionary for %s\n", lang); g_free (lang); enchant_broker_free (broker); return 1; } g_free (lang); str = g_string_new (NULL); while (!was_last_line) { gboolean mode_A_no_command = FALSE; was_last_line = consume_line (in, str); if (countLines) lineCount++; if (str->len) { corrected_something = FALSE; if (mode == MODE_A) { switch (*str->str) { case '&': /* Insert uncapitalised in personal word list */ if (str->len > 1) { gunichar c = g_utf8_get_char_validated(str->str + 1, str->len); if (c > 0) { str = g_string_erase(str, 1, g_utf8_next_char(str->str + 1) - (str->str + 1)); g_string_insert_unichar(str, 1, g_unichar_tolower(c)); } } /* FALLTHROUGH */ case '*': /* Insert in personal word list */ if (str->len == 1) goto empty_word; enchant_dict_add(dict, str->str + 1, -1); break; case '@': /* Accept for this session */ if (str->len == 1) goto empty_word; enchant_dict_add_to_session(dict, str->str + 1, -1); break; case '%': /* Exit terse mode */ terse_mode = FALSE; break; case '!': /* Enter terse mode */ terse_mode = TRUE; break; /* Ignore these commands */ case '#': /* Save personal word list (enchant does this automatically) */ case '+': /* LaTeX mode */ case '-': /* nroff mode [default] */ case '~': /* change string character type (enchant is fixed to UTF-8) */ case '`': /* Enter verbose-correction mode */ break; case '$': /* Save correction for rest of session [aspell extension] */ { /* Syntax: $$ra <MISSPELLED>,<REPLACEMENT> */ gchar *prefix = "$$ra "; if (g_str_has_prefix(str->str, prefix)) { gchar *comma = g_utf8_strchr(str->str, -1, (gunichar)','); char *mis = str->str + strlen(prefix); char *cor = comma + 1; ssize_t mis_len = comma - mis; ssize_t cor_len = strlen(str->str) - (cor - str->str); enchant_dict_store_replacement(dict, mis, mis_len, cor, cor_len); } } break; case '^': /* ^ is used as prefix to prevent interpretation of original first character as a command */ /* FALLTHROUGH */ default: /* A word or words to check */ mode_A_no_command = TRUE; break; empty_word: fprintf (out, "Error: The word \"\" is invalid. Empty string.\n"); } } if (mode != MODE_A || mode_A_no_command) { token_ptr = tokens = tokenize_line (str); if (tokens == NULL) putc('\n', out); while (tokens != NULL) { corrected_something = TRUE; word = (GString *)tokens->data; tokens = tokens->next; pos = GPOINTER_TO_INT(tokens->data); tokens = tokens->next; if (mode == MODE_A) do_mode_a (out, dict, word, pos, lineCount, terse_mode); else if (mode == MODE_L) do_mode_l (out, dict, word, lineCount); g_string_free(word, TRUE); } if (token_ptr) g_slist_free (token_ptr); } } if (mode == MODE_A && corrected_something) { fwrite ("\n", 1, 1, out); } g_string_truncate (str, 0); fflush (out); } enchant_broker_free_dict (broker, dict); enchant_broker_free (broker); g_string_free (str, TRUE); return 0; }
int http_proxy_response(int accept_socket, HTTP_RECV_INFO *http_recv_info_p) { const char *HTTP_RECV_CONTENT_TYPE = "Content-type: text/html"; const char *HTTP_RECV_CONTENT_LENGTH = "Content-Length: "; const char *HTTP_RECV_LOCATION = "Location: "; char *p_target_host_name; char *p_uri_string; char send_http_header_buf[2048]; char line_buf[MAX_LINE][LINE_BUF_SIZE + 5]; char proxy_pre_string[2048]; char base_url[2048]; char *p_url; char *p; char *p_auth = NULL; int port = 80; int sock; off_t content_length = 0; int len = 0; int line = 0; int i; int content_is_html = 0; p_uri_string = http_recv_info_p->request_uri; if (!strncmp(p_uri_string, "/-.-playlist.pls?", 17)) { char buff[FILENAME_MAX]; if (p_uri_string[17] == '/') { snprintf(buff, sizeof(buff), "http://%s%s" , http_recv_info_p->recv_host, p_uri_string+17); } else { strncpy(buff, p_uri_string+17, sizeof(buff)); } replace_character((char*)buff, ".pls", ""); return 0;//http_uri_to_scplaylist_create(accept_socket, (char*)buff); } if (strncmp(p_uri_string, "/-.-http://", 11)) { return -1; } if (!global_param.flag_allow_proxy) { return -1; } strncpy(base_url, p_uri_string, 2048); p = strrchr(base_url, '/'); p[1] = '\0'; p_target_host_name = p_uri_string + 11; p_url = strchr(p_target_host_name, '/'); if (p_url == NULL) return -1; *p_url++ = '\0'; strncpy(proxy_pre_string, p_uri_string, 2048); p = strchr(p_target_host_name, '@'); if (p != NULL) { // there is a user name. p_auth = p_target_host_name; p_target_host_name = p + 1; *p = '\0'; } p = strchr(p_target_host_name, ':'); if (p != NULL) { port = atoi(p+1); *p = '\0'; } debug_log_output("proxy:target_host_name: %s", p_target_host_name); debug_log_output("proxy:authenticate: %s", p_auth ? p_auth : "NULL"); debug_log_output("proxy:url: %s", p_url); debug_log_output("proxy:prestring: %s", proxy_pre_string); debug_log_output("proxy:base_url: %s", base_url); debug_log_output("proxy:port: %d", port); p = send_http_header_buf; if( http_recv_info_p->isGet == 1 ){ p += sprintf((char*)p, "GET /%s HTTP/1.0\r\n", p_url); }else if ( http_recv_info_p->isGet == 2 ){ p += sprintf((char*)p, "HEAD /%s HTTP/1.0\r\n", p_url); } p += sprintf((char*)p, "Host: %s:%u\r\n", p_target_host_name, port); if (global_param.user_agent_proxy_override[0]) { p += sprintf((char*)p, "User-agent: %s\r\n", global_param.user_agent_proxy_override); } else { if (http_recv_info_p->user_agent[0]) { p += sprintf((char*)p, "User-agent: %s\r\n", http_recv_info_p->user_agent); } else { p += sprintf((char*)p, "User-agent: %s\r\n", SERVER_NAME); } } p += sprintf(p, "Accept: */*\r\n"); p += sprintf(p, "Connection: close\r\n"); if (http_recv_info_p->range_start_pos) { p += sprintf((char*)p, "Range: bytes="); p += sprintf((char*)p, "%zu-", http_recv_info_p->range_start_pos); if (http_recv_info_p->range_end_pos) { p += sprintf((char*)p, "%zu", http_recv_info_p->range_end_pos); } p += sprintf(p, "\r\n"); } if (p_auth != NULL) { p += sprintf((char*)p, "Authorization: Basic %s\r\n", base64((unsigned char*)p_auth)); } p += sprintf(p, "\r\n"); sock = sock_connect((char*)p_target_host_name, port); if (sock < 0) { debug_log_output("error: %s", strerror(errno)); debug_log_output("sock: %d", sock); return -1; } set_nonblocking_mode(sock, 0); /* blocking mode */ set_nonblocking_mode(accept_socket, 0); /* blocking mode */ write(sock, send_http_header_buf, strlen(send_http_header_buf)); debug_log_output("================= send to proxy\n"); debug_log_output("%s", send_http_header_buf); debug_log_output("=================\n"); //TODO ここが404や400の可能性あり for (line = 0; line < MAX_LINE; line ++) { char work_buf[LINE_BUF_SIZE + 10]; memset(line_buf[line], 0, LINE_BUF_SIZE + 5); len = line_receive(sock, line_buf[line], LINE_BUF_SIZE + 1); if (len < 0) break; debug_log_output("recv html: '%s' len = %d", ((len)?(char*)line_buf[line]:""), len); line_buf[line][len++] = '\r'; line_buf[line][len++] = '\n'; line_buf[line][len] = '\0'; if (!strncasecmp(line_buf[line], HTTP_RECV_CONTENT_TYPE, strlen(HTTP_RECV_CONTENT_TYPE))) { int n; content_is_html = 1; n = strlen(HTTP_RECV_CONTENT_TYPE); line_buf[line][n++] = '\r'; line_buf[line][n++] = '\n'; line_buf[line][n] = '\0'; }else if (!strncasecmp(line_buf[line], HTTP_RECV_CONTENT_LENGTH, strlen(HTTP_RECV_CONTENT_LENGTH))) { content_length = strtoull((char*)(line_buf[line] + strlen(HTTP_RECV_CONTENT_LENGTH)), NULL, 0); }else if (!strncasecmp(line_buf[line], HTTP_RECV_LOCATION, strlen(HTTP_RECV_LOCATION))) { strcpy(work_buf, line_buf[line]); sprintf((char*)line_buf[line], "Location: /-.-%s", work_buf + strlen(HTTP_RECV_LOCATION)); }else if ( strstr( line_buf[line],"charset") ){ if ( strstr( line_buf[line], "EUC-JP" )){ replace_character( (char*)line_buf[line], "EUC-JP", "UTF-8"); }else if ( strstr ( line_buf[line], "Shift_JIS" )) { replace_character( (char*)line_buf[line], "Shift_JIS", "UTF-8"); } } if (len <= 2) { line++; break; } } if (len < 0 ) { debug_log_output("CLOSED-C"); close(sock); return -1; } if (content_is_html) { char *p, *q; char *new_p, *r; char work_buf[LINE_BUF_SIZE + 10]; char work_buf2[LINE_BUF_SIZE * 2]; char *link_pattern = (char*)"<A HREF="; int flag_conv_html_code = 1; for (i=0; i<line; i++) { //長さは不定なので送らない if (!strncasecmp(line_buf[i], HTTP_RECV_CONTENT_LENGTH, strlen(HTTP_RECV_CONTENT_LENGTH))) continue; //*q = '\0'; p = work_buf; q = work_buf2; if (flag_conv_html_code) { convert_language_code(line_buf[i], work_buf, LINE_BUF_SIZE, CODE_AUTO, global_param.client_language_code); } //strcpy( work_buf, line_buf[i]); // write(accept_socket, line_buf[i], strlen(line_buf[i])); // debug_log_output("sent html: '%s' len = %d", line_buf[i], strlen(line_buf[i])); write(accept_socket, work_buf, strlen(line_buf[i])); debug_log_output("sent html: '%s' len = %d", work_buf, strlen(work_buf)); } debug_log_output("sent header"); //write(accept_socket, "debug:--\n", strlen("debug:--\n")); while (1) { char rep_str[1024]; memset(work_buf, 0, LINE_BUF_SIZE); len = line_receive(sock, work_buf, LINE_BUF_SIZE); if (len < 0) break; debug_log_output("recv html: '%s' len = %d", work_buf, len); work_buf[len++] = '\r'; work_buf[len++] = '\n'; work_buf[len] = '\0'; if (my_strcasestr(work_buf, "Content-Type") != NULL) { // Content-Type があったら // 漢字コードの変換をやめる // flag_conv_html_code = 0; if ( strstr( work_buf, "EUC-JP" )){ replace_character( (char*)work_buf, "EUC-JP", "UTF-8"); }else if ( strstr ( work_buf, "Shift_JIS" )) { replace_character( (char*)work_buf, "Shift_JIS", "UTF-8"); } } p = work_buf; q = work_buf2; memset(q, 0, sizeof(work_buf2)); /* * HTML中に <A HREF="..."> があったら、プロクシを経由するように * たとえば <A HREF="/-.-http://www.yahoo.co.jp/"> のように変換する * もし、ファイルがストリーム可能そうであれば、VOD="0" も追加する。 * * 問題点: * タグの途中に改行があると失敗するだろう. * 面倒なのでたいした置換はしていない * 惰性で書いたので汚い。だれか修正して。 */ link_pattern = (char*)"<A HREF="; while ((new_p = my_strcasestr(p, link_pattern)) != NULL) { int l = new_p - p + strlen(link_pattern); char *tmp; MIME_LIST_T *mlt = NULL; strncpy(q, p, l); q += l; p += l; /* i.e., p = new_p + strlen(link_pattern); */ r = strchr(p, '>'); if (r == NULL) continue; *r = '\0'; if (*p == '"') *q++ = *p++; if ((tmp = strchr(p, '"')) != NULL || (tmp = strchr(p, ' ')) != NULL) { mlt = mime_list; while (mlt->mime_name != NULL) { if (*(tmp - strlen(mlt->file_extension) - 1) == '.' && !strncasecmp(tmp - strlen(mlt->file_extension), mlt->file_extension, strlen(mlt->file_extension))) { break; } mlt++; } } //if (flag_pc && mlt != NULL && mlt->stream_type == TYPE_STREAM) { // q += sprintf((char*)q, "/-.-playlist.pls?http://%s", http_recv_info_p->recv_host); //} if (*p == '/') { q += sprintf(q, "%s%s", proxy_pre_string, p); } else if (!strncmp(p, "http://", 7)) { q += sprintf(q, "/-.-%s", p); } else { q += sprintf((char*)q, "%s%s", base_url, p); //q += sprintf((char*)q, "%s", p); } if (mlt != NULL && mlt->stream_type == TYPE_STREAM) { q += sprintf(q, " vod=\"0\""); } *q++ = '>'; p = r + 1; } while (*p) *q++ = *p++; *q = '\0'; /* * HTML中に SRC="..." があったら、プロクシを経由するように変換する * * 問題点: * タグの途中に改行があると失敗するだろう. * 変数使いまわしたので、融通が効かない。 * だれか修正して。 */ p = work_buf2; q = work_buf; memset(q, 0, sizeof(work_buf)); link_pattern = (char*)"SRC="; while ((new_p = my_strcasestr(p, link_pattern)) != NULL) { int l = new_p - p + strlen(link_pattern); strncpy(q, p, l); q += l; p += l; /* i.e., p = new_p + strlen(link_pattern); */ if (*p == '"') *q++ = *p++; if (*p == '/') { q += sprintf(q, "%s", proxy_pre_string); } else if (!strncmp(p, "http://", 7)) { q += sprintf(q, "/-.-"); } else { q += sprintf(q, "%s", base_url); //q += sprintf(q, "%s", p); } } while (*p) *q++ = *p++; *q = '\0'; p = work_buf; q = work_buf2; if (flag_conv_html_code) { convert_language_code(p, q, LINE_BUF_SIZE, CODE_AUTO, global_param.client_language_code); //strcpy( q,p); p = q; } snprintf(rep_str, sizeof(rep_str), "|http://%s/-.-http://" , http_recv_info_p->recv_host); replace_character((char*)p, "|http://", rep_str); write(accept_socket, p, strlen(p)); debug_log_output("sent html: %s", p); } } else { for (i=0; i<line; i++) { write(accept_socket, line_buf[i], strlen(line_buf[i])); } if( http_recv_info_p->isGet == 1 ){ return ( copy_descriptors(sock, accept_socket, (size_t)content_length) ); //NULL , //(char*)http_recv_info_p->recv_uri, // http_recv_info_p->range_start_pos)); } } sClose(sock); return 0; }
// ************************************************************************** // HTTPヘッダを受信して解析する。 // // 処理するのはGETのみ。GET以外のメソッドが来たらエラー // 今のところ、URIとuser_agent、Range、Hostを解析。 // URIは、URIデコードもやる。 // // return: 0 正常終了 // return: 0以外 エラー // ************************************************************************** static int http_header_receive(int accept_socket, HTTP_RECV_INFO *http_recv_info_p) { int result = 0; int recv_len; char line_buf[1024]; // 大きめに。 char work_buf[1024]; char work_buf2[1024]; char split1[1024]; char split2[1024]; int ret; int i; // ================================ // 1行づつ HTTPヘッダを受信 // ================================ for (i=0;;i++){ // 1行受信 実行。 recv_len = line_receive(accept_socket, line_buf, sizeof(line_buf)); // 受信した内容をチェック。 if ( recv_len == 0 ){ // 空行検知。ヘッダ受信終了。 break; }else if ( recv_len < 0 ){ // 受信失敗 return ( -1 ); } // debug. 受信したヘッダ表示 debug_log_output("'%s'(%d byte)\n", line_buf, recv_len ); // -------------------------- // GETメッセージチェック // -------------------------- if ( i == 0 ){ // 1行目のみチェック debug_log_output("%d:URI Check start.'%s'\n", accept_socket,line_buf); // GETある? if ( strstr(line_buf, "GET") != NULL ){ http_recv_info_p->isGet = 1; }else if ( strstr(line_buf, "HEAD") != NULL ){ http_recv_info_p->isGet = 2; }else if ( strstr(line_buf, "POST") != NULL ){ http_recv_info_p->isGet = 3; }else{ debug_log_output("'GET' not found. error.%d",accept_socket); return ( -1 ); } // 最初のスペースまでを削除。 cut_before_character(line_buf, ' '); // 次にスペースが出てきたところの後ろまでを削除。 cut_after_character(line_buf, ' '); // =========================== // GETオプション部解析 // =========================== // REQUEST_URI用・Proxy用に値を保存 strncpy(http_recv_info_p->request_uri, line_buf, sizeof(http_recv_info_p->request_uri)); // '?'が存在するかチェック。 if ( strchr(line_buf, '?') != NULL ){ strncpy(work_buf, line_buf, sizeof(work_buf)); // '?'より前をカット cut_before_character(work_buf, '?' ); while ( 1 ){ memset(split1, 0, sizeof(split1)); memset(split2, 0, sizeof(split2)); // 最初に登場する'&'で分割 ret = sentence_split(work_buf, '&', split1, split2 ); if ( ret == 0 ){ // 分割成功 strncpy(work_buf, split2, sizeof(work_buf)); }else if (strlen(work_buf) > 0){ // まだwork_bufに中身ある? strncpy( split1, work_buf, sizeof(split1)); strncpy( work_buf, "", sizeof(work_buf)); }else{ // 処理終了 break; } // ------------------------------------- // GETした内容 解析開始 // 超安直。いいのかこんな比較で。 // ------------------------------------- // URIデコード uri_decode(work_buf2, sizeof(work_buf2), split1, sizeof(split1) ); // "action="あるか調査。 if (strncasecmp( work_buf2, "action=", strlen("action=") ) == 0 ){ // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->action, work_buf2, sizeof(http_recv_info_p->action)); continue; } } } debug_log_output("http_recv_info_p->action = '%s'", http_recv_info_p->action); // URIデコード cut_after_character(line_buf, '?'); uri_decode(work_buf, sizeof(work_buf), line_buf, sizeof(line_buf) ); strncpy(line_buf, work_buf, sizeof(line_buf)); debug_log_output("URI(decoded):'%s'\n", line_buf); convert_language_code(line_buf, work_buf, sizeof(work_buf), CODE_AUTO, CODE_EUC); debug_log_output("URI(decoded,euc,FYI):'%s'\n", work_buf); // 構造体に保存 strncpy(http_recv_info_p->recv_uri, line_buf, sizeof(http_recv_info_p->recv_uri)); //httpから始まってる場合には、http://以降の最初の'/'の前でカット if( strncmp(http_recv_info_p->recv_uri,"http://",7)==0){ char* ptr = strstr(http_recv_info_p->recv_uri+7,"/"); if( ptr ){ strcpy(http_recv_info_p->recv_uri,ptr); } } continue; } // User-agent切り出し if ( strncasecmp(line_buf, HTTP_USER_AGENT, strlen(HTTP_USER_AGENT) ) == 0 ){ debug_log_output("User-agent: Detect.\n"); // ':'より前を切る cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); // 構造体に保存 strncpy( http_recv_info_p->user_agent, line_buf, sizeof(http_recv_info_p->user_agent)); continue; } // Rangeあるかチェック if ( strncasecmp(line_buf, HTTP_RANGE, strlen(HTTP_RANGE) ) == 0 ){ debug_log_output("%s Detect.\n", HTTP_RANGE); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); // recv_range にRangeの中身保存 strncpy(http_recv_info_p->recv_range, line_buf, sizeof(http_recv_info_p->recv_range)); // '=' より前を切る cut_before_character(line_buf, '='); // '-'で前後に分割。 sentence_split(line_buf, '-', work_buf, work_buf2); debug_log_output("wrok_buf='%s'\n", work_buf); debug_log_output("wrok_buf2='%s'\n", work_buf2); // 値を文字列→数値変換 http_recv_info_p->range_start_pos = strtoull(work_buf, NULL, 10); if ( strlen(work_buf2) > 0 ){ http_recv_info_p->range_end_pos = strtoull(work_buf2, NULL, 10); } debug_log_output("range_start_pos=%d\n", http_recv_info_p->range_start_pos); debug_log_output("range_end_pos=%d\n", http_recv_info_p->range_end_pos); continue; } // Hostあるかチェック if ( strncasecmp(line_buf, HTTP_HOST, strlen(HTTP_HOST) ) == 0 ){ // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); strncpy(http_recv_info_p->recv_host, line_buf, sizeof(http_recv_info_p->recv_host)); debug_log_output("%s Detect. %s '%s'", HTTP_HOST, HTTP_HOST, http_recv_info_p->recv_host); continue; } // Content-Lengthあるかチェック if ( strncasecmp(line_buf, HTTP_CONTENT_LENGTH1, strlen(HTTP_CONTENT_LENGTH1) ) == 0 ){ // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); strncpy(http_recv_info_p->content_length, line_buf, sizeof(http_recv_info_p->content_length)); debug_log_output("%s Detect. %s '%s'", HTTP_CONTENT_LENGTH1, HTTP_CONTENT_LENGTH1, http_recv_info_p->content_length); continue; } // Content-TYPEあるかチェック if ( strncasecmp(line_buf, HTTP_CONTENT_TYPE1, strlen(HTTP_CONTENT_TYPE1) ) == 0 ){ // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); strncpy(http_recv_info_p->content_type, line_buf, sizeof(http_recv_info_p->content_type)); debug_log_output("%s Detect. %s '%s'", HTTP_CONTENT_TYPE1, HTTP_CONTENT_TYPE1, http_recv_info_p->content_type); continue; } } return result; }