📄 live365.c
字号:
if (config_name && config_password) { name = g_strdup(config_name); password = g_strdup(config_password); } else if (blocking) st_auth_dialog(config_name, config_password, &name, &password, _("Password required"), _("Enter your Live365 account name and password.")); g_free(config_name); g_free(config_password); if (name && password) { static char *global_name = NULL; static char *global_password = NULL; static char *global_params = NULL; G_LOCK_DEFINE_STATIC(global); G_LOCK(global); if (global_params && global_name && ! strcmp(global_name, name) && global_password && ! strcmp(global_password, password)) params = g_strdup(global_params); G_UNLOCK(global); if (! params && blocking) { char *sane_id; char *session_id; GError *err = NULL; G_LOCK(global); g_free(global_name); global_name = g_strdup(name); g_free(global_password); global_password = g_strdup(password); g_free(global_params); global_params = NULL; G_UNLOCK(global); if (login(name, password, &sane_id, &session_id, &err)) { G_LOCK(global); global_params = g_strdup_printf("?SaneID=%s&membername=%s&session=%s", sane_id, name, session_id); g_free(sane_id); g_free(session_id); params = g_strdup(global_params); G_UNLOCK(global); } else { char *normalized; normalized = st_dialog_normalize(err->message); g_error_free(err); st_error_dialog(_("Unable to log into Live365"), "%s", normalized); g_free(normalized); } } } g_free(name); g_free(password); return params;}static gbooleanlogin (const char *name, const char *password, char **sane_id, char **session_id, GError **err){ char *escaped_name; char *escaped_password; char *url; STTransferSession *session; gboolean status; LoginInfo info; g_return_val_if_fail(name != NULL, FALSE); g_return_val_if_fail(password != NULL, FALSE); g_return_val_if_fail(sane_id != NULL, FALSE); g_return_val_if_fail(session_id != NULL, FALSE); escaped_name = st_transfer_escape(name); escaped_password = st_transfer_escape(password); url = g_strdup_printf(LIVE365_ROOT "cgi-bin/login.cgi?url=http://www.live365.com/index.live&membername=%s&password=%s", escaped_name, escaped_password); g_free(escaped_name); g_free(escaped_password); info.sane_id = NULL; info.session_id = NULL; session = st_transfer_session_new(); status = st_transfer_session_get_by_line(session, url, 0, login_header_cb, &info, NULL, NULL, err); st_transfer_session_free(session); if (status) { if (info.sane_id && info.session_id) { *sane_id = info.sane_id; *session_id = info.session_id; } else { g_free(info.sane_id); g_free(info.session_id); g_set_error(err, 0, 0, _("invalid username or password")); status = FALSE; } } return status;}static voidlogin_header_cb (const char *line, gpointer data){ LoginInfo *info = data; char *s1, *s2, *s3; if (! info->sane_id && (s1 = st_str_has_prefix_span(line, "Set-Cookie: SaneID=")) && (s2 = strchr(s1, ';'))) info->sane_id = g_strndup(s1, s2 - s1); else if (! info->session_id && (s1 = st_str_has_prefix_span(line, "Set-Cookie: sessionid=")) && (s2 = st_strstr_span(s1, "%3A")) && (s3 = strchr(s2, ';'))) info->session_id = g_strndup(s2, s3 - s2);}static gbooleanreload_cb (STCategory *category, GNode **categories, GList **streams, gpointer data, GError **err){ if (! session_categories) { if (! reload_categories(&session_categories, err)) return FALSE; } *categories = categories_copy(); if (st_is_aborted()) return FALSE; return category->url_postfix ? reload_streams(category, streams, err) : TRUE;}static GNode *categories_copy (void){ GNode *node; node = g_node_copy(session_categories); g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1, categories_copy_cb, NULL); return node;}static gbooleancategories_copy_cb (GNode *node, gpointer data){ STCategory *category = node->data; if (category) { STCategory *copy; copy = st_category_new(); copy->name = g_strdup(category->name); copy->label = g_strdup(category->label); copy->url_postfix = g_strdup(category->url_postfix); node->data = copy; } return FALSE;}static gbooleanreload_categories (GNode **categories, GError **err){ ReloadCategoriesInfo info; STTransferSession *session; gboolean status; *categories = g_node_new(NULL); info.categories = categories; info.parent = NULL; session = st_transfer_session_new(); status = st_transfer_session_get_by_line(session, LIVE365_ROOT "listen/", ST_TRANSFER_UTF8 | ST_TRANSFER_PARSE_HTTP_CHARSET, NULL, NULL, reload_categories_body_cb, &info, err); st_transfer_session_free(session); return status;}static voidreload_categories_body_cb (const char *line, gpointer data){ ReloadCategoriesInfo *info = data; STCategory *category; char *s1, *s2, *s3, *s4, *s5; if ((s1 = st_strstr_span(line, "<a href=\"/cgi-bin/directory")) && (s2 = st_strstr_span(s1, "&genre=")) && (s3 = strchr(s2, '"')) && (s4 = st_strchr_span(s3, '>')) && (s5 = strstr(s4, "</a>"))) { category = st_category_new(); category->name = g_strndup(s2, s3 - s2); category->label = st_sgml_ref_expand_len(s4, s5 - s4); category->url_postfix = g_strconcat(DIRECTORY_PREFIX, category->name, NULL); } else if ((s1 = st_strstr_span(line, "<a href=\"/genres/")) && (s2 = strchr(s1, '/')) && (s3 = st_strchr_span(s2, '>')) && (s4 = strstr(s3, "</a>"))) { category = st_category_new(); category->name = g_strndup(s1, s2 - s1); category->label = st_sgml_ref_expand_len(s3, s4 - s3); } else return; if (g_str_has_prefix(line, "\t\t\t-")) { if (info->parent) g_node_append_data(info->parent, category); else { PARSE_ERROR; st_category_free(category); } } else info->parent = g_node_append_data(*info->categories, category);}static gbooleanreload_streams (STCategory *category, GList **streams, GError **err){ STTransferSession *session; ReloadStreamsInfo info; gboolean status; int stream_limit; int requested_streams = 0; int received_streams = 0; *streams = NULL; info.streams = streams; session = st_transfer_session_new(); stream_limit = st_handler_config_get_boolean(live365_handler, CONFIG_STREAM_LIMIT_ENABLED) ? st_handler_config_get_int(live365_handler, CONFIG_STREAM_LIMIT) : -1; do { char *url; int rows; if (requested_streams != 0 && st_is_aborted()) { status = FALSE; break; } rows = stream_limit == -1 ? MAX_STREAMS_PER_PAGE : MIN(stream_limit - received_streams, MAX_STREAMS_PER_PAGE); url = g_strdup_printf(LIVE365_ROOT "%s&rows=%i&first=%i", category->url_postfix, rows, requested_streams + 1); requested_streams += rows; info.stream = NULL; info.has_next_page = FALSE; status = st_transfer_session_get_by_line(session, url, ST_TRANSFER_UTF8 | ST_TRANSFER_PARSE_HTTP_CHARSET | ST_TRANSFER_PARSE_HTML_CHARSET, NULL, NULL, reload_streams_body_cb, &info, err); g_free(url); received_streams = g_list_length(*streams); if (info.stream) { stream_free_cb(info.stream, NULL); if (status) /* only display warning if the transfer was otherwise correct */ PARSE_ERROR; } } while (status && info.has_next_page && (stream_limit == -1 || received_streams < stream_limit)); st_transfer_session_free(session); return status;}static voidreload_streams_body_cb (const char *line, gpointer data){ ReloadStreamsInfo *info = data; char *s1, *s2, *s3, *s4, *s5, *s6, *s7; char *word1, *word2, *word3; if ((s1 = st_str_has_prefix_span(line, "<TD CLASS=\"icon\"")) && (s2 = st_strstr_span(s1, "DrawPlayIcon"))) { if (info->stream) /* a malformed stream remains, free it */ { PARSE_ERROR; stream_free_cb(info->stream, NULL); } info->stream = stream_new_cb(NULL); if (strstr(s2, "'OK'")) info->stream->access = ACCESS_ALL; else if (strstr(s2, "'PM_ONLY'")) info->stream->access = ACCESS_VIP; else if (strstr(s2, "'SUBSCRIPTION'")) info->stream->access = ACCESS_SUBSCRIPTION; else PARSE_ERROR; info->finished_stream = NULL; } else if ((s1 = st_str_has_prefix_span(line, "<TD CLASS=\"title")) && (s2 = st_strstr_span(s1, "href='")) && (s3 = strstr(s2, "'>")) && (s4 = strstr(s3, "</a>"))) { if (info->stream) { g_free(info->stream->homepage); info->stream->homepage = st_sgml_ref_expand_len(s2, s3 - s2); g_free(info->stream->title); s3 += 2; info->stream->title = st_sgml_ref_expand_len(s3, s4 - s3); } else PARSE_ERROR; } else if ((s1 = st_str_has_prefix_span(line, "<TD CLASS=\"genre\" >")) && (s2 = strstr(s1, "</TD>"))) { if (info->stream) { g_free(info->stream->genre); info->stream->genre = st_sgml_ref_expand_len(s1, s2 - s1); } else PARSE_ERROR; } else if ((s1 = st_strstr_span(line, "&station_id=")) && (s2 = strchr(s1, '&'))) { if (info->stream) { word1 = g_strndup(s1, s2 - s1); if (st_str_like(word1, ST_NUMERIC)) info->stream->station_id = atoi(word1); g_free(word1); } else PARSE_ERROR; } else if ((s1 = st_strstr_span(line, "alt=\"More broadcaster info")) && (s2 = st_strchr_span(s1, '>')) && (s3 = strstr(s2, "</a>"))) { if (info->stream) { g_free(info->stream->broadcaster); info->stream->broadcaster = st_sgml_ref_expand_len(s2, s3 - s2); } else PARSE_ERROR; } else if ((s1 = st_str_has_prefix_span(line, "<TD CLASS=\"connection\"")) && (s2 = st_strchr_span(s1, '>')) && (s3 = strstr(s2, "<br>")) && ((s4 = strstr(s3, "<img src='/images/mp3pro")) || (s4 = strstr(s3, "</TD>")))) { if (info->stream) { word1 = st_sgml_ref_expand_len(s2, s3 - s2); s3 += 4; word2 = st_sgml_ref_expand_len(s3, s4 - s3); g_free(info->stream->audio); info->stream->audio = g_strdup_printf(g_str_has_prefix(s4, "</TD>") ? "%s %s" : "%s %s, MP3Pro", word2, word1); g_free(word1); g_free(word2); } else PARSE_ERROR; } else if ((s1 = st_str_has_prefix_span(line, "<TD CLASS=\"rating\"")) && (s2 = st_strstr_span(s1, "DrawListenerStars(")) && (s3 = strchr(s2, ',')) && (s4 = st_strstr_span(s3, "DrawRatingStars(")) && (s5 = strchr(s4, ',')) && (s6 = st_strchr_span(s5, ' ')) && (s7 = strchr(s6, ','))) { if (info->stream) { word1 = g_strndup(s2, s3 - s2); word2 = g_strndup(s4, s5 - s4); word3 = g_strndup(s6, s7 - s6); if (st_str_like(word1, ST_NUMERIC)) info->stream->tlh = atoi(word1); else PARSE_ERROR; if (st_str_like(word2, ST_NUMERIC) && st_str_like(word3, ST_NUMERIC)) { int total = atoi(word2); int count = atoi(word3); if (count > 0) info->stream->rating = (double) total / count; } else PARSE_ERROR; g_free(word1); g_free(word2); g_free(word3); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -