static GntWidget* create_string_field(PurpleRequestField *field, GntWidget **screenname) { const char *hint = purple_request_field_get_type_hint(field); GntWidget *entry = gnt_entry_new( purple_request_field_string_get_default_value(field)); gnt_entry_set_masked(GNT_ENTRY(entry), purple_request_field_string_is_masked(field)); if (hint && purple_str_has_prefix(hint, "screenname")) { PurpleBlistNode *node = purple_blist_get_root(); gboolean offline = purple_str_has_suffix(hint, "all"); for (; node; node = purple_blist_node_next(node, offline)) { if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) continue; gnt_entry_add_suggest(GNT_ENTRY(entry), purple_buddy_get_name((PurpleBuddy*)node)); } gnt_entry_set_always_suggest(GNT_ENTRY(entry), TRUE); if (screenname) *screenname = entry; } else if (hint && !strcmp(hint, "group")) { PurpleBlistNode *node; for (node = purple_blist_get_root(); node; node = purple_blist_node_get_sibling_next(node)) { if (PURPLE_BLIST_NODE_IS_GROUP(node)) gnt_entry_add_suggest(GNT_ENTRY(entry), purple_group_get_name((PurpleGroup *)node)); } } return entry; }
void jabber_google_presence_incoming(JabberStream *js, const char *user, JabberBuddyResource *jbr) { if (!js->googletalk) return; if (jbr->status && purple_str_has_prefix(jbr->status, "♫ ")) { purple_prpl_got_user_status(js->gc->account, user, "tune", PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL); g_free(jbr->status); jbr->status = NULL; } else { purple_prpl_got_user_status_deactive(js->gc->account, user, "tune"); } }
void msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport, const char *data) { PurpleConnection *gc; guchar *image_data; size_t image_len; int imgid; char *image_msg; if (!purple_str_has_prefix(data, "base64:")) { purple_debug_error("msn", "Ignoring Ink not in Base64 format.\n"); return; } gc = purple_account_get_connection(swboard->session->account); data += sizeof("base64:") - 1; image_data = purple_base64_decode(data, &image_len); if (!image_data || !image_len) { purple_debug_error("msn", "Unable to decode Ink from Base64 format.\n"); return; } imgid = purple_imgstore_add_with_id(image_data, image_len, NULL); image_msg = g_strdup_printf("<IMG ID='%d'/>", imgid); if (swboard->current_users > 1 || ((swboard->conv != NULL) && purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) serv_got_chat_in(gc, swboard->chat_id, passport, 0, image_msg, time(NULL)); else serv_got_im(gc, passport, image_msg, 0, time(NULL)); purple_imgstore_unref_by_id(imgid); g_free(image_msg); }
static gchar* purple_upnp_parse_description_response(const gchar* httpResponse, gsize len, const gchar* httpURL, const gchar* serviceType) { gchar *xmlRoot, *baseURL, *controlURL, *service; xmlnode *xmlRootNode, *serviceTypeNode, *controlURLNode, *baseURLNode; char *tmp; /* make sure we have a valid http response */ if(g_strstr_len(httpResponse, len, HTTP_OK) == NULL) { purple_debug_error("upnp", "parse_description_response(): Failed In HTTP_OK\n"); return NULL; } /* find the root of the xml document */ if((xmlRoot = g_strstr_len(httpResponse, len, "<root")) == NULL) { purple_debug_error("upnp", "parse_description_response(): Failed finding root\n"); return NULL; } /* create the xml root node */ if((xmlRootNode = xmlnode_from_str(xmlRoot, len - (xmlRoot - httpResponse))) == NULL) { purple_debug_error("upnp", "parse_description_response(): Could not parse xml root node\n"); return NULL; } /* get the baseURL of the device */ if((baseURLNode = xmlnode_get_child(xmlRootNode, "URLBase")) != NULL) { baseURL = xmlnode_get_data(baseURLNode); } else { baseURL = g_strdup(httpURL); } /* get the serviceType child that has the service type as its data */ /* get urn:schemas-upnp-org:device:InternetGatewayDevice:1 and its devicelist */ serviceTypeNode = xmlnode_get_child(xmlRootNode, "device"); while(!purple_upnp_compare_device(serviceTypeNode, "urn:schemas-upnp-org:device:InternetGatewayDevice:1") && serviceTypeNode != NULL) { serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); } if(serviceTypeNode == NULL) { purple_debug_error("upnp", "parse_description_response(): could not get serviceTypeNode 1\n"); g_free(baseURL); xmlnode_free(xmlRootNode); return NULL; } serviceTypeNode = xmlnode_get_child(serviceTypeNode, "deviceList"); if(serviceTypeNode == NULL) { purple_debug_error("upnp", "parse_description_response(): could not get serviceTypeNode 2\n"); g_free(baseURL); xmlnode_free(xmlRootNode); return NULL; } /* get urn:schemas-upnp-org:device:WANDevice:1 and its devicelist */ serviceTypeNode = xmlnode_get_child(serviceTypeNode, "device"); while(!purple_upnp_compare_device(serviceTypeNode, "urn:schemas-upnp-org:device:WANDevice:1") && serviceTypeNode != NULL) { serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); } if(serviceTypeNode == NULL) { purple_debug_error("upnp", "parse_description_response(): could not get serviceTypeNode 3\n"); g_free(baseURL); xmlnode_free(xmlRootNode); return NULL; } serviceTypeNode = xmlnode_get_child(serviceTypeNode, "deviceList"); if(serviceTypeNode == NULL) { purple_debug_error("upnp", "parse_description_response(): could not get serviceTypeNode 4\n"); g_free(baseURL); xmlnode_free(xmlRootNode); return NULL; } /* get urn:schemas-upnp-org:device:WANConnectionDevice:1 and its servicelist */ serviceTypeNode = xmlnode_get_child(serviceTypeNode, "device"); while(serviceTypeNode && !purple_upnp_compare_device(serviceTypeNode, "urn:schemas-upnp-org:device:WANConnectionDevice:1")) { serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); } if(serviceTypeNode == NULL) { purple_debug_error("upnp", "parse_description_response(): could not get serviceTypeNode 5\n"); g_free(baseURL); xmlnode_free(xmlRootNode); return NULL; } serviceTypeNode = xmlnode_get_child(serviceTypeNode, "serviceList"); if(serviceTypeNode == NULL) { purple_debug_error("upnp", "parse_description_response(): could not get serviceTypeNode 6\n"); g_free(baseURL); xmlnode_free(xmlRootNode); return NULL; } /* get the serviceType variable passed to this function */ service = g_strdup_printf(SEARCH_REQUEST_DEVICE, serviceType); serviceTypeNode = xmlnode_get_child(serviceTypeNode, "service"); while(!purple_upnp_compare_service(serviceTypeNode, service) && serviceTypeNode != NULL) { serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); } g_free(service); if(serviceTypeNode == NULL) { purple_debug_error("upnp", "parse_description_response(): could not get serviceTypeNode 7\n"); g_free(baseURL); xmlnode_free(xmlRootNode); return NULL; } /* get the controlURL of the service */ if((controlURLNode = xmlnode_get_child(serviceTypeNode, "controlURL")) == NULL) { purple_debug_error("upnp", "parse_description_response(): Could not find controlURL\n"); g_free(baseURL); xmlnode_free(xmlRootNode); return NULL; } tmp = xmlnode_get_data(controlURLNode); if(baseURL && !purple_str_has_prefix(tmp, "http://") && !purple_str_has_prefix(tmp, "HTTP://")) { /* Handle absolute paths in a relative URL. This probably * belongs in util.c. */ if (tmp[0] == '/') { size_t length; const char *path, *start = strstr(baseURL, "://"); start = start ? start + 3 : baseURL; path = strchr(start, '/'); length = path ? path - baseURL : strlen(baseURL); controlURL = g_strdup_printf("%.*s%s", (int)length, baseURL, tmp); } else { controlURL = g_strdup_printf("%s%s", baseURL, tmp); } g_free(tmp); }else{ controlURL = tmp; } g_free(baseURL); xmlnode_free(xmlRootNode); return controlURL; }
void msn_message_parse_payload(MsnMessage *msg, const char *payload, size_t payload_len, const char *line_dem,const char *body_dem) { char *tmp_base, *tmp; const char *content_type; char *end; char **elems, **cur, **tokens; g_return_if_fail(payload != NULL); tmp_base = tmp = g_malloc(payload_len + 1); memcpy(tmp_base, payload, payload_len); tmp_base[payload_len] = '\0'; /* Find the end of the headers */ end = strstr(tmp, body_dem); /* TODO? some clients use \r delimiters instead of \r\n, the official client * doesn't send such messages, but does handle receiving them. We'll just * avoid crashing for now */ if (end == NULL) { g_free(tmp_base); g_return_if_reached(); } /* NUL-terminate the end of the headers - it'll get skipped over below */ *end = '\0'; /* Split the headers and parse each one */ elems = g_strsplit(tmp, line_dem, 0); for (cur = elems; *cur != NULL; cur++) { const char *key, *value; /* If this line starts with whitespace, it's been folded from the previous line and won't have ':'. */ if ((**cur == ' ') || (**cur == '\t')) { tokens = g_strsplit(g_strchug(*cur), "=\"", 2); key = tokens[0]; value = tokens[1]; /* The only one I care about is 'boundary' (which is folded from the key 'Content-Type'), so only process that. */ if (!strcmp(key, "boundary") && value) { char *end = strchr(value, '\"'); if (end) { *end = '\0'; msn_message_set_header(msg, key, value); } } g_strfreev(tokens); continue; } tokens = g_strsplit(*cur, ": ", 2); key = tokens[0]; value = tokens[1]; if (!strcmp(key, "MIME-Version")) { /* Ignore MIME-Version header */ } else if (!strcmp(key, "Content-Type")) { char *charset, *c; if (value && (c = strchr(value, ';')) != NULL) { if ((charset = strchr(c, '=')) != NULL) { charset++; msn_message_set_charset(msg, charset); } *c = '\0'; } msn_message_set_content_type(msg, value); } else { msn_message_set_header(msg, key, value); } g_strfreev(tokens); } g_strfreev(elems); /* Proceed to the end of the "\r\n\r\n" */ tmp = end + strlen(body_dem); /* Now we *should* be at the body. */ content_type = msn_message_get_content_type(msg); if (payload_len - (tmp - tmp_base) > 0) { msg->body_len = payload_len - (tmp - tmp_base); g_free(msg->body); msg->body = g_malloc(msg->body_len + 1); memcpy(msg->body, tmp, msg->body_len); msg->body[msg->body_len] = '\0'; } if (msg->body && content_type && purple_str_has_prefix(content_type, "text/")) { char *body = NULL; if (msg->charset == NULL || g_str_equal(msg->charset, "UTF-8")) { /* Charset is UTF-8 */ if (!g_utf8_validate(msg->body, msg->body_len, NULL)) { purple_debug_warning("msn", "Message contains invalid " "UTF-8. Attempting to salvage.\n"); body = purple_utf8_salvage(msg->body); payload_len = strlen(body); } } else { /* Charset is something other than UTF-8 */ GError *err = NULL; body = g_convert(msg->body, msg->body_len, "UTF-8", msg->charset, NULL, &payload_len, &err); if (!body || err) { purple_debug_warning("msn", "Unable to convert message from " "%s to UTF-8: %s\n", msg->charset, err ? err->message : "Unknown error"); if (err) g_error_free(err); /* Fallback to ISO-8859-1 */ g_free(body); body = g_convert(msg->body, msg->body_len, "UTF-8", "ISO-8859-1", NULL, &payload_len, NULL); if (!body) { g_free(msg->body); msg->body = NULL; msg->body_len = 0; } } } if (body) { g_free(msg->body); msg->body = body; msg->body_len = payload_len; msn_message_set_charset(msg, "UTF-8"); } } g_free(tmp_base); }
/*------------------------------------------------------------------------ * Convert libpurple (HTML) markup to MXit protocol markup (for sending to MXit). * Any MXit markup codes in the original message also need to be escaped. * * @param message The message text containing libPurple (HTML) markup * @return The message text containing MXit markup */ char* mxit_convert_markup_tx( const char* message, int* msgtype ) { GString* mx; struct tag* tag; GList* entry; GList* tagstack = NULL; char* reply; int len = strlen ( message ); int i; #ifdef MXIT_DEBUG_MARKUP purple_debug_info( MXIT_PLUGIN_ID, "Markup TX (original): '%s'\n", message ); #endif /* * libPurple uses the following HTML markup codes: * Bold: <b>...</b> * Italics: <i>...</i> * Underline: <u>...</u> * Strikethrough: <s>...</s> (NO MXIT SUPPORT) * Font size: <font size="">...</font> * Font type: <font face="">...</font> (NO MXIT SUPPORT) * Font colour: <font color=#">...</font> * Links: <a href="">...</a> * Newline: <br> * Inline image: <IMG ID=""> * The following characters are also encoded: * & " < > */ /* new message data */ mx = g_string_sized_new( len ); /* run through the message and check for HTML markup */ for ( i = 0; i < len; i++ ) { switch ( message[i] ) { case '<' : if ( purple_str_has_prefix( &message[i], "<b>" ) || purple_str_has_prefix( &message[i], "</b>" ) ) { /* bold */ g_string_append_c( mx, '*' ); } else if ( purple_str_has_prefix( &message[i], "<i>" ) || purple_str_has_prefix( &message[i], "</i>" ) ) { /* italics */ g_string_append_c( mx, '/' ); } else if ( purple_str_has_prefix( &message[i], "<u>" ) || purple_str_has_prefix( &message[i], "</u>" ) ) { /* underline */ g_string_append_c( mx, '_' ); } else if ( purple_str_has_prefix( &message[i], "<br>" ) ) { /* newline */ g_string_append_c( mx, '\n' ); } else if ( purple_str_has_prefix( &message[i], "<font size=" ) ) { /* font size */ int fontsize; tag = g_new0( struct tag, 1 ); tag->type = MXIT_TAG_SIZE; tagstack = g_list_prepend( tagstack, tag ); // TODO: implement size control if ( sscanf( &message[i+12], "%i", &fontsize ) ) { purple_debug_info( MXIT_PLUGIN_ID, "Font size set to %i\n", fontsize ); } } else if ( purple_str_has_prefix( &message[i], "<font color=" ) ) { /* font colour */ char color[8]; /* ensure we have the complete tag: <font color="#123456"> */ if ( i + 20 < len ) { tag = g_new0( struct tag, 1 ); tag->type = MXIT_TAG_COLOR; tagstack = g_list_append( tagstack, tag ); memset( color, 0x00, sizeof( color ) ); memcpy( color, &message[i + 13], 7 ); g_string_append( mx, color ); }
PurplePlugin * purple_plugin_probe(const char *filename) { #ifdef PURPLE_PLUGINS PurplePlugin *plugin = NULL; PurplePlugin *loader; gpointer unpunned; gchar *basename = NULL; gboolean (*purple_init_plugin)(PurplePlugin *); purple_debug_misc("plugins", "probing %s\n", filename); g_return_val_if_fail(filename != NULL, NULL); if (!g_file_test(filename, G_FILE_TEST_EXISTS)) return NULL; /* If this plugin has already been probed then exit */ basename = purple_plugin_get_basename(filename); plugin = purple_plugins_find_with_basename(basename); g_free(basename); if (plugin != NULL) { if (purple_strequal(filename, plugin->path)) return plugin; else if (!purple_plugin_is_unloadable(plugin)) { purple_debug_warning("plugins", "Not loading %s. " "Another plugin with the same name (%s) has already been loaded.\n", filename, plugin->path); return plugin; } else { /* The old plugin was a different file and it was unloadable. * There's no guarantee that this new file with the same name * will be loadable, but unless it fails in one of the silent * ways and the first one didn't, it's not any worse. The user * will still see a greyed-out plugin, which is what we want. */ purple_plugin_destroy(plugin); } } plugin = purple_plugin_new(has_file_extension(filename, G_MODULE_SUFFIX), filename); if (plugin->native_plugin) { const char *error; #ifdef _WIN32 /* Suppress error popups for failing to load plugins */ UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS); #endif /* * We pass G_MODULE_BIND_LOCAL here to prevent symbols from * plugins being added to the global name space. * * G_MODULE_BIND_LOCAL was added in glib 2.3.3. */ plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL); if (plugin->handle == NULL) { const char *error = g_module_error(); if (error != NULL && purple_str_has_prefix(error, filename)) { error = error + strlen(filename); /* These are just so we don't crash. If we * got this far, they should always be true. */ if (*error == ':') error++; if (*error == ' ') error++; } if (error == NULL || !*error) { plugin->error = g_strdup(_("Unknown error")); purple_debug_error("plugins", "%s is not loadable: Unknown error\n", plugin->path); } else { plugin->error = g_strdup(error); purple_debug_error("plugins", "%s is not loadable: %s\n", plugin->path, plugin->error); } plugin->handle = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); if (plugin->handle == NULL) { #ifdef _WIN32 /* Restore the original error mode */ SetErrorMode(old_error_mode); #endif purple_plugin_destroy(plugin); return NULL; } else { /* We were able to load the plugin with lazy symbol binding. * This means we're missing some symbol. Mark it as * unloadable and keep going so we get the info to display * to the user so they know to rebuild this plugin. */ plugin->unloadable = TRUE; } } if (!g_module_symbol(plugin->handle, "purple_init_plugin", &unpunned)) { purple_debug_error("plugins", "%s is not usable because the " "'purple_init_plugin' symbol could not be " "found. Does the plugin call the " "PURPLE_INIT_PLUGIN() macro?\n", plugin->path); g_module_close(plugin->handle); error = g_module_error(); if (error != NULL) purple_debug_error("plugins", "Error closing module %s: %s\n", plugin->path, error); plugin->handle = NULL; #ifdef _WIN32 /* Restore the original error mode */ SetErrorMode(old_error_mode); #endif purple_plugin_destroy(plugin); return NULL; } purple_init_plugin = unpunned; #ifdef _WIN32 /* Restore the original error mode */ SetErrorMode(old_error_mode); #endif } else { loader = find_loader_for_plugin(plugin); if (loader == NULL) { purple_plugin_destroy(plugin); return NULL; } purple_init_plugin = PURPLE_PLUGIN_LOADER_INFO(loader)->probe; } if (!purple_init_plugin(plugin) || plugin->info == NULL) { purple_plugin_destroy(plugin); return NULL; } else if (plugin->info->ui_requirement && !purple_strequal(plugin->info->ui_requirement, purple_core_get_ui())) { plugin->error = g_strdup_printf(_("You are using %s, but this plugin requires %s."), purple_core_get_ui(), plugin->info->ui_requirement); purple_debug_error("plugins", "%s is not loadable: The UI requirement is not met. (%s)\n", plugin->path, plugin->error); plugin->unloadable = TRUE; return plugin; } /* * Check to make sure a plugin has defined an id. * Not having this check caused purple_plugin_unload to * enter an infinite loop in certain situations by passing * purple_find_plugin_by_id a NULL value. -- ecoffey */ if (plugin->info->id == NULL || *plugin->info->id == '\0') { plugin->error = g_strdup(_("This plugin has not defined an ID.")); purple_debug_error("plugins", "%s is not loadable: info->id is not defined.\n", plugin->path); plugin->unloadable = TRUE; return plugin; } /* Really old plugins. */ if (plugin->info->magic != PURPLE_PLUGIN_MAGIC) { if (plugin->info->magic >= 2 && plugin->info->magic <= 4) { struct _PurplePluginInfo2 { unsigned int api_version; PurplePluginType type; char *ui_requirement; unsigned long flags; GList *dependencies; PurplePluginPriority priority; char *id; char *name; char *version; char *summary; char *description; char *author; char *homepage; gboolean (*load)(PurplePlugin *plugin); gboolean (*unload)(PurplePlugin *plugin); void (*destroy)(PurplePlugin *plugin); void *ui_info; void *extra_info; PurplePluginUiInfo *prefs_info; GList *(*actions)(PurplePlugin *plugin, gpointer context); } *info2 = (struct _PurplePluginInfo2 *)plugin->info; /* This leaks... but only for ancient plugins, so deal with it. */ plugin->info = g_new0(PurplePluginInfo, 1); /* We don't really need all these to display the plugin info, but * I'm copying them all for good measure. */ plugin->info->magic = info2->api_version; plugin->info->type = info2->type; plugin->info->ui_requirement = info2->ui_requirement; plugin->info->flags = info2->flags; plugin->info->dependencies = info2->dependencies; plugin->info->id = info2->id; plugin->info->name = info2->name; plugin->info->version = info2->version; plugin->info->summary = info2->summary; plugin->info->description = info2->description; plugin->info->author = info2->author; plugin->info->homepage = info2->homepage; plugin->info->load = info2->load; plugin->info->unload = info2->unload; plugin->info->destroy = info2->destroy; plugin->info->ui_info = info2->ui_info; plugin->info->extra_info = info2->extra_info; if (info2->api_version >= 3) plugin->info->prefs_info = info2->prefs_info; if (info2->api_version >= 4) plugin->info->actions = info2->actions; plugin->error = g_strdup_printf(_("Plugin magic mismatch %d (need %d)"), plugin->info->magic, PURPLE_PLUGIN_MAGIC); purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n", plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC); plugin->unloadable = TRUE; return plugin; } purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n", plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC); purple_plugin_destroy(plugin); return NULL; } if (plugin->info->major_version != PURPLE_MAJOR_VERSION || plugin->info->minor_version > PURPLE_MINOR_VERSION) { plugin->error = g_strdup_printf(_("ABI version mismatch %d.%d.x (need %d.%d.x)"), plugin->info->major_version, plugin->info->minor_version, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION); purple_debug_error("plugins", "%s is not loadable: ABI version mismatch %d.%d.x (need %d.%d.x)\n", plugin->path, plugin->info->major_version, plugin->info->minor_version, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION); plugin->unloadable = TRUE; return plugin; } if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) { /* If plugin is a PRPL, make sure it implements the required functions */ if ((PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon == NULL) || (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->login == NULL) || (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->close == NULL)) { plugin->error = g_strdup(_("Plugin does not implement all required functions (list_icon, login and close)")); purple_debug_error("plugins", "%s is not loadable: %s\n", plugin->path, plugin->error); plugin->unloadable = TRUE; return plugin; } /* For debugging, let's warn about prpl prefs. */ if (plugin->info->prefs_info != NULL) { purple_debug_error("plugins", "%s has a prefs_info, but is a prpl. This is no longer supported.\n", plugin->path); } } return plugin; #else return NULL; #endif /* !PURPLE_PLUGINS */ }