# HG changeset patch # User Daniel Atallah # Date 1218077301 0 # Node ID af603a54ae5a2a762714564869a97ea6dfda3d88 # Parent b0812ce0ec17c5107e7500fd62f1de0f3ceb3692 Some Perl bindings fixes and additions from Zsombor Welker. Technically some of these change the API, but in those couple cases, the way it is now is either broken, not usable or pretty unlikely to be used. Feel free to yell at me and/or revert this if you think this is unacceptable. Fixes #5912 diff -r b0812ce0ec17 -r af603a54ae5a libpurple/plugins/perl/common/Cipher.xs --- a/libpurple/plugins/perl/common/Cipher.xs Thu Aug 07 01:46:36 2008 +0000 +++ b/libpurple/plugins/perl/common/Cipher.xs Thu Aug 07 02:48:21 2008 +0000 @@ -3,6 +3,49 @@ MODULE = Purple::Cipher PACKAGE = Purple::Cipher PREFIX = purple_cipher_ PROTOTYPES: ENABLE +BOOT: +{ + HV *stash = gv_stashpv("Purple::Cipher::BatchMode", 1); + HV *cipher_caps = gv_stashpv("Purple::Cipher::Caps", 1); + + static const constiv *civ, const_iv[] = { +#define const_iv(name) {#name, (IV)PURPLE_CIPHER_BATCH_MODE_##name} + const_iv(ECB), + const_iv(CBC), +#undef const_iv + }; + + static const constiv bm_const_iv[] = { +#define const_iv(name) {#name, (IV)PURPLE_CIPHER_CAPS_##name} + const_iv(SET_OPT), + const_iv(GET_OPT), + const_iv(INIT), + const_iv(RESET), + const_iv(UNINIT), + const_iv(SET_IV), + const_iv(APPEND), + const_iv(DIGEST), + const_iv(ENCRYPT), + const_iv(DECRYPT), + const_iv(SET_SALT), + const_iv(GET_SALT_SIZE), + const_iv(SET_KEY), + const_iv(GET_KEY_SIZE), + const_iv(SET_BATCH_MODE), + const_iv(GET_BATCH_MODE), + const_iv(GET_BLOCK_SIZE), + const_iv(SET_KEY_WITH_LEN), + const_iv(UNKNOWN), +#undef const_iv + }; + + for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; ) + newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv)); + + for (civ = bm_const_iv + sizeof(bm_const_iv) / sizeof(bm_const_iv[0]); civ-- > bm_const_iv; ) + newCONSTSUB(cipher_caps, (char *)civ->name, newSViv(civ->iv)); +} + const gchar * purple_cipher_get_name(cipher) Purple::Cipher cipher @@ -11,14 +54,51 @@ purple_cipher_get_capabilities(cipher) Purple::Cipher cipher -gboolean -purple_cipher_digest_region(name, data, data_len, in_len, digest, out_len) - const gchar * name - const guchar * data - size_t data_len +size_t +purple_cipher_digest_region(name, data_sv, in_len, digest) + const gchar *name + SV *data_sv size_t in_len - guchar &digest - size_t * out_len + SV *digest + PREINIT: + gboolean ret; + guchar *buff = NULL; + guchar *data = NULL; + size_t data_len; + CODE: + data = SvPV(data_sv, data_len); + SvUPGRADE(digest, SVt_PV); + buff = SvGROW(digest, in_len); + ret = purple_cipher_digest_region(name, data, data_len, in_len, buff, &RETVAL); + if(!ret) { + SvSetSV_nosteal(digest, &PL_sv_undef); + XSRETURN_UNDEF; + } + SvCUR_set(digest, RETVAL); + SvPOK_only(digest); + OUTPUT: + RETVAL + +gchar_own* +purple_cipher_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key) + const gchar* algorithm + const gchar* method + const gchar* digest_uri + const gchar* qop + const gchar* entity + const gchar* nonce + const gchar* nonce_count + const gchar* client_nonce + const gchar* session_key + +gchar_own* +purple_cipher_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce) + const gchar* algorithm + const gchar* username + const gchar* realm + const gchar* password + const gchar* nonce + const gchar* client_nonce MODULE = Purple::Cipher PACKAGE = Purple::Ciphers PREFIX = purple_ciphers_ PROTOTYPES: ENABLE @@ -69,17 +149,19 @@ gchar *name Purple::Cipher::Context -purple_cipher_context_new(cipher, extra) +purple_cipher_context_new(klass, cipher, extra = NULL) Purple::Cipher cipher void *extra + C_ARGS: cipher, extra Purple::Cipher::Context -purple_cipher_context_new_by_name(name, extra) +purple_cipher_context_new_by_name(klass, name, extra = NULL) gchar *name void *extra + C_ARGS: name, extra void -purple_cipher_context_reset(context, extra) +purple_cipher_context_reset(context, extra = NULL) Purple::Cipher::Context context gpointer extra @@ -88,46 +170,103 @@ Purple::Cipher::Context context void -purple_cipher_context_set_iv(context, iv, len) - Purple::Cipher::Context context - guchar * iv - size_t len +purple_cipher_context_set_iv(Purple::Cipher::Context context, guchar *iv, size_t length(iv)) + PROTOTYPE: $$ void -purple_cipher_context_append(context, data, len) +purple_cipher_context_append(Purple::Cipher::Context context, guchar *data, size_t length(data)) + PROTOTYPE: $$ + +size_t +purple_cipher_context_digest(context, in_len, digest) Purple::Cipher::Context context - guchar * data - size_t len + size_t in_len + SV *digest + PREINIT: + gboolean ret; + guchar *buff = NULL; + CODE: + SvUPGRADE(digest, SVt_PV); + buff = SvGROW(digest, in_len); + ret = purple_cipher_context_digest(context, in_len, buff, &RETVAL); + if(!ret) { + SvSetSV_nosteal(digest, &PL_sv_undef); + XSRETURN_UNDEF; + } + SvCUR_set(digest, RETVAL); + SvPOK_only(digest); + OUTPUT: + RETVAL -gboolean -purple_cipher_context_digest(context, in_len, digest, out_len) +size_t +purple_cipher_context_digest_to_str(context, in_len, digest_s) Purple::Cipher::Context context size_t in_len - guchar &digest - size_t &out_len - -gboolean -purple_cipher_context_digest_to_str(context, in_len, digest_s, out_len) - Purple::Cipher::Context context - size_t in_len - gchar &digest_s - size_t &out_len + SV *digest_s + PREINIT: + gboolean ret; + gchar *buff = NULL; + CODE: + in_len += 1; /* perl shouldn't need to care about '\0' at the end */ + SvUPGRADE(digest_s, SVt_PV); + buff = SvGROW(digest_s, in_len); + ret = purple_cipher_context_digest_to_str(context, in_len, buff, &RETVAL); + if(!ret) { + SvSetSV_nosteal(digest_s, &PL_sv_undef); + XSRETURN_UNDEF; + } + SvCUR_set(digest_s, RETVAL); + SvPOK_only(digest_s); + OUTPUT: + RETVAL gint -purple_cipher_context_encrypt(context, data, len, output, outlen) +purple_cipher_context_encrypt(context, data_sv, output, OUTLIST size_t outlen) Purple::Cipher::Context context - guchar &data - size_t len - guchar &output - size_t &outlen + SV *data_sv + SV *output + PROTOTYPE: $$$ + PREINIT: + size_t datalen; + guchar *buff = NULL; + guchar *data = NULL; + CODE: + data = SvPV(data_sv, datalen); + SvUPGRADE(output, SVt_PV); + buff = SvGROW(output, datalen); + RETVAL = purple_cipher_context_encrypt(context, data, datalen, buff, &outlen); + if(outlen != 0) { + SvPOK_only(output); + SvCUR_set(output, outlen); + } else { + SvSetSV_nosteal(output, &PL_sv_undef); + } + OUTPUT: + RETVAL gint -purple_cipher_context_decrypt(context, data, len, output, outlen) +purple_cipher_context_decrypt(context, data_sv, output, OUTLIST size_t outlen) Purple::Cipher::Context context - guchar &data - size_t len - guchar &output - size_t &outlen + SV *data_sv + SV *output + PROTOTYPE: $$$ + PREINIT: + size_t datalen; + guchar *buff = NULL; + guchar *data = NULL; + CODE: + data = SvPV(data_sv, datalen); + SvUPGRADE(output, SVt_PV); + buff = SvGROW(output, datalen); + RETVAL = purple_cipher_context_decrypt(context, data, datalen, buff, &outlen); + if(outlen != 0) { + SvPOK_only(output); + SvCUR_set(output, outlen); + } else { + SvSetSV_nosteal(output, &PL_sv_undef); + } + OUTPUT: + RETVAL void purple_cipher_context_set_salt(context, salt) @@ -155,3 +294,21 @@ gpointer purple_cipher_context_get_data(context) Purple::Cipher::Context context + +Purple::Cipher::BatchMode +purple_cipher_context_get_batch_mode(context) + Purple::Cipher::Context context + +size_t +purple_cipher_context_get_block_size(context) + Purple::Cipher::Context context + +void +purple_cipher_context_set_batch_mode(context, mode) + Purple::Cipher::Context context + Purple::Cipher::BatchMode mode + +void +purple_cipher_context_set_key_with_len(Purple::Cipher::Context context, guchar *key, size_t length(key)) + PROTOTYPE: $$ + diff -r b0812ce0ec17 -r af603a54ae5a libpurple/plugins/perl/common/Util.xs --- a/libpurple/plugins/perl/common/Util.xs Thu Aug 07 01:46:36 2008 +0000 +++ b/libpurple/plugins/perl/common/Util.xs Thu Aug 07 02:48:21 2008 +0000 @@ -26,9 +26,24 @@ LEAVE; } +static void markup_find_tag_foreach(GQuark key_id, char *data, HV *hv) { + const char *key = NULL; + key = g_quark_to_string(key_id); + hv_store(hv, key, strlen(key), newSVpv(data, 0), 0); +} + MODULE = Purple::Util PACKAGE = Purple::Util PREFIX = purple_ PROTOTYPES: ENABLE +gboolean +purple_running_gnome() + +gboolean +purple_running_kde() + +gboolean +purple_running_osx() + int purple_build_dir(path, mode) const char *path @@ -49,15 +64,30 @@ const gchar * purple_home_dir() -gboolean -purple_message_meify(message, len) - char *message - size_t len +gchar_own* +purple_message_meify(SV *msg) + PREINIT: + char *message = NULL; + gboolean ret; + gssize len; + CODE: + message = SvPV(msg, len); + message = g_strndup(message, len); + ret = purple_message_meify(message, len); + if(ret) { + /* message will get g_free()'d later on, since RETVAL is gchar_own* */ + RETVAL = message; + } else { + RETVAL = NULL; + g_free(message); + } + OUTPUT: + RETVAL FILE * -purple_mkstemp(path, binary) - char **path +purple_mkstemp(OUTLIST gchar_own *path, binary) gboolean binary + PROTOTYPE: $ const char * purple_normalize(account, str) @@ -122,14 +152,36 @@ purple_url_encode(str) const char *str -gboolean -purple_url_parse(url, ret_host, ret_port, ret_path, ret_user, ret_passwd) + # XXX: this made perl assert()... + # + #gboolean + #purple_url_parse(url, OUTLIST gchar_own *ret_host, OUTLIST int ret_port, OUTLIST gchar_own *ret_path, OUTLIST gchar_own *ret_user, OUTLIST gchar_own *ret_passwd) + # const char *url + # PROTOTYPE: $ + +void +purple_url_parse(url) const char *url - char **ret_host - int *ret_port - char **ret_path - char **ret_user - char **ret_passwd + PREINIT: + char *ret_host; + int ret_port; + char *ret_path; + char *ret_user; + char *ret_passwd; + gboolean ret; + PPCODE: + ret = purple_url_parse(url, &ret_host, &ret_port, &ret_path, &ret_user, &ret_passwd); + XPUSHs(sv_2mortal(newSViv(ret))); + XPUSHs(ret_host ? sv_2mortal(newSVpv(ret_host, 0)) : sv_2mortal(newSV(0))); + XPUSHs(sv_2mortal(newSViv(ret_port))); + XPUSHs(ret_path ? sv_2mortal(newSVpv(ret_path, 0)) : sv_2mortal(newSV(0))); + XPUSHs(ret_user ? sv_2mortal(newSVpv(ret_user, 0)) : sv_2mortal(newSV(0))); + XPUSHs(ret_passwd ? sv_2mortal(newSVpv(ret_passwd, 0)) : sv_2mortal(newSV(0))); + g_free(ret_host); + g_free(ret_path); + g_free(ret_user); + g_free(ret_passwd); + const char * purple_user_dir() @@ -137,6 +189,144 @@ const char * purple_utf8_strftime(const char *format, const struct tm *tm); +gboolean +purple_utf8_has_word(haystack, needle) + const char* haystack + const char* needle + +gchar_own* +purple_utf8_ncr_decode(in) + const char* in + +gchar_own* +purple_utf8_ncr_encode(in) + const char* in + +gchar* +purple_utf8_salvage(str) + const char* str + +int +purple_utf8_strcasecmp(a, b) + const char* a + const char* b + +gchar_own* +purple_utf8_try_convert(str) + const char* str + +gboolean +purple_ip_address_is_valid(ip) + const char* ip + +const char* +purple_normalize_nocase(account, str) + Purple::Account account + const char* str + +const gchar* +purple_gai_strerror(errnum) + gint errnum + +void +purple_got_protocol_handler_uri(uri) + const char* uri + +gchar_own* +purple_base16_encode(const guchar *data, gsize length(data)) + PROTOTYPE: $ + +gchar_own* +purple_base16_encode_chunked(const guchar *data, gsize length(data)) + PROTOTYPE: $ + +gchar_own* +purple_base64_encode(const guchar *data, gsize length(data)) + PROTOTYPE: $ + +void +purple_restore_default_signal_handlers() + +SV * +purple_base16_decode(str) + const char* str + PREINIT: + gsize len; + guchar *ret; + CODE: + ret = purple_base16_decode(str, &len); + if(len) { + RETVAL = newSVpv(ret, len); + } else { + g_free(ret); + XSRETURN_UNDEF; + } + g_free(ret); + OUTPUT: + RETVAL + +SV* +purple_base64_decode(str) + const char* str + PREINIT: + gsize len; + guchar *ret; + CODE: + ret = purple_base64_decode(str, &len); + if(len) { + RETVAL = newSVpv(ret, len); + } else { + g_free(ret); + XSRETURN_UNDEF; + } + g_free(ret); + OUTPUT: + RETVAL + +SV* +purple_quotedp_decode(str) + const char* str + PREINIT: + gsize len; + guchar *ret; + CODE: + ret = purple_quotedp_decode(str, &len); + if(len) { + RETVAL = newSVpv(ret, len); + } else { + g_free(ret); + XSRETURN_UNDEF; + } + g_free(ret); + OUTPUT: + RETVAL + +void +purple_uri_list_extract_uris(uri_list) + const gchar* uri_list + PREINIT: + GList *l = NULL, *gl = NULL; + PPCODE: + gl = purple_uri_list_extract_uris(uri_list); + for(l = gl; l; l = l->next) { + XPUSHs(sv_2mortal(newSVpv(l->data, 0))); + g_free(l->data); + } + g_list_free(gl); + +void +purple_uri_list_extract_filenames(uri_list) + const gchar* uri_list + PREINIT: + GList *l = NULL, *gl = NULL; + PPCODE: + gl = purple_uri_list_extract_filenames(uri_list); + for(l = gl; l; l = l->next) { + XPUSHs(sv_2mortal(newSVpv(l->data, 0))); + g_free(l->data); + } + g_list_free(gl); + MODULE = Purple::Util PACKAGE = Purple::Util::Str PREFIX = purple_str_ PROTOTYPES: ENABLE @@ -145,9 +335,8 @@ const char *str gchar_own * -purple_str_binary_to_ascii(binary, len) - const unsigned char *binary - guint len +purple_str_binary_to_ascii(const unsigned char *binary, guint length(binary)) + PROTOTYPE: $ gboolean purple_str_has_prefix(s, p) @@ -173,12 +362,11 @@ char thechar time_t -purple_str_to_time(timestamp, utc = FALSE, tm = NULL, tz_off = NULL, rest = NULL) +purple_str_to_time(timestamp, utc = FALSE, tm = NULL, OUTLIST long tz_off, OUTLIST const char *rest) const char *timestamp gboolean utc struct tm *tm - long *tz_off - const char **rest + PROTOTYPE: $;$$ MODULE = Purple::Util PACKAGE = Purple::Util::Date PREFIX = purple_date_ PROTOTYPES: ENABLE @@ -213,23 +401,38 @@ const char *link_prefix Purple::Util::InfoFieldFormatCallback format_cb -gboolean -purple_markup_find_tag(needle, haystack, start, end, attributes) + # XXX: returning start/end to perl doesn't make a lot of sense... + # XXX: the actual tag data can be gotten with $start =~ s/$end//g; +void +purple_markup_find_tag(needle, haystack) const char *needle const char *haystack - const char **start - const char **end - GData **attributes + PREINIT: + const char *start = NULL; + const char *end = NULL; + GData *attributes; + gboolean ret; + HV *hv = NULL; + PPCODE: + ret = purple_markup_find_tag(needle, haystack, &start, &end, &attributes); + if(!ret) XSRETURN_UNDEF; + + hv = newHV(); + g_datalist_foreach(&attributes, (GDataForeachFunc) markup_find_tag_foreach, hv); + g_datalist_clear(&attributes); + + XPUSHs(sv_2mortal(newSVpv(start, 0))); + XPUSHs(sv_2mortal(newSVpv(end, 0))); + XPUSHs(sv_2mortal(newRV_noinc((SV *) hv))); gchar_own * purple_markup_get_tag_name(tag) const char *tag void -purple_markup_html_to_xhtml(html, dest_xhtml, dest_plain) +purple_markup_html_to_xhtml(html, OUTLIST gchar_own *dest_xhtml, OUTLIST gchar_own *dest_plain) const char *html - char **dest_xhtml - char **dest_plain + PROTOTYPE: $ gchar_own * purple_markup_linkify(str) @@ -245,9 +448,33 @@ purple_markup_strip_html(str) const char *str +gchar_own * +purple_markup_get_css_property(style, opt) + const gchar* style + const gchar* opt + +SV* +purple_markup_unescape_entity(text) + const char* text + PREINIT: + int length; + CODE: + { + const char *str = purple_markup_unescape_entity(text, &length); + if(length) { + RETVAL = newSVpv(str, length); + } else { + XSRETURN_UNDEF; + } + } + OUTPUT: + RETVAL + + MODULE = Purple::Util PACKAGE = Purple::Util PREFIX = purple_util_ PROTOTYPES: ENABLE + #XXX: expand... void purple_util_fetch_url(plugin, url, full, user_agent, http11, cb) Purple::Plugin plugin @@ -256,14 +483,19 @@ const char *user_agent gboolean http11 SV * cb -CODE: +PREINIT: + PurpleUtilFetchUrlData *data; +PPCODE: + /* XXX: i don't like this... only plugins can use it... */ SV *sv = purple_perl_sv_from_fun(plugin, cb); if (sv != NULL) { - purple_util_fetch_url(url, full, user_agent, http11, + data = purple_util_fetch_url(url, full, user_agent, http11, purple_perl_util_url_cb, sv); + XPUSHs(sv_2mortal(purple_perl_bless_object(data, "Purple::Util::FetchUrlData"))); } else { purple_debug_warning("perl", "Callback not a valid type, only strings and coderefs allowed in purple_util_fetch_url.\n"); + XSRETURN_UNDEF; } void @@ -271,7 +503,44 @@ const char *dir gboolean -purple_util_write_data_to_file(filename, data, size) +purple_util_write_data_to_file(filename, const char *data, size_t length(data)) const char *filename - const char *data - size_t size + PROTOTYPE: $$ + +void +purple_util_set_current_song(title, artist, album) + const char *title + const char *artist + const char *album + +void +purple_util_chrreplace(string, delimiter, replacement) + char* string + char delimiter + char replacement + +gchar_own* +purple_util_format_song_info(title, artist, album, unused) + const char* title + const char* artist + const char* album + gpointer unused + +const char* +purple_util_get_image_extension(gconstpointer data, size_t length(data)) + PROTOTYPE: $ + +gchar_own* +purple_util_get_image_filename(gconstpointer image_data, size_t length(image_data)) + PROTOTYPE: $ + +Purple::XMLNode +purple_util_read_xml_from_file(filename, description) + const char* filename + const char* description + +gboolean +purple_util_write_data_to_file_absolute(filename_full, char *data, gssize length(data)) + const char* filename_full + PROTOTYPE: $$ + diff -r b0812ce0ec17 -r af603a54ae5a libpurple/plugins/perl/common/module.h --- a/libpurple/plugins/perl/common/module.h Thu Aug 07 01:46:36 2008 +0000 +++ b/libpurple/plugins/perl/common/module.h Thu Aug 07 02:48:21 2008 +0000 @@ -86,6 +86,7 @@ typedef PurpleCipherCaps Purple__CipherCaps; typedef PurpleCipherContext * Purple__Cipher__Context; typedef PurpleCipherOps * Purple__Cipher__Ops; +typedef PurpleCipherBatchMode Purple__Cipher__BatchMode; /* cmds.h */ typedef PurpleCmdFlag Purple__Cmd__Flag; diff -r b0812ce0ec17 -r af603a54ae5a libpurple/plugins/perl/common/typemap --- a/libpurple/plugins/perl/common/typemap Thu Aug 07 01:46:36 2008 +0000 +++ b/libpurple/plugins/perl/common/typemap Thu Aug 07 02:48:21 2008 +0000 @@ -18,7 +18,7 @@ gchar * T_PV gchar_own * T_GCHAR_OWN guchar T_IV -guchar * T_PTR +guchar * T_PV guchar ** T_PTR const guchar * T_PV char * T_PV @@ -30,7 +30,7 @@ GString * T_PTR GData * T_PTR GData ** T_PTR -const unsigned char * T_PTR +const unsigned char * T_PV struct tm * T_PTR const struct tm * T_PTR xmlnode * T_PTR @@ -176,6 +176,7 @@ /* enums */ /* cipher.h */ +Purple::Cipher::BatchMode T_IV /* blist.h */