static JabberSaslState jabber_cyrus_handle_challenge(JabberStream *js, xmlnode *packet, xmlnode **reply, char **error) { char *enc_in = xmlnode_get_data(packet); unsigned char *dec_in; char *enc_out; const char *c_out; unsigned int clen; gsize declen; dec_in = purple_base64_decode(enc_in, &declen); js->sasl_state = sasl_client_step(js->sasl, (char*)dec_in, declen, NULL, &c_out, &clen); g_free(enc_in); g_free(dec_in); if (js->sasl_state != SASL_CONTINUE && js->sasl_state != SASL_OK) { gchar *tmp = g_strdup_printf(_("SASL error: %s"), sasl_errdetail(js->sasl)); purple_debug_error("jabber", "Error is %d : %s\n", js->sasl_state, sasl_errdetail(js->sasl)); *error = tmp; return JABBER_SASL_STATE_FAIL; } else { xmlnode *response = xmlnode_new("response"); xmlnode_set_namespace(response, NS_XMPP_SASL); if (clen > 0) { /* Cyrus SASL 2.1.22 appears to contain code to add the charset * to the response for DIGEST-MD5 but there is no possibility * it will be executed. * * My reading of the digestmd5 plugin indicates the username and * realm are always encoded in UTF-8 (they seem to be the values * we pass in), so we need to ensure charset=utf-8 is set. */ if (!purple_strequal(js->current_mech, "DIGEST-MD5") || strstr(c_out, ",charset=")) /* If we're not using DIGEST-MD5 or Cyrus SASL is fixed */ enc_out = purple_base64_encode((unsigned char*)c_out, clen); else { char *tmp = g_strdup_printf("%s,charset=utf-8", c_out); enc_out = purple_base64_encode((unsigned char*)tmp, clen + 14); g_free(tmp); } xmlnode_insert_data(response, enc_out, -1); g_free(enc_out); } *reply = response; return JABBER_SASL_STATE_CONTINUE; } }
static char * msn_httpconn_proxy_auth(MsnHttpConn *httpconn) { PurpleAccount *account; PurpleProxyInfo *gpi; const char *username, *password; char *auth = NULL; account = httpconn->session->account; gpi = purple_proxy_get_setup(account); if (gpi == NULL || !(purple_proxy_info_get_type(gpi) == PURPLE_PROXY_HTTP || purple_proxy_info_get_type(gpi) == PURPLE_PROXY_USE_ENVVAR)) return NULL; username = purple_proxy_info_get_username(gpi); password = purple_proxy_info_get_password(gpi); if (username != NULL) { char *tmp; auth = g_strdup_printf("%s:%s", username, password ? password : ""); tmp = purple_base64_encode((const guchar *)auth, strlen(auth)); g_free(auth); auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp); g_free(tmp); } return auth; }
/* TODO find a way to do this without libpurple */ static inline char * get_auth(PnNode *conn) { const char *username, *password; PurpleProxyInfo *gpi; char *tmp, *auth; gpi = purple_proxy_get_setup(msn_session_get_user_data(conn->session)); if (!gpi) return NULL; if (purple_proxy_info_get_type(gpi) != PURPLE_PROXY_HTTP && purple_proxy_info_get_type(gpi) != PURPLE_PROXY_USE_ENVVAR) return NULL; username = purple_proxy_info_get_username(gpi); password = purple_proxy_info_get_password(gpi); if (!username && !password) return NULL; auth = g_strdup_printf("%s:%s", username ? username : "", password ? password : ""); tmp = purple_base64_encode((const guchar *) auth, strlen(auth)); g_free(auth); auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp); g_free(tmp); return auth; }
/*------------------------------------------------------------------------ * Adds a link to a message * * @param mx The Markup message object * @param replydata This is the what will be returned when the link gets clicked * @param isStructured Indicates that the reply is a structured reply * @param displaytext This is the text for the link which will be displayed in the UI */ void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext ) { #ifdef MXIT_LINK_CLICK gchar* link = NULL; gchar* link64 = NULL; /* * The link content is encoded as follows: * MXIT_LINK_KEY | ACCOUNT_USER | ACCOUNT_PROTO | REPLY_TO | REPLY_FORMAT | REPLY_DATA */ link = g_strdup_printf( "%s|%s|%s|%s|%i|%s", MXIT_LINK_KEY, purple_account_get_username( mx->session->acc ), purple_account_get_protocol_id( mx->session->acc ), mx->from, isStructured ? 1 : 0, replydata ); link64 = purple_base64_encode( (const unsigned char*) link, strlen( link ) ); g_string_append_printf( mx->msg, "<a href=\"%s%s\">%s</a>", MXIT_LINK_PREFIX, link64, displaytext ); g_free( link64 ); g_free( link ); #else g_string_append_printf( mx->msg, "<b>%s</b>", replydata ); #endif }
static gchar *twitter_oauth_sign(const gchar * txt, const gchar * key) { PurpleCipher *cipher; PurpleCipherContext *ctx; static guchar output[20]; size_t output_size; cipher = purple_ciphers_find_cipher("hmac"); if (!cipher) { purple_debug_error(GENERIC_PROTOCOL_ID, "%s: Could not find cipher\n", G_STRFUNC); return NULL; } ctx = purple_cipher_context_new(cipher, NULL); if (!ctx) { purple_debug_error(GENERIC_PROTOCOL_ID, "%s: Could not create cipher context\n", G_STRFUNC); return NULL; } purple_cipher_context_set_option(ctx, "hash", "sha1"); purple_cipher_context_set_key(ctx, (guchar *) key); purple_cipher_context_append(ctx, (guchar *) txt, strlen(txt)); if (!purple_cipher_context_digest(ctx, 20, output, &output_size)) { purple_debug_error(GENERIC_PROTOCOL_ID, "%s: Could not sign text\n", G_STRFUNC); purple_cipher_context_destroy(ctx); return NULL; } purple_cipher_context_destroy(ctx); return purple_base64_encode(output, output_size); }
/*encode the message to OIM Message Format*/ static gchar * msn_oim_msg_to_str(MsnOim *oim, const char *body) { GString *oim_body; char *oim_base64; char *c; int len; size_t base64_len; purple_debug_info("msn", "Encoding OIM Message...\n"); len = strlen(body); c = oim_base64 = purple_base64_encode((const guchar *)body, len); base64_len = strlen(oim_base64); purple_debug_info("msn", "Encoded base64 body:{%s}\n", oim_base64); oim_body = g_string_new(NULL); g_string_printf(oim_body, MSN_OIM_MSG_TEMPLATE, oim->run_id, oim->send_seq); #define OIM_LINE_LEN 76 while (base64_len > OIM_LINE_LEN) { g_string_append_len(oim_body, c, OIM_LINE_LEN); g_string_append_c(oim_body, '\n'); c += OIM_LINE_LEN; base64_len -= OIM_LINE_LEN; } #undef OIM_LINE_LEN g_string_append(oim_body, c); g_free(oim_base64); return g_string_free(oim_body, FALSE); }
static gchar * gen_context(const char *file_name, const char *file_path) { struct stat st; gsize size = 0; MsnContextHeader header; gchar *u8 = NULL; guchar *base; guchar *n; gchar *ret; gunichar2 *uni = NULL; glong currentChar = 0; glong uni_len = 0; gsize len; if (g_stat(file_path, &st) == 0) size = st.st_size; if(!file_name) { u8 = purple_utf8_try_convert(g_basename(file_path)); file_name = u8; } uni = g_utf8_to_utf16(file_name, -1, NULL, &uni_len, NULL); if(u8) { g_free(u8); file_name = NULL; u8 = NULL; } len = sizeof(MsnContextHeader) + MAX_FILE_NAME_LEN + 4; header.length = GUINT32_TO_LE(len); header.unk1 = GUINT32_TO_LE(2); header.file_size = GUINT32_TO_LE(size); header.unk2 = GUINT32_TO_LE(0); header.unk3 = GUINT32_TO_LE(0); base = g_malloc(len + 1); n = base; memcpy(n, &header, sizeof(MsnContextHeader)); n += sizeof(MsnContextHeader); memset(n, 0x00, MAX_FILE_NAME_LEN); for(currentChar = 0; currentChar < uni_len; currentChar++) { *((gunichar2 *)n + currentChar) = GUINT16_TO_LE(uni[currentChar]); } n += MAX_FILE_NAME_LEN; memset(n, 0xFF, 4); n += 4; g_free(uni); ret = purple_base64_encode(base, len); g_free(base); return ret; }
void msn_slplink_request_object(MsnSlpLink *slplink, const char *info, MsnSlpCb cb, MsnSlpEndCb end_cb, const MsnObject *obj) { MsnSlpCall *slpcall; char *msnobj_data; char *msnobj_base64; g_return_if_fail(slplink != NULL); g_return_if_fail(obj != NULL); msnobj_data = msn_object_to_string(obj); msnobj_base64 = purple_base64_encode((const guchar *)msnobj_data, strlen(msnobj_data)); g_free(msnobj_data); slpcall = msn_slpcall_new(slplink); msn_slpcall_init(slpcall, MSN_SLPCALL_ANY); slpcall->data_info = g_strdup(info); slpcall->cb = cb; slpcall->end_cb = end_cb; msn_slpcall_invite(slpcall, MSN_OBJ_GUID, 1, msnobj_base64); g_free(msnobj_base64); }
/*encode the str to RFC2047 style * Currently only support the UTF-8 and base64 encode */ char * msn_encode_mime(const char *str) { gchar *base64, *retval; g_return_val_if_fail(str != NULL, NULL); base64 = purple_base64_encode((guchar *)str, strlen(str)); retval = g_strdup_printf("=?utf-8?B?%s?=", base64); g_free(base64); return retval; }
/** * @return A null-terminated base64 encoded version of the HMAC * calculated using the given key and data. */ static gchar *hmac_sha256(const char *key, const char *message) { PurpleCipherContext *context; guchar digest[32]; context = purple_cipher_context_new_by_name("hmac", NULL); purple_cipher_context_set_option(context, "hash", "sha256"); purple_cipher_context_set_key(context, (guchar *)key); purple_cipher_context_append(context, (guchar *)message, strlen(message)); purple_cipher_context_digest(context, sizeof(digest), digest, NULL); purple_cipher_context_destroy(context); return purple_base64_encode(digest, sizeof(digest)); }
void mrim_package_add_base64(MrimPackage *pack, gchar *fmt, ...) { gchar *buffer = NULL; gsize buffer_size = 0; va_list ap; va_start(ap, fmt); while (*fmt) { switch (*fmt) { case 'u': { guint32 value = va_arg(ap, guint32); buffer = g_realloc(buffer, buffer_size + sizeof(guint32)); g_memmove(buffer + buffer_size, &value, sizeof(guint32)); buffer_size += sizeof(guint32); } break; case 's': //CP1251 { gchar *string = va_arg(ap, gchar*); gsize str_len = g_utf8_strlen(string, -1); buffer = g_realloc(buffer, buffer_size + sizeof(guint32) + str_len); g_memmove(buffer + buffer_size, &str_len, sizeof(guint32)); gchar *str = g_convert_with_fallback(string, -1, "CP1251" , "UTF8", NULL, NULL, NULL, NULL); g_memmove(buffer + buffer_size + sizeof(guint32), str, str_len); g_free(str); buffer_size += sizeof(guint32) + str_len; } break; case 'w': //UTF16 { gchar *string = va_arg(ap, gchar*); gsize str_len = g_utf8_strlen(string, -1) * sizeof(gunichar2); buffer = g_realloc(buffer, buffer_size + sizeof(guint32) + str_len); g_memmove(buffer + buffer_size, &str_len, sizeof(guint32)); gunichar2 *str = g_utf8_to_utf16(string, -1, NULL, NULL, NULL); g_memmove(buffer + buffer_size + sizeof(guint32), str, str_len); g_free(str); buffer_size += sizeof(guint32) + str_len; } break; } fmt++; } va_end(ap); gchar *encoded = purple_base64_encode((gchar*)buffer, buffer_size); guint32 encoded_len = strlen(encoded); mrim_package_add_UL(pack, encoded_len); mrim_package_add_raw(pack, encoded, encoded_len); g_free(encoded); g_free(buffer); }
xmlnode * jabber_data_get_xml_definition(const JabberData *data) { xmlnode *tag = xmlnode_new("data"); char *base64data = purple_base64_encode(data->data, data->size); xmlnode_set_namespace(tag, NS_BOB); xmlnode_set_attrib(tag, "cid", data->cid); xmlnode_set_attrib(tag, "type", data->type); xmlnode_insert_data(tag, base64data, -1); g_free(base64data); return tag; }
void twitter_send_request(PurpleAccount *account, gboolean post, const char *url, const char *query_string, TwitterSendRequestSuccessFunc success_callback, TwitterSendRequestErrorFunc error_callback, gpointer data) { gchar *request; const char *pass = purple_connection_get_password(purple_account_get_connection(account)); const char *sn = purple_account_get_username(account); char *auth_text = g_strdup_printf("%s:%s", sn, pass); char *auth_text_b64 = purple_base64_encode((guchar *) auth_text, strlen(auth_text)); gboolean use_https = purple_account_get_bool(account, "use_https", FALSE) && purple_ssl_is_supported(); char *host = "twitter.com"; TwitterSendRequestData *request_data = g_new0(TwitterSendRequestData, 1); char *full_url = g_strdup_printf("%s://%s%s", use_https ? "https" : "http", host, url); request_data->account = account; request_data->user_data = data; request_data->success_func = success_callback; request_data->error_func = error_callback; g_free(auth_text); request = g_strdup_printf( "%s %s%s%s HTTP/1.0\r\n" "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\n" "Host: %s\r\n" "Authorization: Basic %s\r\n" "Content-Length: %d\r\n\r\n" "%s", post ? "POST" : "GET", full_url, (!post && query_string ? "?" : ""), (!post && query_string ? query_string : ""), host, auth_text_b64, query_string && post ? strlen(query_string) : 0, query_string && post ? query_string : ""); g_free(auth_text_b64); purple_util_fetch_url_request(full_url, TRUE, "Mozilla/4.0 (compatible; MSIE 5.5)", TRUE, request, FALSE, twitter_send_request_cb, request_data); g_free(full_url); g_free(request); }
void campfire_http_request(CampfireSslTransaction * xaction, gchar * uri, gchar * method, xmlnode * postxml) { CampfireConn *conn = xaction->campfire; const char *api_token = purple_account_get_string(conn->account, "api_token", ""); gchar *xmlstr = NULL, *len = NULL, *encoded = NULL; gsize auth_len; xaction->http_request = g_string_new(method); g_string_append(xaction->http_request, " "); g_string_append(xaction->http_request, uri); g_string_append(xaction->http_request, " HTTP/1.1\r\n"); g_string_append(xaction->http_request, "Content-Type: application/xml\r\n"); g_string_append(xaction->http_request, "Authorization: Basic "); auth_len = strlen(api_token); encoded = purple_base64_encode((const guchar *) api_token, auth_len); g_string_append(xaction->http_request, encoded); g_string_append(xaction->http_request, "\r\n"); g_free(encoded); g_string_append(xaction->http_request, "Host: "); g_string_append(xaction->http_request, conn->hostname); g_string_append(xaction->http_request, "\r\n"); g_string_append(xaction->http_request, "Accept: */*\r\n"); if (postxml) { xmlstr = xmlnode_to_str(postxml, NULL); g_string_append(xaction->http_request, "Content-Length: "); /* len = g_strdup_printf("%lu", strlen(xmlstr)); */ len = g_strdup_printf("%" G_GSIZE_FORMAT, strlen(xmlstr)); g_string_append(xaction->http_request, len); g_free(len); g_string_append(xaction->http_request, "\r\n\r\n"); g_string_append(xaction->http_request, xmlstr); g_string_append(xaction->http_request, "\r\n"); } g_string_append(xaction->http_request, "\r\n"); purple_debug_info("campfire", "Formatted request:\n%s\n", xaction->http_request->str); }
void jabber_ibb_session_send_data(JabberIBBSession *sess, gconstpointer data, gsize size) { JabberIBBSessionState state = jabber_ibb_session_get_state(sess); purple_debug_info("jabber", "sending data block of %" G_GSIZE_FORMAT " bytes on IBB stream\n", size); if (state != JABBER_IBB_SESSION_OPENED) { purple_debug_error("jabber", "trying to send data on a non-open IBB session\n"); } else if (size > jabber_ibb_session_get_max_data_size(sess)) { purple_debug_error("jabber", "trying to send a too large packet in the IBB session\n"); } else { JabberIq *set = jabber_iq_new(jabber_ibb_session_get_js(sess), JABBER_IQ_SET); PurpleXmlNode *data_element = purple_xmlnode_new("data"); char *base64 = purple_base64_encode(data, size); char seq[10]; g_snprintf(seq, sizeof(seq), "%u", jabber_ibb_session_get_send_seq(sess)); purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess)); purple_xmlnode_set_namespace(data_element, NS_IBB); purple_xmlnode_set_attrib(data_element, "sid", jabber_ibb_session_get_sid(sess)); purple_xmlnode_set_attrib(data_element, "seq", seq); purple_xmlnode_insert_data(data_element, base64, -1); purple_xmlnode_insert_child(set->node, data_element); purple_debug_info("jabber", "IBB: setting send <iq/> callback for session %p %s\n", sess, sess->sid); jabber_iq_set_callback(set, jabber_ibb_session_send_acknowledge_cb, sess); sess->last_iq_id = g_strdup(purple_xmlnode_get_attrib(set->node, "id")); purple_debug_info("jabber", "IBB: set sess->last_iq_id: %s\n", sess->last_iq_id); jabber_iq_send(set); g_free(base64); (sess->send_seq)++; } }
static void ggp_avatar_own_got_token(PurpleConnection *gc, const gchar *token, gpointer _img) { PurpleHttpRequest *req; PurpleImage *img = _img; ggp_avatar_own_data *own_data = ggp_avatar_get_avdata(gc)->own_data; gchar *img_data, *img_data_e, *request_data; PurpleAccount *account = purple_connection_get_account(gc); uin_t uin = ggp_str_to_uin(purple_account_get_username(account)); if (img != own_data->img) { purple_debug_warning("gg", "ggp_avatar_own_got_token: " "avatar was changed in meantime\n"); return; } own_data->img = NULL; img_data = purple_base64_encode(purple_image_get_data(img), purple_image_get_size(img)); img_data_e = g_uri_escape_string(img_data, NULL, FALSE); g_free(img_data); request_data = g_strdup_printf("uin=%d&photo=%s", uin, img_data_e); g_free(img_data_e); purple_debug_misc("gg", "ggp_avatar_own_got_token: " "uploading new avatar...\n"); req = purple_http_request_new("http://avatars.nowe.gg/upload"); purple_http_request_set_max_len(req, GGP_AVATAR_RESPONSE_MAX); purple_http_request_set_method(req, "POST"); purple_http_request_header_set(req, "Authorization", token); purple_http_request_header_set(req, "From", "avatars to avatars"); purple_http_request_header_set(req, "Content-Type", "application/x-www-form-urlencoded"); purple_http_request_set_contents(req, request_data, -1); purple_http_request(gc, req, ggp_avatar_own_sent, NULL); purple_http_request_unref(req); g_free(request_data); }
/*------------------------------------------------------------------------ * Insert an inline image command. * * @param mx The message text as processed so far. * @oaram id The imgstore ID of the inline image. */ static void inline_image_add( GString* mx, int id ) { PurpleStoredImage *image; gconstpointer img_data; gsize img_size; gchar* enc; image = purple_imgstore_find_by_id( id ); if ( image == NULL ) return; img_data = purple_imgstore_get_data( image ); img_size = purple_imgstore_get_size( image ); enc = purple_base64_encode( img_data, img_size ); g_string_append( mx, "::op=img|dat=" ); g_string_append( mx, enc ); g_string_append_c( mx, ':' ); g_free( enc ); }
/*------------------------------------------------------------------------ * Encrypt the user's cleartext password using the AES 128-bit (ECB) * encryption algorithm. * * @param session The MXit session object * @return The encrypted & encoded password. Must be g_free'd when no longer needed. */ char* mxit_encrypt_password( struct MXitSession* session ) { char key[16 + 1]; char exkey[512]; GString* pass = NULL; GString* encrypted = NULL; char* base64; unsigned int i; purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" ); /* build the AES encryption key */ g_strlcpy( key, INITIAL_KEY, sizeof( key ) ); memcpy( key, session->clientkey, strlen( session->clientkey ) ); ExpandKey( (unsigned char*) key, (unsigned char*) exkey ); /* build the secret data to be encrypted: SECRET_HEADER + password */ pass = g_string_new( SECRET_HEADER ); g_string_append( pass, purple_connection_get_password( session->con ) ); padding_add( pass ); /* add ISO10126 padding */ /* now encrypt the secret. we encrypt each block separately (ECB mode) */ encrypted = g_string_sized_new( pass->len ); for ( i = 0; i < pass->len; i += 16 ) { char block[16]; Encrypt( (unsigned char*) pass->str + i, (unsigned char*) exkey, (unsigned char*) block ); g_string_append_len( encrypted, block, 16 ); } /* now base64 encode the encrypted password */ base64 = purple_base64_encode( (unsigned char*) encrypted->str, encrypted->len ); g_string_free( encrypted, TRUE ); g_string_free( pass, TRUE ); return base64; }
/*------------------------------------------------------------------------ * Encrypt a message using transport-layer encryption. * * @param session The MXit session object * @param message The message data. * @return The encrypted message. Must be g_free'd when no longer needed. */ char* mxit_encrypt_message( struct MXitSession* session, char* message ) { GString* raw_message = NULL; char exkey[512]; GString* encoded = NULL; gchar* base64; unsigned int i; purple_debug_info( MXIT_PLUGIN_ID, "encrypt message: '%s'\n", message ); /* append encryption header to message data */ raw_message = g_string_new( SECRET_HEADER ); g_string_append( raw_message, message ); padding_add( raw_message ); /* add ISO10126 padding */ /* build the AES key */ ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey ); /* AES encrypt each block */ encoded = g_string_sized_new( raw_message->len ); for ( i = 0; i < raw_message->len; i += 16 ) { char block[16]; Encrypt( (unsigned char*) raw_message->str + i, (unsigned char*) exkey, (unsigned char*) block ); g_string_append_len( encoded, block, 16 ); } g_string_free( raw_message, TRUE ); /* base64 encode the encrypted message */ base64 = purple_base64_encode( (unsigned char *) encoded->str, encoded->len ); g_string_free( encoded, TRUE ); purple_debug_info( MXIT_PLUGIN_ID, "encrypted message: '%s'\n", base64 ); return base64; }
static gchar * gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path) { gsize size = 0; MsnFileContext *header; gchar *u8 = NULL; gchar *ret; gunichar2 *uni = NULL; glong currentChar = 0; glong len = 0; const char *preview; gsize preview_len; size = purple_xfer_get_size(xfer); purple_xfer_prepare_thumbnail(xfer, "png"); if (!file_name) { gchar *basename = g_path_get_basename(file_path); u8 = purple_utf8_try_convert(basename); g_free(basename); file_name = u8; } uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL); if (u8) { g_free(u8); file_name = NULL; u8 = NULL; } preview = purple_xfer_get_thumbnail(xfer, &preview_len); header = g_malloc(sizeof(MsnFileContext) + preview_len); header->length = GUINT32_TO_LE(sizeof(MsnFileContext) - 1); header->version = GUINT32_TO_LE(2); /* V.3 contains additional unnecessary data */ header->file_size = GUINT64_TO_LE(size); if (preview) header->type = GUINT32_TO_LE(0); else header->type = GUINT32_TO_LE(1); len = MIN(len, MAX_FILE_NAME_LEN); for (currentChar = 0; currentChar < len; currentChar++) { header->file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]); } memset(&header->file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2); memset(&header->unknown1, 0, sizeof(header->unknown1)); header->unknown2 = GUINT32_TO_LE(0xffffffff); if (preview) { memcpy(&header->preview, preview, preview_len); } header->preview[preview_len] = '\0'; g_free(uni); ret = purple_base64_encode((const guchar *)header, sizeof(MsnFileContext) + preview_len); g_free(header); return ret; }
static gchar * gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path) { goffset size = 0; MsnFileContext context; gchar *u8 = NULL; gchar *ret; gunichar2 *uni = NULL; glong currentChar = 0; glong len = 0; const char *preview; gsize preview_len; size = purple_xfer_get_size(xfer); purple_xfer_prepare_thumbnail(xfer, "png"); if (!file_name) { gchar *basename = g_path_get_basename(file_path); u8 = purple_utf8_try_convert(basename); g_free(basename); file_name = u8; } uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL); if (u8) { g_free(u8); file_name = NULL; u8 = NULL; } preview = purple_xfer_get_thumbnail(xfer, &preview_len); context.length = MSN_FILE_CONTEXT_SIZE_V2; context.version = 2; /* V.3 contains additional unnecessary data */ context.file_size = size; if (preview) context.type = 0; else context.type = 1; len = MIN(len, MAX_FILE_NAME_LEN); for (currentChar = 0; currentChar < len; currentChar++) { context.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]); } memset(&context.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2); #if 0 memset(&context.unknown1, 0, sizeof(context.unknown1)); context.unknown2 = 0xffffffff; #endif /* Mind the cast, as in, don't free it after! */ context.preview = (char *)preview; context.preview_len = preview_len; u8 = msn_file_context_to_wire(&context); ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE_V2 + preview_len); g_free(uni); g_free(u8); return ret; }
END_TEST START_TEST(test_util_base64_encode) { assert_string_equal_free("Zm9ydHktdHdvAA==", purple_base64_encode("forty-two", 10)); }
static JabberSaslState digest_md5_handle_challenge(JabberStream *js, PurpleXmlNode *packet, PurpleXmlNode **response, char **msg) { PurpleXmlNode *reply = NULL; char *enc_in = purple_xmlnode_get_data(packet); char *dec_in; char *enc_out; GHashTable *parts; JabberSaslState state = JABBER_SASL_STATE_CONTINUE; if (!enc_in) { *msg = g_strdup(_("Invalid response from server")); return JABBER_SASL_STATE_FAIL; } dec_in = (char *)purple_base64_decode(enc_in, NULL); purple_debug_misc("jabber", "decoded challenge (%" G_GSIZE_FORMAT "): %s\n", strlen(dec_in), dec_in); parts = jabber_auth_digest_md5_parse(dec_in); if (g_hash_table_lookup(parts, "rspauth")) { char *rspauth = g_hash_table_lookup(parts, "rspauth"); char *expected_rspauth = js->auth_mech_data; if (rspauth && purple_strequal(rspauth, expected_rspauth)) { reply = purple_xmlnode_new("response"); purple_xmlnode_set_namespace(reply, NS_XMPP_SASL); } else { *msg = g_strdup(_("Invalid challenge from server")); state = JABBER_SASL_STATE_FAIL; } g_free(js->auth_mech_data); js->auth_mech_data = NULL; } else { /* assemble a response, and send it */ /* see RFC 2831 */ char *realm; char *nonce; /* Make sure the auth string contains everything that should be there. This isn't everything in RFC2831, but it is what we need. */ nonce = g_hash_table_lookup(parts, "nonce"); /* we're actually supposed to prompt the user for a realm if * the server doesn't send one, but that really complicates things, * so i'm not gonna worry about it until is poses a problem to * someone, or I get really bored */ realm = g_hash_table_lookup(parts, "realm"); if(!realm) realm = js->user->domain; if (nonce == NULL || realm == NULL) { *msg = g_strdup(_("Invalid challenge from server")); state = JABBER_SASL_STATE_FAIL; } else { GString *response = g_string_new(""); char *a2; char *auth_resp; char *cnonce; cnonce = g_strdup_printf("%x%u%x", g_random_int(), (int)time(NULL), g_random_int()); a2 = g_strdup_printf("AUTHENTICATE:xmpp/%s", realm); auth_resp = generate_response_value(js->user, purple_connection_get_password(js->gc), nonce, cnonce, a2, realm); g_free(a2); a2 = g_strdup_printf(":xmpp/%s", realm); js->auth_mech_data = generate_response_value(js->user, purple_connection_get_password(js->gc), nonce, cnonce, a2, realm); g_free(a2); g_string_append_printf(response, "username=\"%s\"", js->user->node); g_string_append_printf(response, ",realm=\"%s\"", realm); g_string_append_printf(response, ",nonce=\"%s\"", nonce); g_string_append_printf(response, ",cnonce=\"%s\"", cnonce); g_string_append_printf(response, ",nc=00000001"); g_string_append_printf(response, ",qop=auth"); g_string_append_printf(response, ",digest-uri=\"xmpp/%s\"", realm); g_string_append_printf(response, ",response=%s", auth_resp); g_string_append_printf(response, ",charset=utf-8"); g_free(auth_resp); g_free(cnonce); enc_out = purple_base64_encode((guchar *)response->str, response->len); purple_debug_misc("jabber", "decoded response (%" G_GSIZE_FORMAT "): %s\n", response->len, response->str); reply = purple_xmlnode_new("response"); purple_xmlnode_set_namespace(reply, NS_XMPP_SASL); purple_xmlnode_insert_data(reply, enc_out, -1); g_free(enc_out); g_string_free(response, TRUE); } } g_free(enc_in); g_free(dec_in); g_hash_table_destroy(parts); *response = reply; return state; }
void msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data) { MsnSession *session = nexus->session; MsnNexusUpdateData *ud; MsnNexusUpdateCallback *update; PurpleCipherContext *sha1; PurpleCipherContext *hmac; char *key; guchar digest[20]; struct tm *tm; time_t now; char *now_str; char *timestamp; char *timestamp_b64; char *domain; char *domain_b64; char *signedinfo; gint32 nonce[6]; int i; char *nonce_b64; char *signature_b64; guchar signature[20]; char *request; MsnSoapMessage *soap; update = g_new0(MsnNexusUpdateCallback, 1); update->cb = cb; update->data = data; if (nexus->tokens[id].updates != NULL) { /* Update already in progress. Just add to list and return. */ purple_debug_info("msn", "Ticket update for user '%s' on domain '%s' in progress. Adding request to queue.\n", purple_account_get_username(session->account), ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates, update); return; } else { purple_debug_info("msn", "Updating ticket for user '%s' on domain '%s'\n", purple_account_get_username(session->account), ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates, update); } ud = g_new0(MsnNexusUpdateData, 1); ud->nexus = nexus; ud->id = id; sha1 = purple_cipher_context_new_by_name("sha1", NULL); domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE, id, ticket_domains[id][SSO_VALID_TICKET_DOMAIN], ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ? ticket_domains[id][SSO_VALID_TICKET_POLICY] : nexus->policy); purple_cipher_context_append(sha1, (guchar *)domain, strlen(domain)); purple_cipher_context_digest(sha1, 20, digest, NULL); domain_b64 = purple_base64_encode(digest, 20); now = time(NULL); tm = gmtime(&now); now_str = g_strdup(purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm)); now += 5*60; tm = gmtime(&now); timestamp = g_strdup_printf(MSN_SSO_TIMESTAMP_TEMPLATE, now_str, purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm)); purple_cipher_context_reset(sha1, NULL); purple_cipher_context_append(sha1, (guchar *)timestamp, strlen(timestamp)); purple_cipher_context_digest(sha1, 20, digest, NULL); timestamp_b64 = purple_base64_encode(digest, 20); g_free(now_str); purple_cipher_context_destroy(sha1); signedinfo = g_strdup_printf(MSN_SSO_SIGNEDINFO_TEMPLATE, id, domain_b64, timestamp_b64); for (i = 0; i < 6; i++) nonce[i] = rand(); nonce_b64 = purple_base64_encode((guchar *)&nonce, sizeof(nonce)); key = rps_create_key(nexus->secret, 24, (char *)nonce, sizeof(nonce)); hmac = purple_cipher_context_new_by_name("hmac", NULL); purple_cipher_context_set_option(hmac, "hash", "sha1"); purple_cipher_context_set_key_with_len(hmac, (guchar *)key, 24); purple_cipher_context_append(hmac, (guchar *)signedinfo, strlen(signedinfo)); purple_cipher_context_digest(hmac, 20, signature, NULL); purple_cipher_context_destroy(hmac); signature_b64 = purple_base64_encode(signature, 20); request = g_strdup_printf(MSN_SSO_TOKEN_UPDATE_TEMPLATE, nexus->cipher, nonce_b64, timestamp, signedinfo, signature_b64, domain); g_free(nonce_b64); g_free(domain_b64); g_free(timestamp_b64); g_free(timestamp); g_free(key); g_free(signature_b64); g_free(signedinfo); g_free(domain); soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1)); g_free(request); msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE, nexus_got_update_cb, ud); }
static char * msn_rps_encrypt(MsnNexus *nexus) { char usr_key_base[MSN_USER_KEY_SIZE], *usr_key; const char magic1[] = "SESSION KEY HASH"; const char magic2[] = "SESSION KEY ENCRYPTION"; PurpleCipherContext *hmac; size_t len; guchar *hash; char *key1, *key2, *key3; gsize key1_len; const char *iv; char *nonce_fixed; char *cipher; char *response; usr_key = &usr_key_base[0]; /* Header */ msn_push32le(usr_key, 28); /* Header size */ msn_push32le(usr_key, CRYPT_MODE_CBC); /* Crypt mode */ msn_push32le(usr_key, CIPHER_TRIPLE_DES); /* Cipher type */ msn_push32le(usr_key, HASH_SHA1); /* Hash type */ msn_push32le(usr_key, 8); /* IV size */ msn_push32le(usr_key, 20); /* Hash size */ msn_push32le(usr_key, 72); /* Cipher size */ /* Data */ iv = usr_key; msn_push32le(usr_key, rand()); msn_push32le(usr_key, rand()); hash = (guchar *)usr_key; usr_key += 20; /* Remaining is cipher data */ key1 = (char *)purple_base64_decode((const char *)nexus->tokens[MSN_AUTH_MESSENGER].secret, &key1_len); key2 = rps_create_key(key1, key1_len, magic1, sizeof(magic1) - 1); key3 = rps_create_key(key1, key1_len, magic2, sizeof(magic2) - 1); len = strlen(nexus->nonce); hmac = purple_cipher_context_new_by_name("hmac", NULL); purple_cipher_context_set_option(hmac, "hash", "sha1"); purple_cipher_context_set_key_with_len(hmac, (guchar *)key2, 24); purple_cipher_context_append(hmac, (guchar *)nexus->nonce, len); purple_cipher_context_digest(hmac, 20, hash, NULL); purple_cipher_context_destroy(hmac); /* We need to pad this to 72 bytes, apparently */ nonce_fixed = g_malloc(len + 8); memcpy(nonce_fixed, nexus->nonce, len); memset(nonce_fixed + len, 0x08, 8); cipher = des3_cbc(key3, iv, nonce_fixed, len + 8, FALSE); g_free(nonce_fixed); memcpy(usr_key, cipher, 72); g_free(key1); g_free(key2); g_free(key3); g_free(cipher); response = purple_base64_encode((guchar *)usr_key_base, MSN_USER_KEY_SIZE); return response; }
MsnObject * msn_object_new_from_image (PecanBuffer *image, const char *location, const char *creator, MsnObjectType type) { MsnObject *msnobj; PurpleCipherContext *ctx; char *buf; char *base64; unsigned char digest[20]; msnobj = NULL; if (!image) return msnobj; /* New object */ msnobj = msn_object_new (); msn_object_set_local (msnobj); msn_object_set_type (msnobj, type); msn_object_set_location (msnobj, location); msn_object_set_creator (msnobj, creator); msn_object_set_image (msnobj, image); /* Compute the SHA1D field. */ memset (digest, 0, sizeof (digest)); ctx = purple_cipher_context_new_by_name ("sha1", NULL); purple_cipher_context_append (ctx, (const gpointer) image->data, image->len); purple_cipher_context_digest (ctx, sizeof (digest), digest, NULL); base64 = purple_base64_encode (digest, sizeof (digest)); msn_object_set_sha1d (msnobj, base64); g_free (base64); msn_object_set_size (msnobj, image->len); /* Compute the SHA1C field. */ buf = g_strdup_printf ("Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s", msn_object_get_creator (msnobj), msn_object_get_size (msnobj), msn_object_get_type (msnobj), msn_object_get_location (msnobj), msn_object_get_friendly (msnobj), msn_object_get_sha1d (msnobj)); memset (digest, 0, sizeof (digest)); purple_cipher_context_reset (ctx, NULL); purple_cipher_context_append (ctx, (const guchar *) buf, strlen (buf)); purple_cipher_context_digest (ctx, sizeof (digest), digest, NULL); purple_cipher_context_destroy (ctx); g_free (buf); base64 = purple_base64_encode (digest, sizeof (digest)); msn_object_set_sha1c (msnobj, base64); g_free (base64); return msnobj; }
void gfire_chat_proto_invite(gfire_data *p_gfire, guint16 p_packet_len) { if(!p_gfire) return; guint32 offset = XFIRE_HEADER_LEN; guint8 *chat_id = NULL; guint32 unknown = 0; guint32 userid = 0; gchar *name = NULL; gchar *nick = NULL; gchar *room = NULL; GHashTable *components = NULL; offset = gfire_proto_read_attr_chatid_bs(p_gfire->buff_in, &chat_id, 0x04, offset); if(offset == -1 || !chat_id) return; offset = gfire_proto_read_attr_int32_bs(p_gfire->buff_in, &unknown, 0xAA, offset); if(offset == -1) { g_free(chat_id); return; } offset = gfire_proto_read_attr_int32_bs(p_gfire->buff_in, &userid, 0x01, offset); if(offset == -1) { g_free(chat_id); return; } offset = gfire_proto_read_attr_string_bs(p_gfire->buff_in, &name, 0x02, offset); if(offset == -1 || !name) { g_free(chat_id); return; } offset = gfire_proto_read_attr_string_bs(p_gfire->buff_in, &nick, 0x0D, offset); if(offset == -1 || !nick) { g_free(chat_id); g_free(name); return; } offset = gfire_proto_read_attr_string_bs(p_gfire->buff_in, &room, 0x05, offset); if(offset == -1 || !room) { g_free(chat_id); g_free(name); g_free(nick); return; } if(strlen(nick) == 0) { g_free(nick); nick = g_strdup(name); } purple_debug(PURPLE_DEBUG_MISC, "gfire", "(chat invite): %s with alias %s invited us to room '%s'\n", NN(name), NN(nick), NN(room)); // assemble ghashtable components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_replace(components, g_strdup("room"), room); g_hash_table_replace(components, g_strdup("chat_id"), purple_base64_encode(chat_id, XFIRE_CHATID_LEN)); g_free(chat_id); serv_got_chat_invite(gfire_get_connection(p_gfire), room, nick, "", components); }
static JabberSaslState jabber_auth_start_cyrus(JabberStream *js, xmlnode **reply, char **error) { PurpleAccount *account; const char *clientout = NULL; char *enc_out; unsigned coutlen = 0; sasl_security_properties_t secprops; gboolean again; gboolean plaintext = TRUE; /* Set up security properties and options */ secprops.min_ssf = 0; secprops.security_flags = SASL_SEC_NOANONYMOUS; account = purple_connection_get_account(js->gc); if (!jabber_stream_is_ssl(js)) { secprops.max_ssf = -1; secprops.maxbufsize = 4096; plaintext = purple_account_get_bool(account, "auth_plain_in_clear", FALSE); if (!plaintext) secprops.security_flags |= SASL_SEC_NOPLAINTEXT; } else { secprops.max_ssf = 0; secprops.maxbufsize = 0; plaintext = TRUE; } secprops.property_names = 0; secprops.property_values = 0; do { again = FALSE; js->sasl_state = sasl_client_new("xmpp", js->serverFQDN, NULL, NULL, js->sasl_cb, 0, &js->sasl); if (js->sasl_state==SASL_OK) { sasl_setprop(js->sasl, SASL_SEC_PROPS, &secprops); purple_debug_info("sasl", "Mechs found: %s\n", js->sasl_mechs->str); js->sasl_state = sasl_client_start(js->sasl, js->sasl_mechs->str, NULL, &clientout, &coutlen, &js->current_mech); } switch (js->sasl_state) { /* Success */ case SASL_OK: case SASL_CONTINUE: break; case SASL_NOMECH: /* No mechanisms have offered to help */ /* Firstly, if we don't have a password try * to get one */ if (!purple_account_get_password(account)) { purple_account_request_password(account, G_CALLBACK(auth_pass_cb), G_CALLBACK(auth_no_pass_cb), js->gc); return JABBER_SASL_STATE_CONTINUE; /* If we've got a password, but aren't sending * it in plaintext, see if we can turn on * plaintext auth */ /* XXX Should we just check for PLAIN/LOGIN being offered mechanisms? */ } else if (!plaintext) { char *msg = g_strdup_printf(_("%s may require plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), purple_account_get_username(account)); purple_request_yes_no(js->gc, _("Plaintext Authentication"), _("Plaintext Authentication"), msg, 1, account, NULL, NULL, account, allow_cyrus_plaintext_auth, disallow_plaintext_auth); g_free(msg); return JABBER_SASL_STATE_CONTINUE; } else js->auth_fail_count++; if (js->auth_fail_count == 1 && (js->sasl_mechs->str && g_str_equal(js->sasl_mechs->str, "GSSAPI"))) { /* If we tried GSSAPI first, it failed, and it was the only method we had to try, try jabber:iq:auth * for compatibility with iChat 10.5 Server and other jabberd based servers. * * iChat Server 10.5 and certain other corporate servers offer SASL GSSAPI by default, which is often * not configured on the client side, and expects a fallback to jabber:iq:auth when it (predictably) fails. * * Note: xep-0078 points out that using jabber:iq:auth after a sasl failure is wrong. However, * I believe this refers to actual authentication failure, not a simple lack of concordant mechanisms. * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers * which would connect without issue otherwise. -evands */ js->auth_mech = NULL; jabber_auth_start_old(js); return JABBER_SASL_STATE_CONTINUE; } break; /* Fatal errors. Give up and go home */ case SASL_BADPARAM: case SASL_NOMEM: *error = g_strdup(_("SASL authentication failed")); break; /* For everything else, fail the mechanism and try again */ default: purple_debug_info("sasl", "sasl_state is %d, failing the mech and trying again\n", js->sasl_state); js->auth_fail_count++; /* * DAA: is this right? * The manpage says that "mech" will contain the chosen mechanism on success. * Presumably, if we get here that isn't the case and we shouldn't try again? * I suspect that this never happens. */ /* * SXW: Yes, this is right. What this handles is the situation where a * mechanism, say GSSAPI, is tried. If that mechanism fails, it may be * due to mechanism specific issues, so we want to try one of the other * supported mechanisms. This code handles that case */ if (js->current_mech && *js->current_mech) { char *pos; if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) { g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str, strlen(js->current_mech)); } /* Remove space which separated this mech from the next */ if ((js->sasl_mechs->str)[0] == ' ') { g_string_erase(js->sasl_mechs, 0, 1); } again = TRUE; } sasl_dispose(&js->sasl); } } while (again); if (js->sasl_state == SASL_CONTINUE || js->sasl_state == SASL_OK) { xmlnode *auth = xmlnode_new("auth"); xmlnode_set_namespace(auth, NS_XMPP_SASL); xmlnode_set_attrib(auth, "mechanism", js->current_mech); xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth"); xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true"); if (clientout) { if (coutlen == 0) { xmlnode_insert_data(auth, "=", -1); } else { enc_out = purple_base64_encode((unsigned char*)clientout, coutlen); xmlnode_insert_data(auth, enc_out, -1); g_free(enc_out); } } *reply = auth; return JABBER_SASL_STATE_CONTINUE; } else { return JABBER_SASL_STATE_FAIL; } }
void om_post_or_get(OmegleAccount *oma, OmegleMethod method, const gchar *host, const gchar *url, const gchar *postdata, OmegleProxyCallbackFunc callback_func, gpointer user_data, gboolean keepalive) { GString *request; gchar *cookies; OmegleConnection *omconn; gchar *real_url; gboolean is_proxy = FALSE; const gchar *user_agent; const gchar* const *languages; gchar *language_names; PurpleProxyInfo *proxy_info = NULL; gchar *proxy_auth; gchar *proxy_auth_base64; /* TODO: Fix keepalive and use it as much as possible */ keepalive = FALSE; if (host == NULL) host = purple_account_get_string(oma->account, "host", "bajor.omegle.com"); if (oma && oma->account && !(method & OM_METHOD_SSL)) { proxy_info = purple_proxy_get_setup(oma->account); if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL) proxy_info = purple_global_proxy_get_info(); if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_HTTP) { is_proxy = TRUE; } } if (is_proxy == TRUE) { real_url = g_strdup_printf("http://%s%s", host, url); } else { real_url = g_strdup(url); } cookies = om_cookies_to_string(oma); user_agent = purple_account_get_string(oma->account, "user-agent", "Opera/9.50 (Windows NT 5.1; U; en-GB)"); if (method & OM_METHOD_POST && !postdata) postdata = ""; /* Build the request */ request = g_string_new(NULL); g_string_append_printf(request, "%s %s HTTP/1.0\r\n", (method & OM_METHOD_POST) ? "POST" : "GET", real_url); if (is_proxy == FALSE) g_string_append_printf(request, "Host: %s\r\n", host); g_string_append_printf(request, "Connection: %s\r\n", (keepalive ? "Keep-Alive" : "close")); g_string_append_printf(request, "User-Agent: %s\r\n", user_agent); if (method & OM_METHOD_POST) { g_string_append_printf(request, "Content-Type: application/x-www-form-urlencoded\r\n"); g_string_append_printf(request, "Content-length: %zu\r\n", strlen(postdata)); } g_string_append_printf(request, "Accept: application/json, text/html, */*\r\n"); g_string_append_printf(request, "Cookie: %s\r\n", cookies); g_string_append_printf(request, "Accept-Encoding: gzip\r\n"); if (is_proxy == TRUE) { if (purple_proxy_info_get_username(proxy_info) && purple_proxy_info_get_password(proxy_info)) { proxy_auth = g_strdup_printf("%s:%s", purple_proxy_info_get_username(proxy_info), purple_proxy_info_get_password(proxy_info)); proxy_auth_base64 = purple_base64_encode((guchar *)proxy_auth, strlen(proxy_auth)); g_string_append_printf(request, "Proxy-Authorization: Basic %s\r\n", proxy_auth_base64); g_free(proxy_auth_base64); g_free(proxy_auth); } } /* Tell the server what language we accept, so that we get error messages in our language (rather than our IP's) */ languages = g_get_language_names(); language_names = g_strjoinv(", ", (gchar **)languages); purple_util_chrreplace(language_names, '_', '-'); g_string_append_printf(request, "Accept-Language: %s\r\n", language_names); g_free(language_names); purple_debug_info("omegle", "getting url %s\n", url); g_string_append_printf(request, "\r\n"); if (method & OM_METHOD_POST) g_string_append_printf(request, "%s", postdata); /* If it needs to go over a SSL connection, we probably shouldn't print * it in the debug log. Without this condition a user's password is * printed in the debug log */ if (method == OM_METHOD_POST) purple_debug_info("omegle", "sending request data:\n%s\n", postdata); g_free(cookies); /* * Do a separate DNS lookup for the given host name and cache it * for next time. * * TODO: It would be better if we did this before we call * purple_proxy_connect(), so we could re-use the result. * Or even better: Use persistent HTTP connections for servers * that we access continually. * * TODO: This cache of the hostname<-->IP address does not respect * the TTL returned by the DNS server. We should expire things * from the cache after some amount of time. */ if (!is_proxy) { /* Don't do this for proxy connections, since proxies do the DNS lookup */ gchar *host_ip; host_ip = g_hash_table_lookup(oma->hostname_ip_cache, host); if (host_ip != NULL) { host = host_ip; } else if (oma->account && !oma->account->disconnecting) { GSList *host_lookup_list = NULL; PurpleDnsQueryData *query; host_lookup_list = g_slist_prepend( host_lookup_list, g_strdup(host)); host_lookup_list = g_slist_prepend( host_lookup_list, oma); query = purple_dnsquery_a(host, 80, om_host_lookup_cb, host_lookup_list); oma->dns_queries = g_slist_prepend(oma->dns_queries, query); host_lookup_list = g_slist_append(host_lookup_list, query); } } omconn = g_new0(OmegleConnection, 1); omconn->oma = oma; omconn->url = real_url; omconn->method = method; omconn->hostname = g_strdup(host); omconn->request = request; omconn->callback = callback_func; omconn->user_data = user_data; omconn->fd = -1; omconn->connection_keepalive = keepalive; omconn->request_time = time(NULL); oma->conns = g_slist_prepend(oma->conns, omconn); om_attempt_connection(omconn); }
SevenCupConnection * sevencup_post_or_get(SevenCupAccount *sa, SteamMethod method, const gchar *host, const gchar *url, const gchar *postdata, SteamProxyCallbackFunc callback_func, gpointer user_data, gboolean keepalive) { GString *request; gchar *cookies; SevenCupConnection *scon; gchar *real_url; gboolean is_proxy = FALSE; const gchar *user_agent; const gchar* const *languages; gchar *language_names; PurpleProxyInfo *proxy_info = NULL; gchar *proxy_auth; gchar *proxy_auth_base64; if (host == NULL) host = "www.7cupsoftea.com"; if (sa && sa->account) { if (purple_account_get_bool(sa->account, "use-https", TRUE)) method |= STEAM_METHOD_SSL; } if (sa && sa->account && !(method & STEAM_METHOD_SSL)) { proxy_info = purple_proxy_get_setup(sa->account); if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL) proxy_info = purple_global_proxy_get_info(); if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_HTTP) { is_proxy = TRUE; } } if (is_proxy == TRUE) { real_url = g_strdup_printf("http://%s%s", host, url); } else { real_url = g_strdup(url); } cookies = sevencup_cookies_to_string(sa); user_agent = purple_account_get_string(sa->account, "user-agent", "Steam 1.2.0 / iPhone"); if (method & STEAM_METHOD_POST && !postdata) postdata = ""; /* Build the request */ request = g_string_new(NULL); g_string_append_printf(request, "%s %s HTTP/1.1\r\n", (method & STEAM_METHOD_POST) ? "POST" : "GET", real_url); if (is_proxy == FALSE) g_string_append_printf(request, "Host: %s\r\n", host); g_string_append_printf(request, "Connection: %s\r\n", (keepalive ? "Keep-Alive" : "close")); g_string_append_printf(request, "User-Agent: %s\r\n", user_agent); if (method & STEAM_METHOD_POST) { g_string_append_printf(request, "Content-Type: application/x-www-form-urlencoded\r\n"); g_string_append_printf(request, "Content-length: %zu\r\n", strlen(postdata)); } g_string_append_printf(request, "Accept: */*\r\n"); g_string_append_printf(request, "Cookie: %s\r\n", cookies); g_string_append_printf(request, "Accept-Encoding: gzip\r\n"); if (is_proxy == TRUE) { if (purple_proxy_info_get_username(proxy_info) && purple_proxy_info_get_password(proxy_info)) { proxy_auth = g_strdup_printf("%s:%s", purple_proxy_info_get_username(proxy_info), purple_proxy_info_get_password(proxy_info)); proxy_auth_base64 = purple_base64_encode((guchar *)proxy_auth, strlen(proxy_auth)); g_string_append_printf(request, "Proxy-Authorization: Basic %s\r\n", proxy_auth_base64); g_free(proxy_auth_base64); g_free(proxy_auth); } } /* Tell the server what language we accept, so that we get error messages in our language (rather than our IP's) */ languages = g_get_language_names(); language_names = g_strjoinv(", ", (gchar **)languages); purple_util_chrreplace(language_names, '_', '-'); g_string_append_printf(request, "Accept-Language: %s\r\n", language_names); g_free(language_names); purple_debug_info("7cups", "getting url %s\n", url); g_string_append_printf(request, "\r\n"); if (method & STEAM_METHOD_POST) g_string_append_printf(request, "%s", postdata); /* If it needs to go over a SSL connection, we probably shouldn't print * it in the debug log. Without this condition a user's password is * printed in the debug log */ if (method == STEAM_METHOD_POST) purple_debug_info("7cups", "sending request data:\n%s\n", postdata); g_free(cookies); scon = g_new0(SevenCupConnection, 1); scon->sa = sa; scon->url = real_url; scon->method = method; scon->hostname = g_strdup(host); scon->request = request; scon->callback = callback_func; scon->user_data = user_data; scon->fd = -1; scon->connection_keepalive = keepalive; scon->request_time = time(NULL); g_queue_push_head(sa->waiting_conns, scon); sevencup_next_connection(sa); return scon; }