/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_xml_reader_ref_t tb_xml_reader_init() { // init reader tb_xml_reader_impl_t* reader = tb_malloc0_type(tb_xml_reader_impl_t); tb_assert_and_check_return_val(reader, tb_null); // init string tb_string_init(&reader->text); tb_string_init(&reader->version); tb_string_init(&reader->charset); tb_string_init(&reader->element); tb_string_init(&reader->element_name); tb_string_init(&reader->attribute_name); tb_string_init(&reader->attribute_data); tb_string_cstrcpy(&reader->version, "2.0"); tb_string_cstrcpy(&reader->charset, "utf-8"); // init attributes tb_size_t i = 0; for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++) { tb_xml_node_ref_t node = (tb_xml_node_ref_t)(reader->attributes + i); tb_string_init(&node->name); tb_string_init(&node->data); } // ok return (tb_xml_reader_ref_t)reader; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_network_cookies_main(tb_int_t argc, tb_char_t** argv) { // set cookies tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "BAIDUID=0; max-age=946080000; expires=Sat, 06-Apr-41 03:21:53 GMT; domain=.baidu.com; path=/"); tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_true, "FG=1; max-age=946080000; expires=Sat, 06-Apr-2017 03:21:53 GMT; domain=.baidu.com; path=/; version=1"); tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "BAIDUID=2; max-age=946080000; expires=Sat, 06-Apr-2016 03:21:53 GMT; domain=.baidu.com; path=/style; version=1"); tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "BG=3; expires=Wednesday, 09-Nov-99 23:12:40 GMT; domain=.space.baidu.com; path=/"); tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "BAIDSID=4; expires=Wednesday, 09-Nov-99 23:12:40 GMT; domain=.baidu.com; path=/style/foo"); tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "pvid=3317093836; path=/; domain=qq.com; expires=Sun, 18 Jan 2038 00:00:00 GMT;"); tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "clientuin=; EXPIRES=Fri, 02-Jan-1970 00:00:00 GMT; PATH=/; DOMAIN=qq.com;"); tb_cookies_set_from_url(tb_cookies(), "http://mail.163.com:2000/WorldClient.dll?View=Main", "User=wangrq; Expires=Tue, 19-Apr-2015 07:10:56 GMT; path=/"); tb_cookies_set_from_url(tb_cookies(), "http://mail.163.com:2000/WorldClient.dll?View=Main", "Session=Yz9eJRh6QijR; path=/"); tb_cookies_set_from_url(tb_cookies(), "http://mail.163.com:2000/WorldClient.dll?View=Main", "Lang=zh; Expires=Tue, 19-Apr-2015 07:10:56 GMT; path=/"); tb_cookies_set_from_url(tb_cookies(), "http://mail.163.com:2000/WorldClient.dll?View=Main", "Theme=Standard; Expires=Tue, 19-Apr-2015 07:10:56 GMT; path=/"); // get cookies tb_string_t value; tb_string_init(&value); tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://www.space.baidu.com/style/foo/login.css", &value)); tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://www.baidu.com/style/foo/login.css", &value)); tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://www.baidu.com/style", &value)); tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://www.baidu.com", &value)); tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "https://www.baidu.com/", &value)); tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://pingfore.qq.com/pingd?dm=qzone.qq.com&url=login/qzone_n&tt=-&rdm=-&rurl=-&pvid=7466815060&scr=-&scl=-&lang=-&java=1&cc=-&pf=-&tz=-8&ct=-&vs=3.3&emu=0.20486706611700356", &value)); tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://mail.163.com:2000/?Session=LZBMQVW&View=Menu", &value)); tb_string_exit(&value); return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_http_status_init(tb_http_status_t* status) { // check tb_assert_and_check_return_val(status, tb_false); // init status using the default value status->version = 1; // init content type if (!tb_string_init(&status->content_type)) return tb_false; // init location if (!tb_string_init(&status->location)) return tb_false; // ok return tb_true; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_environment_load(tb_environment_ref_t environment, tb_char_t const* name) { // check tb_assert_and_check_return_val(environment && name, 0); // clear environment first tb_vector_clear(environment); // get values tb_char_t const* values = tb_environment_get_impl(name, tb_null); tb_check_return_val(values, 0); // init value string tb_string_t value; if (tb_string_init(&value)) { // done tb_char_t const* p = values; tb_char_t c = '\0'; while (1) { // the character c = *p++; // make value if (c != ';' && c) tb_string_chrcat(&value, c); else { // save value to environment if (tb_string_size(&value)) tb_vector_insert_tail(environment, tb_string_cstr(&value)); // clear value tb_string_clear(&value); // end? tb_check_break(c); } } // exit value string tb_string_exit(&value); } // exit values if (values) tb_free(values); values = tb_null; // ok? return tb_vector_size(environment); }
tb_size_t tb_environment_get(tb_char_t const* name, tb_char_t* values, tb_size_t maxn) { // check tb_assert_and_check_return_val(name && values && maxn, 0); // init values tb_string_t valuestrs; if (!tb_string_init(&valuestrs)) return 0; // init environment tb_environment_ref_t environment = tb_environment_init(); if (environment) { // load variable if (tb_environment_load(environment, name)) { // make values tb_bool_t is_first = tb_true; tb_for_all_if (tb_char_t const*, value, environment, value) { // append separator if (!is_first) tb_string_chrcat(&valuestrs, TM_ENVIRONMENT_SEP); else is_first = tb_false; // append value tb_string_cstrcat(&valuestrs, value); } } // exit environment tb_environment_exit(environment); } // save result tb_size_t size = tb_string_size(&valuestrs); tb_char_t const* cstr = tb_string_cstr(&valuestrs); if (size && cstr) { // copy it size = tb_strlcpy(values, cstr, maxn); tb_assert(size < maxn); } // exit values tb_string_exit(&valuestrs); // ok? return size; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_int_t xm_os_getenv(lua_State* lua) { // check tb_assert_and_check_return_val(lua, 0); // get the name tb_char_t const* name = luaL_checkstring(lua, 1); tb_check_return_val(name, 0); // init values tb_string_t values; if (!tb_string_init(&values)) return 0; // init environment tb_environment_ref_t environment = tb_environment_init(); if (environment) { // load variable if (tb_environment_load(environment, name)) { // make values tb_bool_t is_first = tb_true; tb_for_all_if (tb_char_t const*, value, environment, value) { // append separator if (!is_first) tb_string_chrcat(&values, XM_OS_ENV_SEP); else is_first = tb_false; // append value tb_string_cstrcat(&values, value); } } // exit environment tb_environment_exit(environment); } // save result if (tb_string_size(&values)) lua_pushstring(lua, tb_string_cstr(&values)); else lua_pushnil(lua); // exit values tb_string_exit(&values); // ok return 1; }
/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_filter_ref_t tb_filter_init_from_chunked(tb_bool_t dechunked) { // done tb_bool_t ok = tb_false; tb_filter_chunked_t* filter = tb_null; do { // noimpl for encoding chunked if (!dechunked) { tb_trace_noimpl(); break; } // make filter filter = tb_malloc0_type(tb_filter_chunked_t); tb_assert_and_check_break(filter); // init filter if (!tb_filter_init((tb_filter_t*)filter, TB_FILTER_TYPE_CHUNKED)) break; filter->base.spak = tb_filter_chunked_spak; filter->base.clos = tb_filter_chunked_clos; filter->base.exit = tb_filter_chunked_exit; // init line if (!tb_string_init(&filter->line)) break; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit filter tb_filter_exit((tb_filter_ref_t)filter); filter = tb_null; } // ok? return (tb_filter_ref_t)filter; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_option_ref_t tb_option_init(tb_char_t const* name, tb_char_t const* help, tb_option_item_t const* opts) { // check tb_assert_and_check_return_val(name && opts, tb_null); // done tb_bool_t ok = tb_false; tb_option_impl_t* impl = tb_null; do { // make option impl = tb_malloc0_type(tb_option_impl_t); tb_assert_and_check_break(impl); // init option impl->opts = opts; impl->list = tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); tb_assert_and_check_break(impl->list); // init name tb_strlcpy(impl->name, name, sizeof(impl->name)); // init help if (!tb_string_init(&impl->help)) break; if (help) tb_string_cstrcpy(&impl->help, help); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (impl) tb_option_exit((tb_option_ref_t)impl); impl = tb_null; } // ok? return (tb_option_ref_t)impl; }
tb_bool_t tb_environment_save(tb_environment_ref_t environment, tb_char_t const* name) { // check tb_assert_and_check_return_val(environment && name, tb_false); // empty? remove this environment variable if (!tb_vector_size(environment)) return !unsetenv(name); // init values string tb_string_t values; if (!tb_string_init(&values)) return tb_false; // make values string tb_for_all_if (tb_char_t const*, value, environment, value) { // the single value cannot exist ':' tb_assertf(!tb_strchr(value, ':'), "invalid value: %s", value); // append value tb_string_cstrcat(&values, value); tb_string_chrcat(&values, ':'); }
static tb_object_ref_t tb_object_json_reader_func_string(tb_object_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream && (type == '\"' || type == '\''), tb_null); // init data tb_string_t data; if (!tb_string_init(&data)) return tb_null; // walk tb_char_t ch; while (tb_stream_left(reader->stream)) { // read one character ch = tb_stream_bread_s8(reader->stream); // end? if (ch == '\"' || ch == '\'') break; // the escaped character? else if (ch == '\\') { // read one character ch = tb_stream_bread_s8(reader->stream); // unicode? if (ch == 'u') { #ifdef TB_CONFIG_MODULE_HAVE_CHARSET // the unicode string tb_char_t unicode_str[5]; unicode_str[0] = tb_stream_bread_s8(reader->stream); unicode_str[1] = tb_stream_bread_s8(reader->stream); unicode_str[2] = tb_stream_bread_s8(reader->stream); unicode_str[3] = tb_stream_bread_s8(reader->stream); unicode_str[4] = '\0'; // the unicode value tb_uint16_t unicode_val = tb_s16toi32(unicode_str); // the utf8 stream tb_char_t utf8_data[16] = {0}; tb_static_stream_t utf8_stream; tb_static_stream_init(&utf8_stream, (tb_byte_t*)utf8_data, sizeof(utf8_data)); // the unicode stream tb_static_stream_t unicode_stream = {0}; tb_static_stream_init(&unicode_stream, (tb_byte_t*)&unicode_val, 2); // unicode to utf8 tb_long_t utf8_size = tb_charset_conv_bst(TB_CHARSET_TYPE_UCS2 | TB_CHARSET_TYPE_NE, TB_CHARSET_TYPE_UTF8, &unicode_stream, &utf8_stream); if (utf8_size > 0) tb_string_cstrncat(&data, utf8_data, utf8_size); #else // trace tb_trace1_e("unicode type is not supported, please enable charset module config if you want to use it!"); // only append it tb_string_chrcat(&data, ch); #endif } // append escaped character else tb_string_chrcat(&data, ch); } // append character else tb_string_chrcat(&data, ch); } // init string tb_object_ref_t string = tb_object_string_init_from_cstr(tb_string_cstr(&data)); // trace tb_trace_d("string: %s", tb_string_cstr(&data)); // exit data tb_string_exit(&data); // ok? return string; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_stream_async_stream_main(tb_int_t argc, tb_char_t** argv) { // done tb_demo_context_t context = {0}; do { // init option context.option = tb_option_init("astream", "the astream demo", g_options); tb_assert_and_check_break(context.option); // done option if (tb_option_done(context.option, argc - 1, &argv[1])) { // debug and verbose context.debug = tb_option_find(context.option, "debug")? tb_false : tb_true; context.verbose = tb_option_find(context.option, "no-verbose")? tb_false : tb_true; // done url if (tb_option_find(context.option, "url")) { // init event context.event = tb_event_init(); tb_assert_and_check_break(context.event); // init istream context.istream = tb_async_stream_init_from_url(tb_null, tb_option_item_cstr(context.option, "url")); tb_assert_and_check_break(context.istream); // ctrl http if (tb_async_stream_type(context.istream) == TB_STREAM_TYPE_HTTP) { // enable gzip? if (tb_option_find(context.option, "gzip")) { // auto unzip if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_AUTO_UNZIP, 1)) break; // need gzip if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Accept-Encoding", "gzip,deflate")) break; } // enable debug? if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD_FUNC, context.debug? tb_demo_istream_head_func : tb_null)) break; // custem header? if (tb_option_find(context.option, "header")) { // init tb_string_t key; tb_string_t val; tb_string_init(&key); tb_string_init(&val); // done tb_bool_t k = tb_true; tb_char_t const* p = tb_option_item_cstr(context.option, "header"); while (*p) { // is key? if (k) { if (*p != ':' && !tb_isspace(*p)) tb_string_chrcat(&key, *p++); else if (*p == ':') { // skip ':' p++; // skip space while (*p && tb_isspace(*p)) p++; // is val now k = tb_false; } else p++; } // is val? else { if (*p != ';') tb_string_chrcat(&val, *p++); else { // skip ';' p++; // skip space while (*p && tb_isspace(*p)) p++; // set header if (tb_string_size(&key) && tb_string_size(&val)) { if (context.debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val)); if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break; } // is key now k = tb_true; // clear key & val tb_string_clear(&key); tb_string_clear(&val); } } } // set header if (tb_string_size(&key) && tb_string_size(&val)) { if (context.debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val)); if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break; } // exit tb_string_exit(&key); tb_string_exit(&val); } // keep alive? if (tb_option_find(context.option, "keep-alive")) { if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Connection", "keep-alive")) break; } // post-data? if (tb_option_find(context.option, "post-data")) { tb_char_t const* post_data = tb_option_item_cstr(context.option, "post-data"); tb_hize_t post_size = tb_strlen(post_data); if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break; if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_POST_DATA, post_data, post_size)) break; if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break; if (context.debug) tb_printf("post: %llu\n", post_size); } // post-file? else if (tb_option_find(context.option, "post-file")) { tb_char_t const* url = tb_option_item_cstr(context.option, "post-file"); if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break; if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_POST_URL, url)) break; if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break; if (context.debug) tb_printf("post: %s\n", url); } } // set range if (tb_option_find(context.option, "range")) { tb_char_t const* p = tb_option_item_cstr(context.option, "range"); if (p) { // the bof tb_hize_t eof = 0; tb_hize_t bof = tb_atoll(p); while (*p && tb_isdigit(*p)) p++; if (*p == '-') { p++; eof = tb_atoll(p); } if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_RANGE, bof, eof)) break; } } // set timeout if (tb_option_find(context.option, "timeout")) { tb_size_t timeout = tb_option_item_uint32(context.option, "timeout"); tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_SET_TIMEOUT, &timeout); } // print verbose info if (context.verbose) tb_printf("open: %s: ..\n", tb_option_item_cstr(context.option, "url")); // open istream if (!tb_async_stream_open(context.istream, tb_demo_istream_open_func, &context)) { // print verbose info if (context.verbose) tb_printf("open: failed\n"); break; } // wait it tb_event_wait(context.event, -1); } else tb_option_help(context.option); } else tb_option_help(context.option); } while (0); // exit transfer if (context.transfer) tb_async_transfer_exit(context.transfer); context.transfer = tb_null; // exit istream if (context.istream) tb_async_stream_exit(context.istream); context.istream = tb_null; // exit ostream if (context.ostream) tb_async_stream_exit(context.ostream); context.ostream = tb_null; // exit option if (context.option) tb_option_exit(context.option); context.option = tb_null; // exit event if (context.event) tb_event_exit(context.event); context.event = tb_null; return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_stream_main(tb_int_t argc, tb_char_t** argv) { // done tb_option_ref_t option = tb_null; tb_stream_ref_t istream = tb_null; tb_stream_ref_t ostream = tb_null; tb_stream_ref_t pstream = tb_null; do { // init option option = tb_option_init("stream", "the stream demo", g_options); tb_assert_and_check_break(option); // done option if (tb_option_done(option, argc - 1, &argv[1])) { // debug & verbose tb_bool_t debug = tb_option_find(option, "debug"); tb_bool_t verbose = tb_option_find(option, "no-verbose")? tb_false : tb_true; // done url if (tb_option_find(option, "url")) { // init istream istream = tb_stream_init_from_url(tb_option_item_cstr(option, "url")); tb_assert_and_check_break(istream); // ctrl http if (tb_stream_type(istream) == TB_STREAM_TYPE_HTTP) { // enable gzip? if (tb_option_find(option, "gzip")) { // auto unzip if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_AUTO_UNZIP, 1)) break; // need gzip if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Accept-Encoding", "gzip,deflate")) break; } // enable debug? if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD_FUNC, debug? tb_demo_stream_head_func : tb_null)) break; // custem header? if (tb_option_find(option, "header")) { // init tb_string_t key; tb_string_t val; tb_string_init(&key); tb_string_init(&val); // done tb_bool_t k = tb_true; tb_char_t const* p = tb_option_item_cstr(option, "header"); while (*p) { // is key? if (k) { if (*p != ':' && !tb_isspace(*p)) tb_string_chrcat(&key, *p++); else if (*p == ':') { // skip ':' p++; // skip space while (*p && tb_isspace(*p)) p++; // is val now k = tb_false; } else p++; } // is val? else { if (*p != ';') tb_string_chrcat(&val, *p++); else { // skip ';' p++; // skip space while (*p && tb_isspace(*p)) p++; // set header if (tb_string_size(&key) && tb_string_size(&val)) { if (debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val)); if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break; } // is key now k = tb_true; // clear key & val tb_string_clear(&key); tb_string_clear(&val); } } } // set header if (tb_string_size(&key) && tb_string_size(&val)) { if (debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val)); if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break; } // exit tb_string_exit(&key); tb_string_exit(&val); } // keep alive? if (tb_option_find(option, "keep-alive")) { if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Connection", "keep-alive")) break; } // post-data? if (tb_option_find(option, "post-data")) { tb_char_t const* post_data = tb_option_item_cstr(option, "post-data"); tb_hize_t post_size = tb_strlen(post_data); if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break; if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_DATA, post_data, post_size)) break; if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break; if (debug) tb_printf("post: %llu\n", post_size); } // post-file? else if (tb_option_find(option, "post-file")) { tb_char_t const* url = tb_option_item_cstr(option, "post-file"); if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break; if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_URL, url)) break; if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break; if (debug) tb_printf("post: %s\n", url); } } // set range if (tb_option_find(option, "range")) { tb_char_t const* p = tb_option_item_cstr(option, "range"); if (p) { // the bof tb_hize_t eof = 0; tb_hize_t bof = tb_atoll(p); while (*p && tb_isdigit(*p)) p++; if (*p == '-') { p++; eof = tb_atoll(p); } if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_RANGE, bof, eof)) break; } } // set timeout if (tb_option_find(option, "timeout")) { tb_size_t timeout = tb_option_item_uint32(option, "timeout"); if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_SET_TIMEOUT, timeout)) break; } // print verbose info if (verbose) tb_printf("open: %s: ..\n", tb_option_item_cstr(option, "url")); // open istream if (!tb_stream_open(istream)) { // print verbose info if (verbose) tb_printf("open: %s\n", tb_state_cstr(tb_stream_state(istream))); break; } // print verbose info if (verbose) tb_printf("open: ok\n"); // init ostream if (tb_option_find(option, "more0")) { // the path tb_char_t const* path = tb_option_item_cstr(option, "more0"); // init ostream = tb_stream_init_from_file(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_BINARY | TB_FILE_MODE_TRUNC); // print verbose info if (verbose) tb_printf("save: %s\n", path); } else { // the name tb_char_t const* name = tb_strrchr(tb_option_item_cstr(option, "url"), '/'); if (!name) name = tb_strrchr(tb_option_item_cstr(option, "url"), '\\'); if (!name) name = "/stream.file"; // the path tb_char_t path[TB_PATH_MAXN] = {0}; if (tb_directory_current(path, TB_PATH_MAXN)) tb_strcat(path, name); else break; // init file ostream = tb_stream_init_from_file(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_BINARY | TB_FILE_MODE_TRUNC); // print verbose info if (verbose) tb_printf("save: %s\n", path); } tb_assert_and_check_break(ostream); // the limit rate tb_size_t limitrate = 0; if (tb_option_find(option, "limitrate")) limitrate = tb_option_item_uint32(option, "limitrate"); // save it tb_hong_t save = 0; tb_demo_context_t context = {0}; context.verbose = verbose; if ((save = tb_transfer_done(istream, ostream, limitrate, tb_demo_stream_save_func, &context)) < 0) break; } else tb_option_help(option); } else tb_option_help(option); } while (0); // exit pstream if (pstream) tb_stream_exit(pstream); pstream = tb_null; // exit istream if (istream) tb_stream_exit(istream); istream = tb_null; // exit ostream if (ostream) tb_stream_exit(ostream); ostream = tb_null; // exit option if (option) tb_option_exit(option); option = tb_null; return 0; }