static gchar *escape_username(const gchar *in) { gchar *tmp, *tmp2; tmp = purple_strreplace(in, "=", "=3D"); tmp2 = purple_strreplace(tmp, ",", "=2C"); g_free(tmp); return tmp2; }
static void ggp_message_format_from_gg(ggp_message_got_data *msg, const gchar *text) { gchar *text_new, *tmp; if (text == NULL) { msg->text = g_strdup(""); return; } text_new = g_strdup(text); purple_str_strip_char(text_new, '\r'); tmp = text_new; text_new = purple_strreplace(text_new, GGP_GG10_DEFAULT_FORMAT, GGP_GG10_DEFAULT_FORMAT_REPLACEMENT); g_free(tmp); tmp = text_new; text_new = g_regex_replace_eval(global_data.re_gg_img, text_new, -1, 0, 0, ggp_message_format_from_gg_found_img, msg, NULL); g_free(tmp); msg->text = text_new; }
static void list_cmd(NateonCmdProc *cmdproc, NateonCommand *cmd) { NateonSession *session = cmdproc->session; NateonUser *user; char *user_id; char *account; char *stored; char *friend; int list_op; user_id = cmd->params[5]; account = cmd->params[4]; stored = purple_strreplace(cmd->params[7], "%20", " "); friend = cmd->params[6]; list_op = cmd->params[3][NATEON_LIST_FL]-'0' ? NATEON_LIST_FL_OP : 0; list_op += cmd->params[3][NATEON_LIST_AL]-'0' ? NATEON_LIST_AL_OP : 0; list_op += cmd->params[3][NATEON_LIST_BL]-'0' ? NATEON_LIST_BL_OP : 0; list_op += cmd->params[3][NATEON_LIST_RL]-'0' ? NATEON_LIST_RL_OP : 0; user = nateon_userlist_find_user_with_id(session->userlist, user_id); if (user == NULL) { user = nateon_user_new(session->userlist, account, stored, user_id); user->group_ids = NULL; nateon_userlist_add_user(session->userlist, user); } g_free(user->account_name); user->account_name = g_strdup(account); g_free(user->store_name); if (!g_strncasecmp(stored, "%00", 3)) { user->store_name = NULL; } else { user->store_name = g_strdup(stored); } g_free(user->friendly_name); user->friendly_name = g_strdup(friend); nateon_got_lst_user(session, user, list_op, user->group_ids); session->sync->last_user = user; session->sync->num_users++; /* end of lists */ if (session->sync->num_users == atoi(cmd->params[2])) { cmdproc->cbs_table = session->sync->old_cbs_table; nateon_session_finish_login(session); nateon_sync_destroy(session->sync); session->sync = NULL; } }
static void ggp_message_request_images_got(PurpleConnection *gc, uint64_t id, int stored_id, gpointer _msg) { ggp_message_session_data *sdata = ggp_message_get_sdata(gc); ggp_message_got_data *msg = _msg; GList *m_it, *i_it; gchar *tmp, *tag_search, *tag_replace; m_it = g_list_find(sdata->pending_messages, msg); if (!m_it) { purple_debug_error("gg", "ggp_message_request_images_got: " "message %p is not in queue\n", msg); return; } i_it = g_list_find_custom(msg->pending_images, &id, ggp_int64_compare); if (!i_it) { purple_debug_error("gg", "ggp_message_request_images_got: " "image " GGP_IMAGE_ID_FORMAT " is not present in this " "message\n", id); return; } tag_search = g_strdup_printf(GGP_IMAGE_REPLACEMENT, id); tag_replace = g_strdup_printf(GGP_IMAGE_DESTINATION, stored_id); tmp = msg->text; msg->text = purple_strreplace(msg->text, tag_search, tag_replace); g_free(tmp); g_free(tag_search); g_free(tag_replace); g_free(i_it->data); msg->pending_images = g_list_delete_link(msg->pending_images, i_it); if (msg->pending_images != NULL) { purple_debug_info("gg", "ggp_message_request_images_got: " "got image " GGP_IMAGE_ID_FORMAT ", but the message " "contains more of them\n", id); return; } ggp_message_got_display(gc, msg); ggp_message_got_data_free(msg); sdata->pending_messages = g_list_delete_link(sdata->pending_messages, m_it); }
static void ggp_edisc_xfer_send_start(PurpleXfer *xfer) { ggp_edisc_session_data *sdata; ggp_edisc_xfer *edisc_xfer; gchar *upload_url, *filename_e; PurpleHttpRequest *req; g_return_if_fail(xfer != NULL); edisc_xfer = purple_xfer_get_protocol_data(xfer); g_return_if_fail(edisc_xfer != NULL); sdata = ggp_edisc_get_sdata(edisc_xfer->gc); g_return_if_fail(sdata != NULL); filename_e = purple_strreplace(edisc_xfer->filename, " ", "%20"); upload_url = g_strdup_printf("https://drive.mpa.gg.pl/me/file/outbox/" "%s%%2C%s", edisc_xfer->ticket_id, filename_e); g_free(filename_e); req = purple_http_request_new(upload_url); g_free(upload_url); purple_http_request_set_method(req, "PUT"); purple_http_request_set_timeout(req, -1); ggp_edisc_set_defaults(req); purple_http_request_set_cookie_jar(req, sdata->cookies); purple_http_request_header_set(req, "X-gged-local-revision", "0"); purple_http_request_header_set(req, "X-gged-security-token", sdata->security_token); purple_http_request_header_set(req, "X-gged-metadata", "{\"node_type\": \"file\"}"); purple_http_request_set_contents_reader(req, ggp_edisc_xfer_send_reader, purple_xfer_get_size(xfer), xfer); edisc_xfer->hc = purple_http_request(edisc_xfer->gc, req, ggp_edisc_xfer_send_done, xfer); purple_http_request_unref(req); purple_http_conn_set_progress_watcher(edisc_xfer->hc, ggp_edisc_xfer_progress_watcher, xfer, 250000); }
void skype_debug_vargs(PurpleDebugLevel level, const char *category, const char *format, va_list args) { SkypeDebugWrapper *wrapper; gchar *message; if (purple_eventloop_get_ui_ops() == NULL) { return; } wrapper = g_new(SkypeDebugWrapper, 1); wrapper->level = level; wrapper->category = g_strdup(category); message = g_strdup_vprintf(format, args); wrapper->message = purple_strreplace(message, "%", "%%"); g_free(message); purple_timeout_add(1, (GSourceFunc) skype_debug_cb, (gpointer)wrapper); }
gboolean purple_smiley_list_add(PurpleSmileyList *list, PurpleSmiley *smiley) { PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list); PurpleImage *smiley_img; const gchar *smiley_path; gboolean succ; gchar *shortcut_escaped; const gchar *shortcut; g_return_val_if_fail(priv != NULL, FALSE); g_return_val_if_fail(PURPLE_IS_SMILEY(smiley), FALSE); if (g_object_get_data(G_OBJECT(smiley), "purple-smiley-list") != NULL) { purple_debug_warning("smiley-list", "smiley is already associated with some list"); return FALSE; } shortcut = purple_smiley_get_shortcut(smiley); if (g_hash_table_lookup(priv->shortcut_map, shortcut) != NULL) return FALSE; shortcut_escaped = g_markup_escape_text(shortcut, -1); succ = purple_trie_add(priv->trie, shortcut_escaped, smiley); /* A special-case for WebKit, which unescapes apos entity. * Please, don't trust this hack - it may be removed in future releases. */ if (succ && strstr(shortcut_escaped, "'") != NULL) { gchar *tmp = shortcut_escaped; shortcut_escaped = purple_strreplace(shortcut_escaped, "'", "'"); g_free(tmp); succ = purple_trie_add(priv->trie, shortcut_escaped, smiley); } g_free(shortcut_escaped); if (!succ) return FALSE; g_object_ref(smiley); _list_append2(&priv->smileys, &priv->smileys_end, smiley); g_object_set_data(G_OBJECT(smiley), "purple-smiley-list", list); g_object_set_data(G_OBJECT(smiley), "purple-smiley-list-elem", priv->smileys_end); g_hash_table_insert(priv->shortcut_map, g_strdup(shortcut), smiley); smiley_img = purple_smiley_get_image(smiley); if (priv->drop_failed_remotes && !purple_image_is_ready(smiley_img)) { g_object_set_data(G_OBJECT(smiley_img), "purple-smiley-list-smiley", smiley); g_signal_connect_object(smiley_img, "failed", G_CALLBACK(remote_smiley_failed), list, 0); } smiley_path = smiley_get_uniqid(smiley); /* TODO: add to the table, when the smiley sets the path */ if (!smiley_path) return TRUE; if (g_hash_table_lookup(priv->path_map, smiley_path) == NULL) { g_hash_table_insert(priv->path_map, g_strdup(smiley_path), smiley); } return TRUE; }
static void finch_sound_play_file(const char *filename) { const char *method; #ifdef USE_GSTREAMER float volume; char *uri; GstElement *sink = NULL; GstElement *play = NULL; GstBus *bus = NULL; #endif if (purple_prefs_get_bool(make_pref("/mute"))) return; method = purple_prefs_get_string(make_pref("/method")); if (!strcmp(method, "nosound")) { return; } else if (!strcmp(method, "beep")) { beep(); return; } if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { purple_debug_error("gntsound", "sound file (%s) does not exist.\n", filename); return; } #ifndef _WIN32 if (!strcmp(method, "custom")) { const char *sound_cmd; char *command; char *esc_filename; GError *error = NULL; sound_cmd = purple_prefs_get_path(make_pref("/command")); if (!sound_cmd || *sound_cmd == '\0') { purple_debug_error("gntsound", "'Command' sound method has been chosen, " "but no command has been set."); return; } esc_filename = g_shell_quote(filename); if (strstr(sound_cmd, "%s")) command = purple_strreplace(sound_cmd, "%s", esc_filename); else command = g_strdup_printf("%s %s", sound_cmd, esc_filename); if (!g_spawn_command_line_async(command, &error)) { purple_debug_error("gntsound", "sound command could not be launched: %s\n", error->message); g_error_free(error); } g_free(esc_filename); g_free(command); return; } #ifdef USE_GSTREAMER if (gst_init_failed) /* Perhaps do beep instead? */ return; volume = (float)(CLAMP(purple_prefs_get_int(make_pref("/volume")), 0, 100)) / 50; if (!strcmp(method, "automatic")) { if (purple_running_gnome()) { sink = gst_element_factory_make("gconfaudiosink", "sink"); } if (!sink) sink = gst_element_factory_make("autoaudiosink", "sink"); if (!sink) { purple_debug_error("sound", "Unable to create GStreamer audiosink.\n"); return; } } else if (!strcmp(method, "esd")) { sink = gst_element_factory_make("esdsink", "sink"); if (!sink) { purple_debug_error("sound", "Unable to create GStreamer audiosink.\n"); return; } } else if (!strcmp(method, "alsa")) { sink = gst_element_factory_make("alsasink", "sink"); if (!sink) { purple_debug_error("sound", "Unable to create GStreamer audiosink.\n"); return; } } else { purple_debug_error("sound", "Unknown sound method '%s'\n", method); return; } play = gst_element_factory_make("playbin", "play"); if (play == NULL) { return; } uri = g_strdup_printf("file://%s", filename); g_object_set(G_OBJECT(play), "uri", uri, "volume", volume, "audio-sink", sink, NULL); bus = gst_pipeline_get_bus(GST_PIPELINE(play)); gst_bus_add_watch(bus, bus_call, play); gst_element_set_state(play, GST_STATE_PLAYING); gst_object_unref(bus); g_free(uri); #else /* USE_GSTREAMER */ beep(); return; #endif /* USE_GSTREAMER */ #else /* _WIN32 */ purple_debug_info("sound", "Playing %s\n", filename); { wchar_t *wc_filename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL); if (!PlaySoundW(wc_filename, NULL, SND_ASYNC | SND_FILENAME)) purple_debug(PURPLE_DEBUG_ERROR, "sound", "Error playing sound.\n"); g_free(wc_filename); } #endif /* _WIN32 */ }
static void pidgin_sound_play_file(const char *filename) { const char *method; #ifdef USE_GSTREAMER float volume; char *uri; GstElement *sink = NULL; GstElement *play = NULL; GstBus *bus = NULL; #endif if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/sound/mute")) return; method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); if (!strcmp(method, "none")) { return; } else if (!strcmp(method, "beep")) { gdk_beep(); return; } #ifdef _WIN32 else if (!strcmp(method, "playsoundw")) { pidgin_sound_play_file_win32(filename); return; } #endif /* _WIN32 */ if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { purple_debug_error("gtksound", "sound file (%s) does not exist.\n", filename); return; } #ifndef _WIN32 if (!strcmp(method, "custom")) { const char *sound_cmd; char *command; char *esc_filename; char **argv = NULL; GError *error = NULL; GPid pid; sound_cmd = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/sound/command"); if (!sound_cmd || *sound_cmd == '\0') { purple_debug_error("gtksound", "'Command' sound method has been chosen, " "but no command has been set.\n"); return; } esc_filename = g_shell_quote(filename); if(strstr(sound_cmd, "%s")) command = purple_strreplace(sound_cmd, "%s", esc_filename); else command = g_strdup_printf("%s %s", sound_cmd, esc_filename); if (!g_shell_parse_argv(command, NULL, &argv, &error)) { purple_debug_error("gtksound", "error parsing command %s (%s)\n", command, error->message); g_error_free(error); g_free(esc_filename); g_free(command); return; } if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &error)) { purple_debug_error("gtksound", "sound command could not be launched: %s\n", error->message); g_error_free(error); } else { purple_timeout_add_seconds(15, expire_old_child, GINT_TO_POINTER(pid)); } g_strfreev(argv); g_free(esc_filename); g_free(command); return; } #endif /* _WIN32 */ #ifdef USE_GSTREAMER if (gst_init_failed) /* Perhaps do gdk_beep instead? */ return; volume = (float)(CLAMP(purple_prefs_get_int(PIDGIN_PREFS_ROOT "/sound/volume"),0,100)) / 50; #ifdef _WIN32 if (!strcmp(method, "automatic")) { sink = gst_element_factory_make("directsoundsink", "sink"); if (sink == NULL) sink = gst_element_factory_make("waveformsink", "sink"); if (sink == NULL) sink = gst_element_factory_make("gconfaudiosink", "sink"); } else if (!strcmp(method, "directsound")) { sink = gst_element_factory_make("directsoundsink", "sink"); } else if (!strcmp(method, "waveform")) { sink = gst_element_factory_make("waveformsink", "sink"); } #else if (!strcmp(method, "automatic")) { sink = gst_element_factory_make("gconfaudiosink", "sink"); } else if (!strcmp(method, "esd")) { sink = gst_element_factory_make("esdsink", "sink"); } else if (!strcmp(method, "alsa")) { sink = gst_element_factory_make("alsasink", "sink"); } #endif else { purple_debug_error("sound", "Unknown sound method '%s'\n", method); return; } if (strcmp(method, "automatic") != 0 && !sink) { purple_debug_error("sound", "Unable to create GStreamer audiosink.\n"); return; } #if GST_CHECK_VERSION(1,0,0) play = gst_element_factory_make("playbin", "play"); #else play = gst_element_factory_make("playbin2", "play"); #endif if (play == NULL) { return; } #ifdef _WIN32 uri = g_strdup_printf("file:///%s", filename); g_strdelimit(uri, "\\", '/'); #else uri = g_strdup_printf("file://%s", filename); #endif g_object_set(G_OBJECT(play), "uri", uri, "volume", volume, "audio-sink", sink, NULL); bus = gst_pipeline_get_bus(GST_PIPELINE(play)); gst_bus_add_watch(bus, bus_call, play); gst_element_set_state(play, GST_STATE_PLAYING); gst_object_unref(bus); g_free(uri); #else /* #ifdef USE_GSTREAMER */ #ifndef _WIN32 gdk_beep(); #else /* _WIN32 */ pidgin_sound_play_file_win32(filename); #endif /* _WIN32 */ #endif /* USE_GSTREAMER */ }
// FIXME: Changes needed static gchar *gfire_game_config_get_command(const gfire_game_configuration *p_gconf, const gfire_game_data *p_game_data) { if (!p_gconf) { purple_debug_error("gfire", "Invalid game config info.\n"); return NULL; } const gfire_game *game = gfire_game_by_id(p_gconf->game_id); if(!game) { purple_debug_error("gfire", "gfire_game_config_get_command: Game not existing.\n"); return NULL; } if (!game->detection_sets || !((gfire_game_detection_set*)game->detection_sets->data)->launch_args || !p_gconf->launch_file) { purple_debug_error("gfire", "Insufficient information available!\n"); return NULL; } // Get the first detection set gfire_game_detection_set *dset = (gfire_game_detection_set*)game->detection_sets->data; gchar *username_args = NULL; /* This is not implemented yet, so let it stay NULL for now if(dset->username_args) { username_args = purple_strreplace(dset->username_args, "%UA_GAME_HOST_USERNAME%", ""); }*/ gchar *password_args = NULL; /* This is not implemented yet, so let it stay NULL for now if(dset->password_args) { password_args = purple_strreplace(dset->password_args, "%UA_GAME_HOST_PASSWORD%", ""); }*/ gchar *tmp, *tmp2; gchar *network_args = NULL; if(dset->network_args && p_game_data && p_game_data->ip.value) { gchar *server_ip_tmp = NULL, *server_port_tmp = NULL, *tmp = NULL, *tmp2 = NULL; server_port_tmp = gfire_game_data_port_str(p_game_data); server_ip_tmp = gfire_game_data_ip_str(p_game_data); // Replace IP and port tmp = purple_strreplace(dset->network_args, "%UA_GAME_HOST_NAME%", server_ip_tmp); tmp2 = purple_strreplace(tmp, "%UA_GAME_HOST_PORT%", server_port_tmp); g_free(tmp); g_free(server_port_tmp); g_free(server_ip_tmp); // Replace username tmp = purple_strreplace(tmp2, "%UA_LAUNCHER_USERNAME_ARGS%", username_args ? username_args : ""); g_free(tmp2); // Replace password network_args = purple_strreplace(tmp, "%UA_LAUNCHER_PASSWORD_ARGS%", password_args ? password_args : ""); g_free(tmp); } g_free(username_args); g_free(password_args); gchar *exe; #ifdef _WIN32 exe = g_strdup_printf("\"%s\"", p_gconf->launch_file); #else // Checks for Wine compatibility if needed exe = g_strdup_printf("%s \"%s\"", gfire_filetype_use_wine(p_gconf->launch_file) ? "wine": "", p_gconf->launch_file); #endif tmp = purple_strreplace(dset->launch_args, "%UA_LAUNCHER_EXE_PATH%", exe); g_free(exe); tmp2 = purple_strreplace(tmp, "%UA_LAUNCHER_EXTRA_ARGS%", ""); // Unknown g_free(tmp); gchar *launch_cmd = purple_strreplace(tmp2, "%UA_LAUNCHER_NETWORK_ARGS%", network_args ? network_args : ""); g_free(network_args); g_free(tmp2); return launch_cmd; }
static void * pidgin_notify_uri(const char *uri) { #ifndef _WIN32 char *escaped = g_shell_quote(uri); char *command = NULL; char *remote_command = NULL; const char *web_browser; int place; web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/browser"); place = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/browsers/place"); /* if they are running gnome, use the gnome web browser */ if (purple_running_gnome() == TRUE) { char *tmp = g_find_program_in_path("xdg-open"); if (tmp == NULL) command = g_strdup_printf("gnome-open %s", escaped); else command = g_strdup_printf("xdg-open %s", escaped); g_free(tmp); } else if (purple_running_osx() == TRUE) { command = g_strdup_printf("open %s", escaped); } else if (!strcmp(web_browser, "epiphany") || !strcmp(web_browser, "galeon")) { if (place == PIDGIN_BROWSER_NEW_WINDOW) command = g_strdup_printf("%s -w %s", web_browser, escaped); else if (place == PIDGIN_BROWSER_NEW_TAB) command = g_strdup_printf("%s -n %s", web_browser, escaped); else command = g_strdup_printf("%s %s", web_browser, escaped); } else if (!strcmp(web_browser, "xdg-open")) { command = g_strdup_printf("xdg-open %s", escaped); } else if (!strcmp(web_browser, "gnome-open")) { command = g_strdup_printf("gnome-open %s", escaped); } else if (!strcmp(web_browser, "kfmclient")) { command = g_strdup_printf("kfmclient openURL %s", escaped); /* * Does Konqueror have options to open in new tab * and/or current window? */ } else if (!strcmp(web_browser, "mozilla") || !strcmp(web_browser, "mozilla-firebird") || !strcmp(web_browser, "firefox") || !strcmp(web_browser, "seamonkey")) { char *args = ""; command = g_strdup_printf("%s %s", web_browser, escaped); /* * Firefox 0.9 and higher require a "-a firefox" option when * using -remote commands. This breaks older versions of * mozilla. So we include this other handly little string * when calling firefox. If the API for remote calls changes * any more in firefox then firefox should probably be split * apart from mozilla-firebird and mozilla... but this is good * for now. */ if (!strcmp(web_browser, "firefox")) args = "-a firefox"; if (place == PIDGIN_BROWSER_NEW_WINDOW) remote_command = g_strdup_printf("%s %s -remote " "openURL(%s,new-window)", web_browser, args, escaped); else if (place == PIDGIN_BROWSER_NEW_TAB) remote_command = g_strdup_printf("%s %s -remote " "openURL(%s,new-tab)", web_browser, args, escaped); else if (place == PIDGIN_BROWSER_CURRENT) remote_command = g_strdup_printf("%s %s -remote " "openURL(%s)", web_browser, args, escaped); } else if (!strcmp(web_browser, "netscape")) { command = g_strdup_printf("netscape %s", escaped); if (place == PIDGIN_BROWSER_NEW_WINDOW) { remote_command = g_strdup_printf("netscape -remote " "openURL(%s,new-window)", escaped); } else if (place == PIDGIN_BROWSER_CURRENT) { remote_command = g_strdup_printf("netscape -remote " "openURL(%s)", escaped); } } else if (!strcmp(web_browser, "opera")) { if (place == PIDGIN_BROWSER_NEW_WINDOW) command = g_strdup_printf("opera -newwindow %s", escaped); else if (place == PIDGIN_BROWSER_NEW_TAB) command = g_strdup_printf("opera -newpage %s", escaped); else if (place == PIDGIN_BROWSER_CURRENT) { remote_command = g_strdup_printf("opera -remote " "openURL(%s)", escaped); command = g_strdup_printf("opera %s", escaped); } else command = g_strdup_printf("opera %s", escaped); } else if (!strcmp(web_browser, "custom")) { const char *web_command; web_command = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/browsers/command"); if (web_command == NULL || *web_command == '\0') { purple_notify_error(NULL, NULL, _("Unable to open URL"), _("The 'Manual' browser command has been " "chosen, but no command has been set.")); return NULL; } if (strstr(web_command, "%s")) command = purple_strreplace(web_command, "%s", escaped); else { /* * There is no "%s" in the browser command. Assume the user * wanted the URL tacked on to the end of the command. */ command = g_strdup_printf("%s %s", web_command, escaped); } } g_free(escaped); if (remote_command != NULL) { /* try the remote command first */ if (uri_command(remote_command, TRUE) != 0) uri_command(command, FALSE); g_free(remote_command); } else uri_command(command, FALSE); g_free(command); #else /* !_WIN32 */ winpidgin_notify_uri(uri); #endif /* !_WIN32 */ return NULL; }
gchar * ggp_message_format_to_gg(PurpleConversation *conv, const gchar *text) { gchar *text_new, *tmp; GList *rt = NULL; /* reformatted text */ GMatchInfo *match; guint pos = 0; GList *pending_objects = NULL; GList *font_stack = NULL; static int html_sizes_pt[7] = { 7, 8, 9, 10, 12, 14, 16 }; ggp_font *font_new, *font_current, *font_base; gboolean font_changed = FALSE; gboolean in_any_tag = FALSE; /* TODO: verbose * purple_debug_info("gg", "ggp formatting text: [%s]\n", text); */ /* default font */ font_base = ggp_font_new(); font_current = ggp_font_new(); font_new = ggp_font_new(); /* GG11 doesn't use nbsp, it just print spaces */ text_new = purple_strreplace(text, " ", " "); /* add end-of-message tag */ if (strstr(text_new, "<eom>") != NULL) { tmp = text_new; text_new = purple_strreplace(text_new, "<eom>", ""); g_free(tmp); purple_debug_warning("gg", "ggp_message_format_to_gg: " "unexpected <eom> tag\n"); } tmp = text_new; text_new = g_strdup_printf("%s<eom></eom>", text_new); g_free(tmp); g_regex_match(global_data.re_html_tag, text_new, 0, &match); while (g_match_info_matches(match)) { int m_start, m_end, m_pos; gboolean tag_close; gchar *tag_str, *attribs_str; ggp_html_tag tag; gboolean text_before; /* reading tag and its contents */ g_match_info_fetch_pos(match, 0, &m_start, &m_end); g_assert(m_start >= 0 && m_end >= 0); text_before = ((guint)m_start > pos); g_match_info_fetch_pos(match, 1, &m_pos, NULL); tag_close = (m_pos >= 0); tag_str = g_match_info_fetch(match, 2); tag = ggp_html_parse_tag(tag_str); attribs_str = g_match_info_fetch(match, 3); g_match_info_next(match, NULL); if (tag == GGP_HTML_TAG_UNKNOWN) { purple_debug_warning("gg", "ggp_message_format_to_gg: " "uknown tag %s\n", tag_str); } /* closing *all* formatting-related tags (GG11 weirness) * and adding pending objects */ if ((text_before && (font_changed || pending_objects)) || (tag == GGP_HTML_TAG_EOM && tag_close)) { font_changed = FALSE; if (in_any_tag) { in_any_tag = FALSE; if (font_current->s && !GGP_GG11_FORCE_COMPAT) rt = g_list_prepend(rt, g_strdup("</s>")); if (font_current->u) rt = g_list_prepend(rt, g_strdup("</u>")); if (font_current->i) rt = g_list_prepend(rt, g_strdup("</i>")); if (font_current->b) rt = g_list_prepend(rt, g_strdup("</b>")); rt = g_list_prepend(rt, g_strdup("</span>")); } if (pending_objects) { rt = g_list_concat(pending_objects, rt); pending_objects = NULL; } } /* opening formatting-related tags again */ if (text_before && !in_any_tag) { gchar *style; GList *styles = NULL; gboolean has_size = (font_new->size > 0 && font_new->size <= 7 && font_new->size != 3); if (has_size) styles = g_list_append(styles, g_strdup_printf( "font-size:%dpt;", html_sizes_pt[font_new->size - 1])); if (font_new->face) styles = g_list_append(styles, g_strdup_printf( "font-family:%s;", font_new->face)); if (font_new->bgcolor >= 0 && !GGP_GG11_FORCE_COMPAT) styles = g_list_append(styles, g_strdup_printf( "background-color:#%06x;", font_new->bgcolor)); if (font_new->color >= 0) styles = g_list_append(styles, g_strdup_printf( "color:#%06x;", font_new->color)); if (styles) { gchar *combined = ggp_strjoin_list(" ", styles); g_list_free_full(styles, g_free); style = g_strdup_printf(" style=\"%s\"", combined); g_free(combined); } else style = g_strdup(""); rt = g_list_prepend(rt, g_strdup_printf("<span%s>", style)); g_free(style); if (font_new->b) rt = g_list_prepend(rt, g_strdup("<b>")); if (font_new->i) rt = g_list_prepend(rt, g_strdup("<i>")); if (font_new->u) rt = g_list_prepend(rt, g_strdup("<u>")); if (font_new->s && !GGP_GG11_FORCE_COMPAT) rt = g_list_prepend(rt, g_strdup("<s>")); ggp_font_free(font_current); font_current = font_new; font_new = ggp_font_clone(font_current); in_any_tag = TRUE; } if (text_before) { rt = g_list_prepend(rt, g_strndup(text_new + pos, m_start - pos)); } /* set formatting of a following text */ if (tag == GGP_HTML_TAG_B) { font_changed |= (font_new->b != !tag_close); font_new->b = !tag_close; } else if (tag == GGP_HTML_TAG_I) { font_changed |= (font_new->i != !tag_close); font_new->i = !tag_close; } else if (tag == GGP_HTML_TAG_U) { font_changed |= (font_new->u != !tag_close); font_new->u = !tag_close; } else if (tag == GGP_HTML_TAG_S) { font_changed |= (font_new->s != !tag_close); font_new->s = !tag_close; } else if (tag == GGP_HTML_TAG_IMG && !tag_close) { GHashTable *attribs = ggp_html_tag_attribs(attribs_str); gchar *val = NULL; uint64_t id; int stored_id = -1; ggp_image_prepare_result res = -1; if ((val = g_hash_table_lookup(attribs, "src")) != NULL && g_str_has_prefix(val, PURPLE_STORED_IMAGE_PROTOCOL)) { val += strlen(PURPLE_STORED_IMAGE_PROTOCOL); if (sscanf(val, "%u", &stored_id) != 1) stored_id = -1; } if (stored_id >= 0) res = ggp_image_prepare(conv, stored_id, &id); if (res == GGP_IMAGE_PREPARE_OK) { pending_objects = g_list_prepend( pending_objects, g_strdup_printf( "<img name=\"" GGP_IMAGE_ID_FORMAT "\">", id)); } else if (res == GGP_IMAGE_PREPARE_TOO_BIG) { purple_conversation_write(conv, "", _("Image is too large, please try " "smaller one."), PURPLE_MESSAGE_ERROR, time(NULL)); } else { purple_conversation_write(conv, "", _("Image cannot be sent."), PURPLE_MESSAGE_ERROR, time(NULL)); } g_hash_table_destroy(attribs); } else if (tag == GGP_HTML_TAG_FONT && !tag_close) { GHashTable *attribs = ggp_html_tag_attribs(attribs_str); gchar *val = NULL; font_stack = g_list_prepend(font_stack, ggp_font_clone(font_new)); if ((val = g_hash_table_lookup(attribs, "size")) != NULL && val[0] >= '1' && val[0] <= '7' && val[1] == '\0') { int size = val[0] - '0'; font_changed |= (font_new->size != size); font_new->size = size; } if ((val = g_hash_table_lookup(attribs, "face")) != NULL) { font_changed |= (g_strcmp0(font_new->face, val) != 0); g_free(font_new->face); font_new->face = g_strdup(val); } if ((val = g_hash_table_lookup(attribs, "color")) != NULL && val[0] == '#' && strlen(val) == 7) { int color = ggp_html_decode_color(val); font_changed |= (font_new->color != color); font_new->color = color; } g_hash_table_destroy(attribs); } else if ((tag == GGP_HTML_TAG_SPAN || tag == GGP_HTML_TAG_DIV) && !tag_close) { GHashTable *attribs, *styles = NULL; gchar *style = NULL; gchar *val = NULL; attribs = ggp_html_tag_attribs(attribs_str); font_stack = g_list_prepend(font_stack, ggp_font_clone(font_new)); if (tag == GGP_HTML_TAG_DIV) pending_objects = g_list_prepend( pending_objects, g_strdup("<br>")); style = g_hash_table_lookup(attribs, "style"); if (style) styles = ggp_html_css_attribs(style); if ((val = g_hash_table_lookup(styles, "background-color")) != NULL) { int color = ggp_html_decode_color(val); font_changed |= (font_new->bgcolor != color); font_new->bgcolor = color; } if ((val = g_hash_table_lookup(styles, "color")) != NULL) { int color = ggp_html_decode_color(val); font_changed |= (font_new->color != color); font_new->color = color; } if (styles) g_hash_table_destroy(styles); g_hash_table_destroy(attribs); } else if ((tag == GGP_HTML_TAG_FONT || tag == GGP_HTML_TAG_SPAN || tag == GGP_HTML_TAG_DIV) && tag_close) { font_changed = TRUE; ggp_font_free(font_new); if (font_stack) { font_new = (ggp_font*)font_stack->data; font_stack = g_list_delete_link( font_stack, font_stack); } else font_new = ggp_font_clone(font_base); } else if (tag == GGP_HTML_TAG_BR) { pending_objects = g_list_prepend(pending_objects, g_strdup("<br>")); } else if (tag == GGP_HTML_TAG_HR) { pending_objects = g_list_prepend(pending_objects, g_strdup("<br><span>---</span><br>")); } else if (tag == GGP_HTML_TAG_A || tag == GGP_HTML_TAG_EOM) { /* do nothing */ } else if (tag == GGP_HTML_TAG_UNKNOWN) { purple_debug_warning("gg", "ggp_message_format_to_gg: " "uknown tag %s\n", tag_str); } else { purple_debug_error("gg", "ggp_message_format_to_gg: " "not handled tag %s\n", tag_str); } pos = m_end; g_free(tag_str); g_free(attribs_str); } g_match_info_free(match); if (pos < strlen(text_new) || in_any_tag) { purple_debug_fatal("gg", "ggp_message_format_to_gg: " "end of message not reached\n"); } /* releasing fonts recources */ ggp_font_free(font_new); ggp_font_free(font_current); ggp_font_free(font_base); g_list_free_full(font_stack, ggp_font_free); /* combining reformatted text info one string */ rt = g_list_reverse(rt); g_free(text_new); text_new = ggp_strjoin_list("", rt); g_list_free_full(rt, g_free); /* TODO: verbose * purple_debug_info("gg", "reformatted text: [%s]\n", text_new); */ return text_new; }