示例#1
0
文件: wizd_http.c 项目: birkirb/wizd
// **************************************************************************
// * サーバ HTTP処理部
// **************************************************************************
void 	server_http_process(int accept_socket)
{
	int					result;
	HTTP_RECV_INFO	http_recv_info;	//HTTP受信情報保存構造体
	int				i;
	int				flag_allow_user_agent_check;
	int				found;

	memset(&http_recv_info, 0, sizeof(http_recv_info));


	// ----------------------------------------
	// HTTP リクエストヘッダ受信
	// ----------------------------------------
	debug_log_output("HTTP Header receive start!\n");

	result = http_header_receive(accept_socket,  &http_recv_info);
	if ( result != 0 ) // エラーチェック
	{
		// エラーメッセージ
		debug_log_output("http_header_receive() Error. result=%d\n", result);
		// ソケットクローズ
		close(accept_socket);
		return;
	}
	debug_log_output("HTTP Header receive end!\n");

	debug_log_output("recv_uri:'%s'\n", http_recv_info.recv_uri);
	debug_log_output("user_agent:'%s'\n", http_recv_info.user_agent);

	debug_log_output("range_start_pos=%lld\n", http_recv_info.range_start_pos);
	debug_log_output("range_end_pos=%lld\n", http_recv_info.range_end_pos);

	if (http_recv_info.passwd[0]) {
		debug_log_output("http passwd:'%s'\n", http_recv_info.passwd);
	}

	// ==========================
	// = User-Agent チェック
	// ==========================

	flag_allow_user_agent_check = 0;

	if ( strlen(allow_user_agent[0].user_agent)  == 0 ) // User-Agnet指示が無し。
	{
		debug_log_output("user_agent: allow_user_agent No List. All Allow.");
		flag_allow_user_agent_check = 1; // OK
	}
	else
	{
		// User-Agent チェック実行
		for ( i=0; i<ALLOW_USER_AGENT_LIST_MAX; i++)
		{
			if ( strlen(allow_user_agent[i].user_agent)  == 0 )
			{
				break;
			}

			// 一致チェック
			debug_log_output("user_agent: Check[%d] '%s' in '%s'",i, allow_user_agent[i].user_agent, http_recv_info.user_agent);
			if ( strstr( http_recv_info.user_agent, allow_user_agent[i].user_agent ) != NULL )
			{
				debug_log_output("user_agent: '%s' OK.", allow_user_agent[i].user_agent );
				flag_allow_user_agent_check = 1; // 一致。OK
				break;
			}
		}
	}

	if (global_param.http_passwd[0] && !flag_allow_user_agent_check) {
		// パスワードが設定されて、正しければ、User-AgentチェックNGでもOK.
		char *pass, *p;

		pass = base64(global_param.http_passwd);
		if ((p = strchr(pass, '=')) != NULL) {
			*p = '\0';
		}
		if ((p = strchr(http_recv_info.passwd, '=')) != NULL) {
			*p = '\0';
		}

		if (!strcmp(pass, http_recv_info.passwd)) {
			// 一致
			flag_allow_user_agent_check = 1;
		} else {
			// 不一致
			// flag_allow_user_agent_check = 0;

			http_unauthorized_response(accept_socket, &http_recv_info);
			close(accept_socket);
			return ;
		}
	}

	// User-Agentチェック NGならば、ソケットクローズ。終了。
	if ( flag_allow_user_agent_check == 0 )
	{
		debug_log_output("allow_user_agent check. Deny. Socket close.");

		// ソケットクローズ
		close(accept_socket);
		return;
	}

	// クライアントがPCかどうか判断
	http_recv_info.flag_pc = (global_param.user_agent_pc[0]
		&& !strncmp(http_recv_info.user_agent, global_param.user_agent_pc
			, strlen(global_param.user_agent_pc))
	) ? 1 : 0;

	if(global_param.user_agent_pc[0]) {
		debug_log_output("Checking for PC user agent '%s'", global_param.user_agent_pc);
	}
	debug_log_output("flag_pc: %d", http_recv_info.flag_pc);

	// User-Agent
	// HD: 'Syabas/13-14-060414-04-IOD-234-000/04-IOD (uCOS-II v2.05;NOS;KA9Q; Res1280x720-HiColor; TV Res1920x1080; Browser Res1104x656-8bits; www.syabas.com mac_addr=00.a0.b0.65.51.31)'(186 byte)
	// SD: 'Syabas/13-14-060414-04-IOD-234-000/04-IOD (uCOS-II v2.05;NOS;KA9Q; Res624x416-HiColor; TV Res1920x1080; Browser Res624x416-8bits; www.syabas.com mac_addr=00.a0.b0.65.51.31)'

	http_recv_info.flag_hd = (strstr(http_recv_info.user_agent, "Res624x416") == NULL);

	if (!strncmp(http_recv_info.recv_uri, "/-.-", 4)) {
		// proxy
		if (http_proxy_response(accept_socket, &http_recv_info) < 0) {
			http_not_found_response(accept_socket, &http_recv_info);
		}

		// ソケットクローズ
		close(accept_socket);
		return;
	}

	if (path_sanitize(http_recv_info.recv_uri, sizeof(http_recv_info.recv_uri)) == NULL) {
		// BAD REQUEST!
		debug_log_output("BAD REQUEST!");
		http_not_found_response(accept_socket, &http_recv_info);
		close(accept_socket);
		return;
	}
	debug_log_output("sanitized recv_uri: %s", http_recv_info.recv_uri);

	// ----------------------------------------
	// 受け取ったURIの拡張子がrename対象ならばrename
	// ----------------------------------------
	extension_del_rename(http_recv_info.recv_uri, sizeof(http_recv_info.recv_uri));

	// ============================
	// ファイルチェック
	//  種類に応じて分岐
	// ============================
	result = http_file_check(&http_recv_info);
	debug_log_output("http_file_check returns %d\n", result);

	if (result != CGI_TYPE && !strcmp(http_recv_info.request_method, "POST")) {
		debug_log_output("BAD POST REQUEST.");
		http_not_found_response(accept_socket, &http_recv_info);
	}
	else if (result == -2) { // Directory without the trailing slash -> redirect
		char buffer[WIZD_FILENAME_MAX];
		sprintf(buffer, "%s/", http_recv_info.recv_uri);
		http_redirect_response(accept_socket, &http_recv_info, buffer);
	}
	else if ( result < 0 ) // File not found
	{
		http_not_found_response(accept_socket, &http_recv_info);
	}
	else if ( result == GENERAL_FILE_TYPE ) // ファイル実体ならば、実体転送。
	{
		if ( global_param.flag_allow_delete && (strcasecmp(http_recv_info.action, "delete" ) == 0) )
		{
			// ----------------------------------------
			// Delete file
			// ----------------------------------------
			char path[WIZD_FILENAME_MAX];

			debug_log_output("Delete file start!\n");
			debug_log_output("unlink(%s)", http_recv_info.send_filename);
			unlink(http_recv_info.send_filename);
			// Remove any associated bookmarks if they exist
			snprintf(path, sizeof(path), "%s.wizd.bookmark", http_recv_info.send_filename);
			unlink(path);

			// Redirect to directory
			strncpy(path, http_recv_info.recv_uri, sizeof(path));
			cut_after_last_character(path, '/');
			strcat(path, "/");
			http_redirect_response(accept_socket, &http_recv_info, path);
			debug_log_output("Delete file end!\n");
		} else
		// actionに、ImageViewerが指示されている?
		if ( strcasecmp(http_recv_info.action, "ImageView" ) == 0)
		{
			// ----------------------------------------
			// イメージファイルビューアー
			// ----------------------------------------
			debug_log_output("Image Viewer start!\n");
			http_image_viewer(accept_socket, &http_recv_info);
			debug_log_output("Image Viewer end!\n");
		}
		// actionに、SinglePlayが指示されている?
		else if ( strcasecmp(http_recv_info.action, "SinglePlay" ) == 0)
		{
			// ----------------------------------------
			// Musicファイル 単独プレイ
			// ----------------------------------------
			debug_log_output("Single Play start!\n");
			http_music_single_play(accept_socket, &http_recv_info);
			debug_log_output("Single Play end!\n");
		}
#ifdef RESIZE_JPEG
		// actionに、Resizeが指示されている?
		else if ( strcasecmp(http_recv_info.action, "Resize.jpg" ) == 0)
		{
			// ----------------------------------------
			// JPEG Resize
			// ----------------------------------------
			debug_log_output("JPEG Resize start!\n");
			if(http_send_resized_jpeg(accept_socket, &http_recv_info) == 0) {
				// Failed to resize - send the original file as-is
				// (this can happen if we have the wrong file extension)
				http_file_response(accept_socket, &http_recv_info);
			}
			debug_log_output("JPEG Resize end!\n");
		}
#endif
		else if (strcmp(http_recv_info.option, "aviinfo") == 0)
		{
			debug_log_output("got aviinfo option\n");
			http_menu(accept_socket, &http_recv_info);
		}
		else if (strcmp(http_recv_info.option, "mp3info") == 0)
		{
			http_menu(accept_socket, &http_recv_info);
		}
		else // アクションに指定無し。
		{
			// ----------------------------------------
			// ファイルの実体
			// HTTPリクエストヘッダに従ってデータを返信。
			// ----------------------------------------
			found = 0;
			if (global_param.flag_use_index && strstr(http_recv_info.recv_uri, "wizd") != 0 && strstr(http_recv_info.recv_uri, ".htm") != 0) {
				if (http_find_and_replace_html(accept_socket, &http_recv_info)) {
					found = 1;
				}
			}

			if (!found) {
				debug_log_output("HTTP response start!\n");
				http_file_response(accept_socket, &http_recv_info);
				debug_log_output("HTTP response end!\n");
			}
		}

	}
	else if ( result == SVI_TYPE )
	{
		// ----------------------------------------
		// SVIファイル(;´Д`)
		// SVIファイル処理してデータを返信
		// ----------------------------------------

		// actionに、SinglePlayが指示されている?
		if ( strcasecmp(http_recv_info.action, "SinglePlay" ) == 0)
		{
			// ----------------------------------------
			// Musicファイル 単独プレイ
			// ----------------------------------------
			debug_log_output("Single Play start!(SVI)\n");
			http_music_single_play(accept_socket, &http_recv_info);
			debug_log_output("Single Play end!(SVI)\n");
		}
		else // アクションに指定無し。
		{
			debug_log_output("HTTP joint file response start!\n");
			http_joint_file_response(accept_socket, &http_recv_info);
			debug_log_output("HTTP joint file response end!\n");
		}
	}
	else if ( result == PLW_UPL_TYPE )
	{
		// ---------------------------------------------
		// plw/uplファイル(`・ω・´)
		// リストファイルから、プレイリスト生成して返信
		// ---------------------------------------------
		debug_log_output("HTTP wizd play list create and response start!\n");
		http_listfile_to_playlist_create(accept_socket, &http_recv_info);
		debug_log_output("HTTP wizd play list create and response end!\n");
	}
	else if ( result == VOB_TYPE )
	{
		// ---------------------------------------------
		// vobファイル 連結
		// vobを連結して返信
		// ---------------------------------------------

		// actionに、SinglePlayが指示されている?
		if ( strcasecmp(http_recv_info.action, "SinglePlay" ) == 0)
		{
			// ----------------------------------------
			// Musicファイル 単独プレイ
			// ----------------------------------------
			debug_log_output("Single Play start!(VOB)\n");
			http_music_single_play(accept_socket, &http_recv_info);
			debug_log_output("Single Play end!(VOB)\n");
		}
		else // アクションに指定無し。
		{
			debug_log_output("HTTP vob file response start!\n");
			http_vob_file_response(accept_socket, &http_recv_info);
			debug_log_output("HTTP vob file response end!\n");
		}
	}
	else if ( result == CGI_TYPE )
	{
		// ---------------------------------------------
		// cgiファイル
		// cgiを実行して結果を返信
		// ---------------------------------------------
		debug_log_output("HTTP CGI response start!\n");
		http_cgi_response(accept_socket, &http_recv_info);
		debug_log_output("HTTP CGI response end!\n");
	}
	else if ( result == ISO_TYPE )
	{ // ISO file handling
		if ( (strcasecmp(http_recv_info.action, "IsoPlay" ) == 0) ||
			(strcasecmp(http_recv_info.action, "dvdplay" ) == 0) ||
			(strncmp(http_recv_info.action, "showchapters", 12 ) == 0))
		{
			debug_log_output("ISO playlist create start!\n");
			http_menu(accept_socket, &http_recv_info);
			debug_log_output("ISO playlist create end!\n");
		}
		else
		{
			// Start to stream the VOB
			debug_log_output("HTTP ISO file response start!\n");
			http_vob_file_response(accept_socket, &http_recv_info);
			debug_log_output("HTTP ISO file response end!\n");
		}
	}
	else
	{
		// ----------------------------------------
		// ディレクトリ
		// ----------------------------------------

		// actionに、OptionMenuが指示されている?
		if ( strcasecmp(http_recv_info.action, "OptionMenu" ) == 0)
		{
			debug_log_output("HTTP Option menu create.\n");
			http_option_menu(accept_socket, &http_recv_info);
			debug_log_output("HTTP Option menu end.\n");
		}
		else if ( strcasecmp(http_recv_info.action, "copy" ) == 0)
		{
			// --------------------------------------------
			// Copy the default playlist to this directory
			// --------------------------------------------
			char source[WIZD_FILENAME_MAX];
			char dest[WIZD_FILENAME_MAX];
			int fd_source, fd_dest;

			if(http_recv_info.default_file_type == TYPE_MUSICLIST) {
				snprintf(dest, sizeof(dest), "%s/%s", http_recv_info.send_filename, DEFAULT_MUSICLIST);
				snprintf(source, sizeof(source), "%s/%s/%s", global_param.skin_root, global_param.skin_name, DEFAULT_MUSICLIST);
			} else {
				snprintf(dest, sizeof(dest), "%s/%s", http_recv_info.send_filename, DEFAULT_PHOTOLIST);
				snprintf(source, sizeof(source), "%s/%s/%s", global_param.skin_root, global_param.skin_name, DEFAULT_PHOTOLIST);
			}
			duplex_character_to_unique(source, '/');
			duplex_character_to_unique(dest, '/');

			debug_log_output("Copying '%s' to '%s'", source, dest);

			// Copy the file
			fd_source = open(source, O_RDONLY);
			if(fd_source >= 0) {
				fd_dest = open(dest, O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE);
				if(fd_dest >= 0) {
					while( (i = read(fd_source, source, sizeof(source))) > 0 ) {
						write(fd_dest, source, i);
					}
					close(fd_dest);
				} else {
					debug_log_output("Failed to open destination file");
				}
				close(fd_source);
			} else {
				debug_log_output("Failed to open source file");
			}
			
			// Redirect to the directory
			strncpy(dest, http_recv_info.recv_uri, sizeof(dest));
			cut_after_last_character(dest, '/');
			strcat(dest, "/");
			http_redirect_response(accept_socket, &http_recv_info, dest);
			debug_log_output("Copy playlist end!\n");
		}
		else	// DIRECTORY_TYPE or {wizd,index}.htm{l}
		{
			int	found = 0;

			if (global_param.flag_use_index) {
				if (http_find_and_replace(accept_socket, &http_recv_info))
					found = 1;
			}

			if (!found) {
				debug_log_output("HTTP file menu create.\n");
				http_menu(accept_socket, &http_recv_info);
				debug_log_output("HTTP file menu end.\n");
			}
		}
	}

	// Clean shutdown
	shutdown(accept_socket, SHUT_WR);
 
	for(i=0; i<1 && (read(accept_socket, &result, sizeof(result))>0); i++);



	// ソケットクローズ
	close(accept_socket);

	return;
}
示例#2
0
// **************************************************************************
// * サーバ HTTP処理部
// **************************************************************************
void 	server_http_process(int accept_socket)
{
    FILETYPES		result;
    HTTP_RECV_INFO	http_recv_info;	//HTTP受信情報保存構造体
    int			flag_allow_user_agent_check;
    int                 ret;
    memset(&http_recv_info, 0, sizeof(http_recv_info));
    // ----------------------------------------
    // HTTP リクエストヘッダ受信
    // ----------------------------------------
    debug_log_output("HTTP Header receive start!\n");
    ret = http_header_receive(accept_socket,  &http_recv_info);
    if ( ret != 0 ){ // エラーチェック
        // エラーメッセージ
        debug_log_output("http_header_receive() Error. result=%d\n", ret);
        // ソケットクローズ
        sClose(accept_socket);
        return;
    }
    debug_log_output("recv_uri:'%s'\n", http_recv_info.recv_uri);
    debug_log_output("user_agent:'%s'\n", http_recv_info.user_agent);
    debug_log_output("range_start_pos=%d\n", http_recv_info.range_start_pos);
    debug_log_output("range_end_pos=%d\n", http_recv_info.range_end_pos);
    // ==========================
    // = User-Agent チェック
    // ==========================
    flag_allow_user_agent_check = 0;
    if ( strlen(allow_user_agent[0].user_agent)  == 0 ){ // User-Agnet指示が無し。
        debug_log_output("user_agent: allow_user_agent No List. All Allow.");
        flag_allow_user_agent_check = 1; // OK
    }else{
        // User-Agent チェック実行
        //TODO iはかきつぶしちゃいけないよ。
        for ( int i=0; i<ALLOW_USER_AGENT_LIST_MAX; i++){
            if ( strlen(allow_user_agent[i].user_agent)  == 0 ){
                break;
            }
            // 一致チェック
            debug_log_output("user_agent: Check[%d] '%s' in '%s'",i, allow_user_agent[i].user_agent, http_recv_info.user_agent);
            if ( strstr( http_recv_info.user_agent, allow_user_agent[i].user_agent ) != NULL ){
                debug_log_output("user_agent: '%s' OK.", allow_user_agent[i].user_agent );
                flag_allow_user_agent_check = 1; // 一致。OK
                break;
            }
        }
    }
    // User-Agentチェック NGならば、ソケットクローズ。終了。
    if ( flag_allow_user_agent_check == 0 ){
        debug_log_output("allow_user_agent check. Deny. Socket close.");
        // ソケットクローズ
        sClose(accept_socket);
        return;
    }
    //PROXY判定
    if (!strncmp(http_recv_info.recv_uri, "/-.-", 4)) {
        // proxy
        if (http_proxy_response(accept_socket, &http_recv_info) < 0){
            debug_log_output("error close not found");
            http_not_found_response(accept_socket, &http_recv_info);
        }
        // ソケットクローズ
        sClose(accept_socket);
        return;
    }
    if (path_sanitize(http_recv_info.recv_uri, sizeof(http_recv_info.recv_uri)) == NULL){
        // BAD REQUEST!
        debug_log_output("BAD REQUEST!");
        http_not_found_response(accept_socket, &http_recv_info);
        sClose(accept_socket);
        return;
    }
    debug_log_output("sanitized recv_uri: %s", http_recv_info.recv_uri);
    // ----------------------------------------
    // 受け取ったURIの拡張子がrename対象ならばrename
    // ----------------------------------------
    extension_del_rename(http_recv_info.recv_uri);
    // ============================
    // ファイルチェック
    //  種類に応じて分岐
    // ============================
    result = http_file_check(&http_recv_info);
    if (result == _OPENDIR){ // ディレクトリだが終端が '/' ではない
        char buffer[FILENAME_MAX];
        sprintf(buffer, "%s/", http_recv_info.recv_uri);
        http_redirect_response(accept_socket, &http_recv_info, buffer);
    }else if ( result < _FILE ){ // ファイルが見つからない
        http_not_found_response(accept_socket, &http_recv_info);
    }else if ( result == _FILE ){ // ファイル実体ならば、実体転送。
        // actionに、ImageViewerが指示されている?
        //if ( strcasecmp(http_recv_info.action, "ImageView" ) == 0){
        //    // ----------------------------------------
        //    // イメージファイルビューアー
        //    // ----------------------------------------
        //    debug_log_output("Image Viewer start!\n");
        //    http_image_viewer(accept_socket, &http_recv_info);
        //    debug_log_output("Image Viewer end!\n");
        //    // actionに、SinglePlayが指示されている?
        if ( strcasecmp(http_recv_info.action, "SinglePlay" ) == 0){
            // ----------------------------------------
            // Musicファイル 単独プレイ
            // ----------------------------------------
            debug_log_output("Single Play start!\n");
            //http_music_single_play(accept_socket, &http_recv_info);
            debug_log_output("Single Play end!\n");
        }else{ // アクションに指定無し。
            // ----------------------------------------
            // ファイルの実体
            // HTTPリクエストヘッダに従ってデータを返信。
            // ----------------------------------------
            debug_log_output("HTTP response start!\n");
            http_file_response(accept_socket, &http_recv_info);
            debug_log_output("HTTP response end!\n");
            return;
        }
    }else if ( result == _PLW ){
        // ---------------------------------------------
        // plw/uplファイル(`・ω・´)
        // リストファイルから、プレイリスト生成して返信
        // ---------------------------------------------
        debug_log_output("HTTP wizd play list create and response start!\n");
        //http_listfile_to_playlist_create(accept_socket, &http_recv_info);
        debug_log_output("HTTP wizd play list create and response end!\n");
    }else if ( result == _CGI ){
        // ---------------------------------------------
        // cgiファイル
        // cgiを実行して結果を返信
        // ---------------------------------------------
        debug_log_output("HTTP CGI response start!\n");
        http_cgi_response(accept_socket, &http_recv_info);
        debug_log_output("HTTP CGI response end!\n");
        return;
    }else{
        // ----------------------------------------
        // ディレクトリ 内にindex.html or index.htm or index.cgi があったら、そちらを表示する。
        // ----------------------------------------
        //request_uriの最後が?なら強制的にmenu.jssを起動。それ以外は通常のファイル処理
        //request_uriの設定
        //?以降のパラメータがあるなら付け替える。なければsend_filenameをつける
        wString tmp(http_recv_info.request_uri);
        int pos=tmp.Pos("?");
        if( pos >= 0 ){
            strcpy(http_recv_info.recv_uri,"/menu.jss");
            tmp = tmp.substr(pos+1,tmp.Length()-pos-1);
            if(tmp.Length()){
                sprintf(http_recv_info.request_uri,"/menu.jss?%s", tmp.c_str());
            }else{
                sprintf(http_recv_info.request_uri,"/menu.jss?root=%s", http_recv_info.send_filename);
            }
            //send file nameの設定
            sprintf(http_recv_info.send_filename,"%s%smenu.jss", global_param.skin_root,global_param.skin_name);
            http_cgi_response(accept_socket, &http_recv_info);
            debug_log_output("HTTP file menu end.\n");
            return;
        //通常の処理
        }else{
            result = http_index( &http_recv_info );
            if( result == _FILE ){
                // ----------------------------------------
                // ファイルの実体
                // HTTPリクエストヘッダに従ってデータを返信。
                // ----------------------------------------
                debug_log_output("HTTP response start!\n");
                http_file_response(accept_socket, &http_recv_info);
                debug_log_output("HTTP response end!\n");
            }else if ( result == _CGI ){
                debug_log_output("HTTP CGI response start! %d\n",accept_socket);
                http_cgi_response(accept_socket, &http_recv_info);
                debug_log_output("HTTP CGI response end!\n");
                return;
            }else{
                debug_log_output("BAD REQUEST!");
                http_not_found_response(accept_socket, &http_recv_info);
            }
        }
    }
    sClose(accept_socket);
    return;
}