Fri, 30 Jun 2017 15:03:16 +0300
Merged pidgin/main into default
--- a/.hgignore Thu Jun 15 10:48:26 2017 +0300 +++ b/.hgignore Fri Jun 30 15:03:16 2017 +0300 @@ -64,7 +64,6 @@ doc/reference/.*/xml/.* doc/reference/.*/version.xml finch/finch$ -finch/libgnt/gntmarshal.[ch] gtk-doc.make install-sh intltool-.* @@ -75,9 +74,7 @@ libpurple/example/nullclient libpurple/data/purple-url-handler.desktop$ libpurple/data/purple-url-handler.desktop.in$ -libpurple/marshallers.[ch] libpurple/plugins/dbus-example-bindings.c -libpurple/protocols/facebook/marshal.[ch] libpurple/purple-client-bindings.[ch] libpurple/purple-client-example libpurple/purple.h$ @@ -108,7 +105,7 @@ pidgin-.*.tar.gz pidgin-[0-9a-z.-]+/ pidgin.apspec$ -pidgin/.*\.html\.h$ +pidgin/.*\.gresource\.[ch]$ pidgin/pidgin$ pidgin/data/pidgin.appdata.xml$ pidgin/data/pidgin.desktop$
--- a/ChangeLog.API Thu Jun 15 10:48:26 2017 +0300 +++ b/ChangeLog.API Fri Jun 30 15:03:16 2017 +0300 @@ -23,14 +23,6 @@ * purple_account_presence_new * purple_buddy_presence_new * purple_account_register_completed - * PurpleAESCipher, PurpleDESCipher, PurpleDES3Cipher, PurpleHMACCipher, - PurplePBKDF2Cipher and PurpleRC4Cipher inherit PurpleCipher - * purple_aes_cipher_new - * purple_des3_cipher_new - * purple_des_cipher_new - * purple_hmac_cipher_new - * purple_pbkdf2_cipher_new - * purple_rc4_cipher_new * purple_blist_node_is_transient * purple_blist_node_set_transient * purple_certificate_get_der_data @@ -55,13 +47,6 @@ * purple_counting_node_get_* * purple_counting_node_change_* * purple_counting_node_set_* - * PurpleHash and purple_hash_* API - * PurpleMD4Hash, PurpleMD5Hash, PurpleSHA1Hash and PurpleSHA265Hash - inherit PurpleHash - * purple_md4_hash_new - * purple_md5_hash_new - * purple_sha1_hash_new - * purple_sha256_hash_new * PurpleIMConversation and PurpleChatConversation inherit PurpleConversation * purple_notify_emails_pending @@ -197,8 +182,6 @@ * conversation.h has been split into conversation.h (PurpleConversation), conversationtypes.h (PurpleIMConversation and PurpleChatConversation) and conversations.h (Conversations subsystem) - * Files in libpurple/ciphers have been renamed. To use a particular - cipher, include its header. * Renamed ft.h file to xfer.h * Renamed plugin.h file to plugins.h * prpl.h has been split into protocol.h (PurpleProtocol GObject and @@ -259,9 +242,6 @@ * Replaced 'chat-buddy' with 'chat-user' in conversation signals * Replaced chatname, buddyname arguments of 'chat-user-flags' (formerly 'chat-buddy-flags') signal with PurpleChatUser * - * PurpleCipher split into PurpleCipher and PurpleHash, both are - GObjects. Please see the documentation for details. - * purple_cipher_context_* functions are now purple_cipher_* * PurpleCircBuffer changed to PurpleCircularBuffer, is now a GObject. Please see the documentation for details. * purple_circ_buffer_* functions are now purple_circular_buffer_* @@ -403,7 +383,6 @@ * buddy-added and buddy-removed blist signals * privacy.h file * value.h file - * _PurpleCipherBatchMode * _PurpleCmdFlag * _PurpleCmdPriority * _PurpleCmdRet @@ -430,19 +409,8 @@ purple_certificate_check_signature_chain, instead * purple_certificate_display_x509. Use purple_request_certificate, instead - * PurpleCipherContext - * purple_cipher_context_destroy - * purple_cipher_context_get_data - * purple_cipher_context_get_option - * purple_cipher_context_new - * purple_cipher_context_new_by_name - * purple_cipher_context_set_data - * purple_cipher_context_set_option - * purple_cipher_get_capabilities - * purple_cipher_get_name - * PurpleCipherOps - * purple_ciphers_* - * PurpleCipher's init and uninit operations + * Purple Cipher API (PurpleCipherContext and friends). + Use GLib's GHmac or GChecksum instead. * purple_connection_error_reason * purple_connection_new * purple_connection_new_unregister @@ -453,6 +421,10 @@ * PurpleConversationType * purple_core_migrate * purple_dnsquery_a_account + * purple_event_loop_{get|set}_ui_ops. Manually drive the GLib + event loop yourself. See GLib Main Event Loop docs. + * PurpleEventLoopUiOps. Manually drive the GLib event loop + yourself. See GLib Main Event Loop docs. * purple_network_listen_family. Use purple_network_listen, instead. * purple_network_listen_map_external * purple_network_listen_range_family. Use purple_network_listen,
--- a/config.h.mingw Thu Jun 15 10:48:26 2017 +0300 +++ b/config.h.mingw Fri Jun 30 15:03:16 2017 +0300 @@ -287,9 +287,6 @@ /* Define to 1 if you have X11 */ /* #define HAVE_X11 1 */ -/* Define to 1 if you have the <X11/SM/SMlib.h> header file. */ -/* #define HAVE_X11_SM_SMLIB_H 1 */ - /* whether or not we have xsltproc for devhelp index */ /* #define HAVE_XSLTPROC 1 */ @@ -360,9 +357,6 @@ /* Define if we're using XScreenSaver. */ #define USE_SCREENSAVER 1 -/* Define if we're using X Session Management. */ -/* #define USE_SM 1 */ - /* Use voice and video */ /* #define USE_VV 1 */
--- a/configure.ac Thu Jun 15 10:48:26 2017 +0300 +++ b/configure.ac Fri Jun 30 15:03:16 2017 +0300 @@ -109,7 +109,6 @@ AC_SUBST(GNT_LT_VERSION_INFO) AC_PATH_PROG(sedpath, sed) -AC_PATH_PROG(xxdpath, xxd) dnl Storing configure arguments AC_DEFINE_UNQUOTED(CONFIG_ARGS, "$ac_configure_args", [configure arguments]) @@ -488,6 +487,8 @@ GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` AC_SUBST(GLIB_MKENUMS) +AC_PATH_PROG(GLIB_COMPILE_RESOURCES, [glib-compile-resources]) + AC_PATH_PROG(GTESTER, gtester) GLIB_TESTS @@ -522,10 +523,6 @@ [AS_HELP_STRING([--disable-screensaver], [compile without X screensaver extension (used to detect idleness)])], enable_screensaver="$enableval", enable_screensaver="yes") -AC_ARG_ENABLE(sm, - [AS_HELP_STRING([--disable-sm], - [compile without X session management support])], - enable_sm="$enableval", enable_sm="yes") AC_ARG_ENABLE(startup-notification, [AS_HELP_STRING([--disable-startup-notification], [compile without startup notification support])], @@ -644,7 +641,6 @@ AC_SUBST(X11_CFLAGS) else enable_screensaver=no - enable_sm=no enable_gestures=no fi @@ -690,36 +686,6 @@ fi dnl ####################################################################### - dnl # Check for X session management libs - dnl ####################################################################### - if test "x$enable_sm" = "xyes"; then - if test "x$with_x" = "xyes" ; then - enable_sm=no - AC_CHECK_LIB(SM, SmcSaveYourselfDone, found_sm_lib=true, , [$x_libpath_add -lICE]) - if test "x$found_sm_lib" = "xtrue"; then - oldCPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $x_incpath_add" - AC_CHECK_HEADERS(X11/SM/SMlib.h, SM_LIBS="$x_libpath_add -lSM -lICE" enable_sm=yes) - CPPFLAGS="$oldCPPFLAGS" - fi - - if test "x$enable_sm" = "xyes"; then - AC_DEFINE(USE_SM, 1, [Define if we're using X Session Management.]) - AC_SUBST(SM_LIBS) - else - if test "x$force_deps" = "xyes" ; then - AC_MSG_ERROR([ -X session management development headers not found. -Use --disable-sm if you do not need session management support. -]) - fi - fi - else - AC_MSG_ERROR([X support is required to build with X session management support]) - fi - fi - - dnl ####################################################################### dnl # Check for X11 to allow the gestures plugin dnl ####################################################################### if test "x$enable_gestures" = "xyes"; then @@ -787,7 +753,6 @@ enable_cap=no enable_gevolution=no enable_screensaver=no - enable_sm=no enable_startup_notification=no fi # GTK @@ -1865,105 +1830,6 @@ fi AM_CONDITIONAL(INSTALL_SSL_CERTIFICATES, test "x$SSL_CERTIFICATES_DIR" = "x") -dnl These two are inverses of each other <-- stolen from evolution! - -AC_ARG_ENABLE(gnutls, - [ --enable-gnutls=[yes,no] attempt to use GnuTLS for SSL support [default=yes]], - [enable_gnutls="$enableval"], - [enable_gnutls="yes"]) - -AC_ARG_ENABLE(nss, - [ --enable-nss=[yes,no,static] attempt to use Mozilla libnss for SSL support [default=yes]], - [enable_nss="$enableval"], - [enable_nss="yes"]) - -msg_ssl="None. Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!" -looked_for_gnutls="no" -dnl # -dnl # Check for GnuTLS if it isn't disabled -dnl # -if test "x$enable_gnutls" != "xno"; then - looked_for_gnutls="yes" - - if `$PKG_CONFIG --exists gnutls`; then - dnl # minimum required version should almost certainly be higher - PKG_CHECK_MODULES(GNUTLS, [gnutls >= 2.10], [ - have_gnutls="yes" - ], [ - AC_MSG_RESULT(no) - have_gnutls="no" - ]) - fi - - if test "x$have_gnutls" = "xyes"; then - AC_DEFINE(HAVE_GNUTLS, 1, [Define if you have GnuTLS]) - msg_gnutls="GnuTLS" - fi -fi - -AM_CONDITIONAL(USE_GNUTLS, test "x$have_gnutls" = "xyes") - - -dnl # -dnl # Check for NSS if it isn't disabled -dnl # -looked_for_nss="no" -if test "x$enable_nss" != "xno"; then - looked_for_nss="yes" - - if `$PKG_CONFIG --exists mozilla-nss`; then - dnl # TODO: set required minimum version - PKG_CHECK_MODULES(NSS, mozilla-nss, [ - have_nss="yes" - ], [ - AC_MSG_RESULT(no) - have_nss="no" - ]) - elif `$PKG_CONFIG --exists nss`; then - dnl # TODO: set required minimum version - PKG_CHECK_MODULES(NSS, nss, [ - have_nss="yes" - ], [ - AC_MSG_RESULT(no) - have_nss="no" - ]) - fi - - if test "x$have_nss" = "xyes"; then - AC_DEFINE(HAVE_NSS, 1, [Define if you have Mozilla NSS]) - msg_nss="Mozilla NSS" - fi -fi - -AM_CONDITIONAL(USE_NSS, test "x$have_nss" = "xyes") - - -if test "x$msg_nss" != "x" -a "x$msg_gnutls" != "x"; then - msg_ssl="$msg_nss and $msg_gnutls" -elif test "x$msg_nss" != "x"; then - msg_ssl=$msg_nss -elif test "x$msg_gnutls" != "x"; then - msg_ssl=$msg_gnutls -elif test "x$looked_for_gnutls" = "xyes" -a "x$looked_for_nss" = "xyes" -a "x$force_deps" = "xyes" ; then - AC_MSG_ERROR([ -Neither GnuTLS or NSS SSL development headers found. -Use --disable-nss --disable-gnutls if you do not need SSL support. -Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable! -]) -elif test "x$looked_for_gnutls" = "xyes" -a "x$force_deps" = "xyes" ; then - AC_MSG_ERROR([ -GnuTLS SSL development headers not found. -Use --disable-gnutls if you do not need SSL support. -Novell Groupwise and Google Talk will not work without SSL support. -]) -elif test "x$looked_for_nss" = "xyes" -a "x$force_deps" = "xyes" ; then - AC_MSG_ERROR([ -NSS SSL development headers not found. -Use --disable-nss if you do not need SSL support. -Novell Groupwise and Google Talk will not work without SSL support. -]) -fi - if test "$ac_cv_cygwin" = yes ; then LDADD="$LDADD -static" AC_DEFINE(DEBUG, 1, [Define if debugging is enabled.]) @@ -1985,6 +1851,33 @@ AC_SUBST(PLUGINS_DEFINE) dnl ####################################################################### +dnl # Check for Nettle (Crypto Library) +dnl ####################################################################### +AC_ARG_ENABLE(nettle, + [AC_HELP_STRING([--disable-nettle], [disable Nettle support])], + enable_nettle="$enableval", enable_nettle="yes") + +if test "x$enable_nettle" = "xyes" ; then + PKG_CHECK_MODULES(NETTLE, [nettle >= 3.0], [ + enable_nettle="yes" + AC_SUBST(NETTLE_CFLAGS) + AC_SUBST(NETTLE_LIBS) + AC_DEFINE(HAVE_NETTLE, 1, [Define if we have Nettle.]) + ], [ + enable_nettle="no" + ]) + + if test "x$enable_nettle" != "xyes" -a "x$force_deps" = "xyes" ; then + AC_MSG_ERROR([ +Nettle development headers not found +Use --disable-nettle if you do not need it. +]) + fi +fi + +AM_CONDITIONAL(ENABLE_NETTLE, test "x$enable_nettle" = "xyes") + +dnl ####################################################################### dnl # Check for Cyrus-SASL (for xmpp/irc) dnl ####################################################################### dnl AC_CHECK_SIZEOF(short) @@ -2230,10 +2123,10 @@ eval eval echo D-Bus services directory...... : $DBUS_SERVICES_DIR fi echo Build with GNU Libidn......... : $enable_idn -echo SSL Library/Libraries......... : $msg_ssl if test "x$SSL_CERTIFICATES_DIR" != "x" ; then eval eval echo SSL CA certificates directory. : $SSL_CERTIFICATES_DIR fi +echo Build with Nettle support..... : $enable_nettle echo Build with Cyrus SASL support. : $enable_cyrus_sasl echo Use kerberos 4 with zephyr.... : $kerberos echo Use external libzephyr........ : $zephyr @@ -2243,7 +2136,6 @@ echo Has you....................... : yes echo echo Use XScreenSaver Extension.... : $enable_screensaver -echo Use X Session Management...... : $enable_sm echo Use startup notification...... : $enable_startup_notification echo Build with Enchant support.... : $use_enchant echo Build with GCR widgets........ : $enable_gcr
--- a/doc/reference/libpurple/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/doc/reference/libpurple/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -135,8 +135,6 @@ $(IDN_CFLAGS) \ $(NETWORKMANAGER_CFLAGS) \ $(JSON_CFLAGS) \ - $(GNUTLS_CFLAGS) \ - $(NSS_CFLAGS) \ $(ZLIB_CFLAGS) \ $(INTROSPECTION_CFLAGS) @@ -155,8 +153,6 @@ $(GSTINTERFACES_LIBS) \ $(IDN_LIBS) \ $(JSON_LIBS) \ - $(GNUTLS_LIBS) \ - $(NSS_LIBS) \ $(ZLIB_LIBS) \ $(INTROSPECTION_LIBS) \ -lm
--- a/doc/reference/libpurple/libpurple-docs.xml Thu Jun 15 10:48:26 2017 +0300 +++ b/doc/reference/libpurple/libpurple-docs.xml Fri Jun 30 15:03:16 2017 +0300 @@ -38,7 +38,6 @@ <xi:include href="xml/pounce.xml" /> <xi:include href="xml/chat.xml" /> <xi:include href="xml/circularbuffer.xml" /> - <xi:include href="xml/cipher.xml" /> <xi:include href="xml/contact.xml" /> <xi:include href="xml/connection.xml" /> <xi:include href="xml/conversation.xml" /> @@ -104,17 +103,6 @@ <xi:include href="xml/cmds.xml" /> </chapter> - <chapter id="ciphers"> - <title>Ciphers and Hashes</title> - - <xi:include href="xml/aescipher.xml" /> - <xi:include href="xml/descipher.xml" /> - <xi:include href="xml/des3cipher.xml" /> - <xi:include href="xml/pbkdf2cipher.xml" /> - <xi:include href="xml/rc4cipher.xml" /> - <xi:include href="xml/md4hash.xml" /> - </chapter> - <chapter id="smiley"> <title>Smiley APIs</title>
--- a/doc/reference/libpurple/ui_ops.xml Thu Jun 15 10:48:26 2017 +0300 +++ b/doc/reference/libpurple/ui_ops.xml Fri Jun 30 15:03:16 2017 +0300 @@ -17,7 +17,6 @@ <listitem><link linkend="PurpleCoreUiOps"><literal>PurpleCoreUiOps</literal></link></listitem> <listitem><link linkend="PurpleDebugUiOps"><literal>PurpleDebugUiOps</literal></link></listitem> <listitem><link linkend="PurpleDnsQueryUiOps"><literal>PurpleDnsQueryUiOps</literal></link></listitem> -<listitem><link linkend="PurpleEventLoopUiOps"><literal>PurpleEventLoopUiOps</literal></link> (without this, nothing will work and you will cry)</listitem> <listitem><link linkend="PurpleIdleUiOps"><literal>PurpleIdleUiOps</literal></link></listitem> <listitem><link linkend="PurpleNotifyUiOps"><literal>PurpleNotifyUiOps</literal></link></listitem> <listitem><link linkend="PurpleRequestUiOps"><literal>PurpleRequestUiOps</literal></link></listitem>
--- a/doc/reference/pidgin/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/doc/reference/pidgin/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -120,7 +120,6 @@ $(GSTVIDEO_LIBS) \ $(GSTINTERFACES_LIBS) \ $(XSS_LIBS) \ - $(SM_LIBS) \ $(INTLLIBS) \ $(LIBXML_LIBS) \ $(WEBKIT_LIBS) \
--- a/doc/reference/pidgin/pidgin-docs.xml Thu Jun 15 10:48:26 2017 +0300 +++ b/doc/reference/pidgin/pidgin-docs.xml Fri Jun 30 15:03:16 2017 +0300 @@ -35,7 +35,6 @@ <xi:include href="xml/gtkdebug.xml" /> <xi:include href="xml/gtkdocklet.xml" /> <xi:include href="xml/gtkdnd-hints.xml" /> - <xi:include href="xml/gtkeventloop.xml" /> <xi:include href="xml/gtkxfer.xml" /> <xi:include href="xml/gtkicon-theme.xml" /> <xi:include href="xml/gtkidle.xml" /> @@ -65,7 +64,6 @@ <xi:include href="xml/gtkwebview.xml" /> <xi:include href="xml/gtkwebviewtoolbar.xml" /> <xi:include href="xml/gtkwhiteboard.xml" /> - <xi:include href="xml/gtksession.xml" /> <xi:include href="xml/pidgin.xml" /> </part>
--- a/finch/libfinch.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libfinch.c Fri Jun 30 15:03:16 2017 +0300 @@ -26,7 +26,6 @@ #include "conversation.h" #include "core.h" #include "debug.h" -#include "eventloop.h" #include "glibcompat.h" #include "log.h" #include "notify.h" @@ -134,103 +133,6 @@ return &core_ops; } -/* Anything IO-related is directly copied from gtkpurple's source tree */ - -#define FINCH_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) -#define FINCH_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) - -typedef struct _PurpleGntIOClosure { - PurpleInputFunction function; - guint result; - gpointer data; - -} PurpleGntIOClosure; - -static void purple_gnt_io_destroy(gpointer data) -{ - g_free(data); -} - -static gboolean purple_gnt_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) -{ - PurpleGntIOClosure *closure = data; - PurpleInputCondition purple_cond = 0; - - if (condition & FINCH_READ_COND) - purple_cond |= PURPLE_INPUT_READ; - if (condition & FINCH_WRITE_COND) - purple_cond |= PURPLE_INPUT_WRITE; - -#if 0 - purple_debug(PURPLE_DEBUG_MISC, "gtk_eventloop", - "CLOSURE: callback for %d, fd is %d\n", - closure->result, g_io_channel_unix_get_fd(source)); -#endif - -#ifdef _WIN32 - if(! purple_cond) { -#if 0 - purple_debug_misc("gnt_eventloop", - "CLOSURE received GIOCondition of 0x%x, which does not" - " match 0x%x (READ) or 0x%x (WRITE)\n", - condition, FINCH_READ_COND, FINCH_WRITE_COND); -#endif /* DEBUG */ - - return TRUE; - } -#endif /* _WIN32 */ - - closure->function(closure->data, g_io_channel_unix_get_fd(source), - purple_cond); - - return TRUE; -} - -static guint gnt_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function, - gpointer data) -{ - PurpleGntIOClosure *closure = g_new0(PurpleGntIOClosure, 1); - GIOChannel *channel; - GIOCondition cond = 0; - - closure->function = function; - closure->data = data; - - if (condition & PURPLE_INPUT_READ) - cond |= FINCH_READ_COND; - if (condition & PURPLE_INPUT_WRITE) - cond |= FINCH_WRITE_COND; - - channel = g_io_channel_unix_new(fd); - closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, - purple_gnt_io_invoke, closure, purple_gnt_io_destroy); - - g_io_channel_unref(channel); - return closure->result; -} - -static PurpleEventLoopUiOps eventloop_ops = -{ - g_timeout_add, - g_source_remove, - gnt_input_add, - g_source_remove, - NULL, /* input_get_error */ - g_timeout_add_seconds, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static PurpleEventLoopUiOps * -gnt_eventloop_get_ui_ops(void) -{ - return &eventloop_ops; -} - /* This is mostly copied from gtkpurple's source tree */ static void show_usage(const char *name, gboolean terse) @@ -348,7 +250,6 @@ purple_debug_set_enabled(debug_enabled); purple_core_set_ui_ops(gnt_core_get_ui_ops()); - purple_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops()); purple_idle_set_ui_ops(finch_idle_get_ui_ops()); if (!purple_core_init(FINCH_UI))
--- a/finch/libgnt/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -1,5 +1,3 @@ -EXTRA_DIST=genmarshal - SUBDIRS = . wms pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = gnt.pc @@ -8,10 +6,7 @@ noinst_HEADERS = gntinternal.h -BUILT_SOURCES = gntmarshal.h - libgnt_la_SOURCES = \ - gntmarshal.c \ gntwidget.c \ gntbindable.c \ gntbox.c \ @@ -53,7 +48,6 @@ gntkeys.h \ gntlabel.h \ gntline.h \ - gntmarshal.h \ gntmenu.h \ gntmenuitem.h \ gntmenuitemcheck.h \ @@ -68,17 +62,6 @@ gntws.h \ gnt.h -CLEANFILES = \ - gntmarshal.h \ - gntmarshal.c - -gntmarshal.c: $(srcdir)/genmarshal gntmarshal.h - $(AM_V_GEN)echo "#include \"gntmarshal.h\"" > $@ - $(AM_V_at)glib-genmarshal --prefix=gnt_closure_marshal --body $(srcdir)/genmarshal >> $@ - -gntmarshal.h: $(srcdir)/genmarshal - $(AM_V_GEN)glib-genmarshal --prefix=gnt_closure_marshal --header $(srcdir)/genmarshal > $@ - libgnt_laincludedir=$(includedir)/gnt libgnt_lainclude_HEADERS = \ $(libgnt_la_headers) @@ -147,5 +130,5 @@ $(INTROSPECTION_TYPELIBDIR) typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) -CLEANFILES += $(gir_DATA) $(typelib_DATA) +CLEANFILES = $(gir_DATA) $(typelib_DATA) endif
--- a/finch/libgnt/genmarshal Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -BOOLEAN:VOID -BOOLEAN:STRING -VOID:INT,INT,INT,INT -VOID:INT,INT -VOID:POINTER,POINTER -BOOLEAN:INT,INT -BOOLEAN:INT,INT,INT -BOOLEAN:POINTER,POINTER,POINTER -BOOLEAN:INT,INT,INT,POINTER -VOID:STRING,STRING -VOID:POINTER,BOOLEAN
--- a/finch/libgnt/gntcheckbox.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntcheckbox.c Fri Jun 30 15:03:16 2017 +0300 @@ -105,8 +105,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntCheckBoxClass, toggled), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); GNTDEBUG; }
--- a/finch/libgnt/gntclipboard.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntclipboard.c Fri Jun 30 15:03:16 2017 +0300 @@ -37,8 +37,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); }
--- a/finch/libgnt/gntcombobox.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntcombobox.c Fri Jun 30 15:03:16 2017 +0300 @@ -24,7 +24,6 @@ #include "gntbox.h" #include "gntcombobox.h" #include "gnttree.h" -#include "gntmarshal.h" #include "gntstyle.h" #include "gntutils.h" @@ -283,8 +282,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, - NULL, NULL, - gnt_closure_marshal_VOID__POINTER_POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); gnt_bindable_class_register_action(bindable, "dropdown", dropdown_menu,
--- a/finch/libgnt/gntentry.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntentry.c Fri Jun 30 15:03:16 2017 +0300 @@ -26,7 +26,6 @@ #include "gntinternal.h" #include "gntbox.h" #include "gntentry.h" -#include "gntmarshal.h" #include "gntstyle.h" #include "gnttree.h" #include "gntutils.h" @@ -951,16 +950,14 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntEntryClass, text_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_COMPLETION] = g_signal_new("completion", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - gnt_closure_marshal_VOID__POINTER_POINTER, + 0, NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); gnt_bindable_class_register_action(bindable, "cursor-home", move_start,
--- a/finch/libgnt/gntfilesel.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntfilesel.c Fri Jun 30 15:03:16 2017 +0300 @@ -28,7 +28,6 @@ #include "gntentry.h" #include "gntfilesel.h" #include "gntlabel.h" -#include "gntmarshal.h" #include "gntstyle.h" #include "gnttree.h" @@ -506,8 +505,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntFileSelClass, file_selected), - NULL, NULL, - gnt_closure_marshal_VOID__STRING_STRING, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); gnt_bindable_class_register_action(bindable, "toggle-tag", toggle_tag_selection, "t", NULL);
--- a/finch/libgnt/gntmenuitem.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntmenuitem.c Fri Jun 30 15:03:16 2017 +0300 @@ -57,8 +57,7 @@ g_signal_new("activate", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, + 0, NULL, NULL, NULL, G_TYPE_NONE, 0); }
--- a/finch/libgnt/gntslider.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntslider.c Fri Jun 30 15:03:16 2017 +0300 @@ -202,8 +202,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntSliderClass, changed), - NULL, NULL, - g_cclosure_marshal_VOID__INT, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT); gnt_bindable_class_register_action(bindable, "step-backward", step_back, GNT_KEY_LEFT, NULL);
--- a/finch/libgnt/gnttree.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gnttree.c Fri Jun 30 15:03:16 2017 +0300 @@ -21,7 +21,6 @@ */ #include "gntinternal.h" -#include "gntmarshal.h" #include "gntstyle.h" #include "gnttree.h" #include "gntutils.h" @@ -1072,32 +1071,28 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntTreeClass, selection_changed), - NULL, NULL, - gnt_closure_marshal_VOID__POINTER_POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); signals[SIG_SCROLLED] = g_signal_new("scrolled", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, - NULL, NULL, - g_cclosure_marshal_VOID__INT, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT); signals[SIG_TOGGLED] = g_signal_new("toggled", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntTreeClass, toggled), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_COLLAPSED] = g_signal_new("collapse-toggled", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, - NULL, NULL, - gnt_closure_marshal_VOID__POINTER_BOOLEAN, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN); gnt_bindable_class_register_action(bindable, "move-up", action_up,
--- a/finch/libgnt/gntwidget.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntwidget.c Fri Jun 30 15:03:16 2017 +0300 @@ -25,7 +25,6 @@ #include "gntinternal.h" #include "gntwidget.h" #include "gntstyle.h" -#include "gntmarshal.h" #include "gntutils.h" enum @@ -135,104 +134,91 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, destroy), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_GIVE_FOCUS] = g_signal_new("gained-focus", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, gained_focus), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_LOST_FOCUS] = g_signal_new("lost-focus", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, lost_focus), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_ACTIVATE] = g_signal_new("activate", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, activate), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_MAP] = g_signal_new("map", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, map), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_DRAW] = g_signal_new("draw", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, draw), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_HIDE] = g_signal_new("hide", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, hide), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_EXPOSE] = g_signal_new("expose", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, expose), - NULL, NULL, - gnt_closure_marshal_VOID__INT_INT_INT_INT, + NULL, NULL, NULL, G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); signals[SIG_POSITION] = g_signal_new("position-set", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, set_position), - NULL, NULL, - gnt_closure_marshal_VOID__INT_INT, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); signals[SIG_SIZE_REQUEST] = g_signal_new("size_request", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, size_request), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_SIZE_CHANGED] = g_signal_new("size_changed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, size_changed), - NULL, NULL, - gnt_closure_marshal_VOID__INT_INT, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); signals[SIG_CONFIRM_SIZE] = g_signal_new("confirm_size", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, confirm_size), - NULL, NULL, - gnt_closure_marshal_BOOLEAN__INT_INT, + NULL, NULL, NULL, G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_INT); signals[SIG_KEY_PRESSED] = g_signal_new("key_pressed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, key_pressed), - gnt_boolean_handled_accumulator, NULL, - gnt_closure_marshal_BOOLEAN__STRING, + gnt_boolean_handled_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_STRING); signals[SIG_CLICKED] = @@ -240,8 +226,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWidgetClass, clicked), - gnt_boolean_handled_accumulator, NULL, - gnt_closure_marshal_BOOLEAN__INT_INT_INT, + gnt_boolean_handled_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); signals[SIG_CONTEXT_MENU] = @@ -249,8 +234,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, - gnt_boolean_handled_accumulator, NULL, - gnt_closure_marshal_BOOLEAN__VOID, + gnt_boolean_handled_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 0); /* This is relevant for all widgets */
--- a/finch/libgnt/gntwindow.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntwindow.c Fri Jun 30 15:03:16 2017 +0300 @@ -94,8 +94,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[SIG_WORKSPACE_SHOW] = @@ -103,8 +102,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); gnt_bindable_class_register_action(bindable, "show-menu", show_menu,
--- a/finch/libgnt/gntwm.c Thu Jun 15 10:48:26 2017 +0300 +++ b/finch/libgnt/gntwm.c Fri Jun 30 15:03:16 2017 +0300 @@ -50,7 +50,6 @@ #include "gntwm.h" #include "gntstyle.h" -#include "gntmarshal.h" #include "gnt.h" #include "gntbox.h" #include "gntbutton.h" @@ -1421,32 +1420,28 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, new_window), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_DECORATE_WIN] = g_signal_new("decorate_win", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, decorate_window), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_CLOSE_WIN] = g_signal_new("close_win", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, close_window), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_CONFIRM_RESIZE] = g_signal_new("confirm_resize", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, window_resize_confirm), - gnt_boolean_handled_accumulator, NULL, - gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER, + gnt_boolean_handled_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER); signals[SIG_CONFIRM_MOVE] = @@ -1454,8 +1449,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, window_move_confirm), - gnt_boolean_handled_accumulator, NULL, - gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER, + gnt_boolean_handled_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER); signals[SIG_RESIZED] = @@ -1463,24 +1457,21 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, window_resized), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_MOVED] = g_signal_new("window_moved", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, window_moved), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_UPDATE_WIN] = g_signal_new("window_update", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, window_update), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_GIVE_FOCUS] = @@ -1488,8 +1479,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, give_focus), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_MOUSE_CLICK] = @@ -1497,8 +1487,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, mouse_clicked), - gnt_boolean_handled_accumulator, NULL, - gnt_closure_marshal_BOOLEAN__INT_INT_INT_POINTER, + gnt_boolean_handled_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_POINTER); signals[SIG_TERMINAL_REFRESH] = @@ -1506,8 +1495,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntWMClass, terminal_refresh), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-next", window_next,
--- a/libpurple/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -5,7 +5,6 @@ enums.c.in \ enums.h.in \ glibcompat.h \ - marshallers.list \ purple-notifications-example \ purple-remote \ purple-send \ @@ -40,13 +39,6 @@ buddylist.c \ buddyicon.c \ chat.c \ - ciphers/aescipher.c \ - ciphers/descipher.c \ - ciphers/des3cipher.c \ - ciphers/md4hash.c \ - ciphers/pbkdf2cipher.c \ - ciphers/rc4cipher.c \ - cipher.c \ circularbuffer.c \ cmds.c \ connection.c \ @@ -121,8 +113,7 @@ xmlnode.c purple_builtsources = \ - enums.c \ - marshallers.c + enums.c purple_coreheaders = \ account.h \ @@ -133,7 +124,6 @@ buddylist.h \ buddyicon.h \ chat.h \ - cipher.h \ circularbuffer.h \ cmds.h \ connection.h \ @@ -233,20 +223,11 @@ codec.h \ enum-types.h -purple_cipherheaders = \ - aescipher.h \ - descipher.h \ - des3cipher.h \ - md4hash.h \ - pbkdf2cipher.h \ - rc4cipher.h - -purple_builtheaders = purple.h version.h enums.h marshallers.h +purple_builtheaders = purple.h version.h enums.h purple_enumheaders = \ $(srcdir)/account.h \ $(srcdir)/buddyicon.h \ - $(srcdir)/cipher.h \ $(srcdir)/connection.h \ $(srcdir)/conversation.h \ $(srcdir)/conversationtypes.h \ @@ -263,13 +244,6 @@ $(srcdir)/xmlnode.h -marshallers.h: marshallers.list - $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --header > marshallers.h - -marshallers.c: marshallers.list marshallers.h - $(AM_V_GEN)echo "#include \"marshallers.h\"" > marshallers.c - $(AM_V_at)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --body >> marshallers.c - # glib-mkenums doesn't handle VPATHs well, sed is used here to fix the # include paths and documentation. # Escaping possible . in $(srcdir) to \. for sed pattern. @@ -283,9 +257,7 @@ CLEANFILES = \ enums.c \ - enums.h \ - marshallers.c \ - marshallers.h + enums.h DISTCLEANFILES = \ data/purple-url-handler.desktop @@ -314,14 +286,13 @@ prefs.h presence.h roomlist.h savedstatuses.h smiley.h smiley-list.h \ status.h server.h util.h xmlnode.h protocol.h protocols.h -# Filter out enums.h and marshallers.h as they don't actually generate -# anything. This way making from a VPATH and distcheck doesn't fail due -# to not being able to find the enums.h or marshallers.h files if -# they've already been generated in the $(srcdir). +# Filter out enums.h as it doesn't actually generate anything. +# This way making from a VPATH and distcheck doesn't fail due +# to not being able to find the enums.h file if it's already +# been generated in the $(srcdir). purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \ - $(addprefix $(srcdir)/ciphers/, $(purple_cipherheaders)) \ $(addprefix $(srcdir)/media/, $(purple_mediaheaders)) \ - $(filter-out: enums.h marshallers.h, $(purple_builtheaders)) + $(filter-out: enums.h, $(purple_builtheaders)) dbus_build_exported = $(addprefix $(srcdir)/, $(dbus_exported)) # We should probably make this better dbus_signals = $(addprefix $(srcdir)/, $(purple_coresources)) \ @@ -345,7 +316,7 @@ # Declare these as dependencies so they're built even if `make distcheck` # is run immediately after configuring. -$(libpurple_la_OBJECTS): dbus-types.h enums.h marshallers.h +$(libpurple_la_OBJECTS): dbus-types.h enums.h # libpurple-client @@ -358,7 +329,7 @@ purple-client-bindings.c: dbus-analyze-functions.py $(dbus_exported) $(AM_V_GEN) $(PYTHON) $(srcdir)/dbus-analyze-functions.py --client -o $@ $(dbus_build_exported) -purple-client-bindings.h: dbus-analyze-types.py dbus-analyze-functions.py $(purple_coreheaders) $(addprefix ciphers/, $(purple_cipherheaders)) $(addprefix media/, $(purple_mediaheaders)) $(purple_builtheaders) $(dbus_exported) +purple-client-bindings.h: dbus-analyze-types.py dbus-analyze-functions.py $(purple_coreheaders) $(addprefix media/, $(purple_mediaheaders)) $(purple_builtheaders) $(dbus_exported) $(AM_V_GEN) $(PYTHON) $(srcdir)/dbus-analyze-types.py --keyword=enum --verbatim -o $@ $(purple_build_coreheaders) $(AM_V_at) $(PYTHON) $(srcdir)/dbus-analyze-functions.py --client --headers --append -o $@ $(dbus_build_exported) @@ -398,7 +369,7 @@ # Declare these as dependencies so they're built even if `make distcheck` # is run immediately after configuring. -$(libpurple_la_OBJECTS): enums.h marshallers.h +$(libpurple_la_OBJECTS): enums.h endif @@ -420,10 +391,6 @@ $(purple_builtheaders) \ $(dbus_headers) -cipherincludedir=$(includedir)/libpurple/ciphers -cipherinclude_HEADERS = \ - $(addprefix $(srcdir)/ciphers/, $(purple_cipherheaders)) - mediaincludedir=$(includedir)/libpurple/media mediainclude_HEADERS = \ $(addprefix $(srcdir)/media/, $(purple_mediaheaders)) @@ -467,8 +434,6 @@ $(GSTINTERFACES_LIBS) \ $(IDN_LIBS) \ $(JSON_LIBS) \ - $(GNUTLS_LIBS) \ - $(NSS_LIBS) \ $(ZLIB_LIBS) \ $(INTROSPECTION_LIBS) \ -lm @@ -487,8 +452,6 @@ $(IDN_CFLAGS) \ $(NETWORKMANAGER_CFLAGS) \ $(JSON_CFLAGS) \ - $(GNUTLS_CFLAGS) \ - $(NSS_CFLAGS) \ $(ZLIB_CFLAGS) \ $(INTROSPECTION_CFLAGS) @@ -500,7 +463,6 @@ if HAVE_INTROSPECTION introspection_sources = \ $(libpurpleinclude_HEADERS) \ - $(addprefix ciphers/, $(purple_cipherheaders)) \ $(addprefix media/, $(purple_mediaheaders)) Purple-$(PURPLE_MAJOR_VERSION).$(PURPLE_MINOR_VERSION).gir: $(builddir)/libpurple.la @@ -530,8 +492,6 @@ $(IDN_CFLAGS) \ $(NETWORKMANAGER_CFLAGS) \ $(JSON_CFLAGS) \ - $(GNUTLS_CFLAGS) \ - $(NSS_CFLAGS) \ $(ZLIB_CFLAGS) \ $(INTROSPECTION_CFLAGS)
--- a/libpurple/Makefile.mingw Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/Makefile.mingw Fri Jun 30 15:03:16 2017 +0300 @@ -56,7 +56,7 @@ VV_SRC = endif -BUILT_SRC = marshallers.c enums.c +BUILT_SRC = enums.c C_SRC = \ $(BUILT_SRC) \ @@ -68,13 +68,6 @@ buddylist.c \ buddyicon.c \ certificate.c \ - ciphers/aescipher.c \ - ciphers/descipher.c \ - ciphers/des3cipher.c \ - ciphers/md4hash.c \ - ciphers/pbkdf2cipher.c \ - ciphers/rc4cipher.c \ - cipher.c \ circularbuffer.c \ cmds.c \ connection.c \ @@ -146,7 +139,6 @@ ENUM_HEADERS = \ account.h \ - cipher.h \ connection.h \ conversation.h \ conversationtypes.h \ @@ -209,15 +201,6 @@ $(OBJECTS): $(PURPLE_CONFIG_H) $(PURPLE_VERSION_H) $(PURPLE_PURPLE_H) -marshallers.h: marshallers.list - @echo -e " GEN\t$@" - @$(GLIB_GENMARSHAL) --prefix=purple_smarshal $< --header > marshallers.h - -marshallers.c: marshallers.list marshallers.h - @echo -e " GEN\t$@" - @echo "#include \"marshallers.h\"" > marshallers.c - @$(GLIB_GENMARSHAL) --prefix=purple_smarshal $< --body >> marshallers.c - enums.h: enums.h.in $(ENUM_HEADERS) @echo -e " GEN\t$@" @$(GLIB_MKENUMS) --template enums.h.in $(ENUM_HEADERS) > enums.h @@ -233,7 +216,7 @@ ## CLEAN RULES ## clean: - rm -f $(OBJECTS) $(RC_SRC) $(PURPLE_VERSION_H) $(PURPLE_PURPLE_H) marshallers.h marshallers.c enums.h enums.c + rm -f $(OBJECTS) $(RC_SRC) $(PURPLE_VERSION_H) $(PURPLE_PURPLE_H) enums.h enums.c rm -f $(TARGET).dll $(TARGET).dll.a $(TARGET).def $(MAKE_at) $(MAKE) -C $(PURPLE_PROTOS_TOP) -f $(MINGW_MAKEFILE) clean $(MAKE_at) $(MAKE) -C $(PURPLE_PLUGINS_TOP) -f $(MINGW_MAKEFILE) clean
--- a/libpurple/cipher.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,555 +0,0 @@ -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "internal.h" -#include "cipher.h" -#include "debug.h" - -/****************************************************************************** - * PurpleCipher API - *****************************************************************************/ -GType -purple_cipher_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleCipherClass), - NULL, - NULL, - NULL, - NULL, - NULL, - sizeof(PurpleCipher), - 0, - NULL, - NULL - }; - - type = g_type_register_static(G_TYPE_OBJECT, - "PurpleCipher", - &info, G_TYPE_FLAG_ABSTRACT); - } - - return type; -} - -static const gchar * -purple_cipher_get_name(PurpleCipher *cipher) -{ - PurpleCipherClass *klass; - const gchar *name; - - if (!PURPLE_IS_CIPHER(cipher)) - return "(error: not a cipher)"; - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - if (!klass) - return "(error: unknown cipher class)"; - - name = g_type_name(G_TYPE_FROM_CLASS(klass)); - if (!name) - return "(error: unknown cipher name)"; - - return name; -} - -static const gchar * -purple_hash_get_name(PurpleHash *hash) -{ - PurpleHashClass *klass; - const gchar *name; - - if (!PURPLE_IS_HASH(hash)) - return "(error: not a hash)"; - - klass = PURPLE_HASH_GET_CLASS(hash); - if (!klass) - return "(error: unknown hash class)"; - - name = g_type_name(G_TYPE_FROM_CLASS(klass)); - if (!name) - return "(error: unknown hash name)"; - - return name; -} - -void -purple_cipher_reset(PurpleCipher *cipher) { - PurpleCipherClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->reset) - klass->reset(cipher); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the reset method", - purple_cipher_get_name(cipher)); - } -} - -void -purple_cipher_reset_state(PurpleCipher *cipher) { - PurpleCipherClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->reset_state) - klass->reset_state(cipher); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the reset_state method", - purple_cipher_get_name(cipher)); - } -} - -void -purple_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) -{ - PurpleCipherClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - g_return_if_fail(iv); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->set_iv) - klass->set_iv(cipher, iv, len); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the set_iv method", - purple_cipher_get_name(cipher)); - } -} - -void -purple_cipher_append(PurpleCipher *cipher, const guchar *data, - size_t len) -{ - PurpleCipherClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->append) - klass->append(cipher, data, len); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the append method", - purple_cipher_get_name(cipher)); - } -} - -gboolean -purple_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len) -{ - PurpleCipherClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), FALSE); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->digest) - return klass->digest(cipher, digest, len); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the digest method", - purple_cipher_get_name(cipher)); - } - - return FALSE; -} - -gboolean -purple_cipher_digest_to_str(PurpleCipher *cipher, gchar digest_s[], size_t len) -{ - /* 8k is a bit excessive, will tweak later. */ - guchar digest[BUF_LEN * 4]; - size_t digest_size, n; - - g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), FALSE); - g_return_val_if_fail(digest_s, FALSE); - - digest_size = purple_cipher_get_digest_size(cipher); - - g_return_val_if_fail(digest_size <= BUF_LEN * 4, FALSE); - - if(!purple_cipher_digest(cipher, digest, sizeof(digest))) - return FALSE; - - /* Every digest byte occupies 2 chars + the NUL at the end. */ - g_return_val_if_fail(digest_size * 2 + 1 <= len, FALSE); - - for(n = 0; n < digest_size; n++) - sprintf(digest_s + (n * 2), "%02x", digest[n]); - - digest_s[n * 2] = '\0'; - - return TRUE; -} - -size_t -purple_cipher_get_digest_size(PurpleCipher *cipher) -{ - PurpleCipherClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), FALSE); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->get_digest_size) - return klass->get_digest_size(cipher); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the get_digest_size method", - purple_cipher_get_name(cipher)); - } - - return FALSE; -} - -ssize_t -purple_cipher_encrypt(PurpleCipher *cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - PurpleCipherClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - g_return_val_if_fail(input != NULL, -1); - g_return_val_if_fail(output != NULL, -1); - g_return_val_if_fail(out_size >= in_len, -1); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->encrypt) - return klass->encrypt(cipher, input, in_len, output, out_size); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the encrypt method", - purple_cipher_get_name(cipher)); - } - - return -1; -} - -ssize_t -purple_cipher_decrypt(PurpleCipher *cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - PurpleCipherClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - g_return_val_if_fail(input != NULL, -1); - g_return_val_if_fail(output != NULL, -1); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->decrypt) - return klass->decrypt(cipher, input, in_len, output, out_size); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the decrypt method", - purple_cipher_get_name(cipher)); - } - - return -1; -} - -void -purple_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len) { - PurpleCipherClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->set_salt) - klass->set_salt(cipher, salt, len); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the set_salt method", - purple_cipher_get_name(cipher)); - } -} - -void -purple_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { - PurpleCipherClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->set_key) - klass->set_key(cipher, key, len); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the set_key method", - purple_cipher_get_name(cipher)); - } -} - -size_t -purple_cipher_get_key_size(PurpleCipher *cipher) { - PurpleCipherClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->get_key_size) - return klass->get_key_size(cipher); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the get_key_size method", - purple_cipher_get_name(cipher)); - } - - return -1; -} - -void -purple_cipher_set_batch_mode(PurpleCipher *cipher, - PurpleCipherBatchMode mode) -{ - PurpleCipherClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->set_batch_mode) - klass->set_batch_mode(cipher, mode); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the set_batch_mode method", - purple_cipher_get_name(cipher)); - } -} - -PurpleCipherBatchMode -purple_cipher_get_batch_mode(PurpleCipher *cipher) -{ - PurpleCipherClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->get_batch_mode) - return klass->get_batch_mode(cipher); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the get_batch_mode method", - purple_cipher_get_name(cipher)); - } - - return -1; -} - -size_t -purple_cipher_get_block_size(PurpleCipher *cipher) -{ - PurpleCipherClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - - klass = PURPLE_CIPHER_GET_CLASS(cipher); - - if (klass && klass->get_block_size) - return klass->get_block_size(cipher); - else { - purple_debug_warning("cipher", "the %s cipher does not " - "implement the get_block_size method", - purple_cipher_get_name(cipher)); - } - - return -1; -} - -/****************************************************************************** - * PurpleHash API - *****************************************************************************/ -GType -purple_hash_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleHashClass), - NULL, - NULL, - NULL, - NULL, - NULL, - sizeof(PurpleHash), - 0, - NULL, - NULL - }; - - type = g_type_register_static(G_TYPE_OBJECT, - "PurpleHash", - &info, G_TYPE_FLAG_ABSTRACT); - } - - return type; -} - -void -purple_hash_reset(PurpleHash *hash) { - PurpleHashClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_HASH(hash)); - - klass = PURPLE_HASH_GET_CLASS(hash); - - if (klass && klass->reset) - klass->reset(hash); - else { - purple_debug_warning("hash", "the %s hash does not implement " - "the reset method", purple_hash_get_name(hash)); - } -} - -void -purple_hash_reset_state(PurpleHash *hash) { - PurpleHashClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_HASH(hash)); - - klass = PURPLE_HASH_GET_CLASS(hash); - - if (klass && klass->reset_state) - klass->reset_state(hash); - else { - purple_debug_warning("hash", "the %s hash does not implement " - "the reset_state method", purple_hash_get_name(hash)); - } -} - -void -purple_hash_append(PurpleHash *hash, const guchar *data, - size_t len) -{ - PurpleHashClass *klass = NULL; - - g_return_if_fail(PURPLE_IS_HASH(hash)); - - klass = PURPLE_HASH_GET_CLASS(hash); - - if (klass && klass->append) - klass->append(hash, data, len); - else { - purple_debug_warning("hash", "the %s hash does not implement " - "the append method", purple_hash_get_name(hash)); - } -} - -gboolean -purple_hash_digest(PurpleHash *hash, guchar digest[], size_t len) -{ - PurpleHashClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_HASH(hash), FALSE); - - klass = PURPLE_HASH_GET_CLASS(hash); - - if (klass && klass->digest) - return klass->digest(hash, digest, len); - else { - purple_debug_warning("hash", "the %s hash does not implement " - "the digest method", purple_hash_get_name(hash)); - } - - return FALSE; -} - -gboolean -purple_hash_digest_to_str(PurpleHash *hash, gchar digest_s[], size_t len) -{ - /* 8k is a bit excessive, will tweak later. */ - guchar digest[BUF_LEN * 4]; - size_t digest_size, n; - - g_return_val_if_fail(PURPLE_IS_HASH(hash), FALSE); - g_return_val_if_fail(digest_s, FALSE); - - digest_size = purple_hash_get_digest_size(hash); - - g_return_val_if_fail(digest_size <= BUF_LEN * 4, FALSE); - - if(!purple_hash_digest(hash, digest, sizeof(digest))) - return FALSE; - - /* Every digest byte occupies 2 chars + the NUL at the end. */ - g_return_val_if_fail(digest_size * 2 + 1 <= len, FALSE); - - for(n = 0; n < digest_size; n++) - sprintf(digest_s + (n * 2), "%02x", digest[n]); - - digest_s[n * 2] = '\0'; - - return TRUE; -} - -size_t -purple_hash_get_digest_size(PurpleHash *hash) -{ - PurpleHashClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_HASH(hash), FALSE); - - klass = PURPLE_HASH_GET_CLASS(hash); - - if (klass && klass->get_digest_size) - return klass->get_digest_size(hash); - else { - purple_debug_warning("hash", "the %s hash does not implement " - "the get_digest_size method", purple_hash_get_name(hash)); - } - - return FALSE; -} - -size_t -purple_hash_get_block_size(PurpleHash *hash) -{ - PurpleHashClass *klass = NULL; - - g_return_val_if_fail(PURPLE_IS_HASH(hash), -1); - - klass = PURPLE_HASH_GET_CLASS(hash); - - if (klass && klass->get_block_size) - return klass->get_block_size(hash); - else { - purple_debug_warning("hash", "the %s hash does not implement " - "the get_block_size method", purple_hash_get_name(hash)); - } - - return -1; -}
--- a/libpurple/cipher.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,421 +0,0 @@ -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef PURPLE_CIPHER_H -#define PURPLE_CIPHER_H -/** - * SECTION:cipher - * @section_id: libpurple-cipher - * @short_description: <filename>cipher.h</filename> - * @title: Cipher and Hash API - */ - -#include <glib.h> -#include <glib-object.h> -#include <string.h> - -#define PURPLE_TYPE_CIPHER (purple_cipher_get_type()) -#define PURPLE_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CIPHER, PurpleCipher)) -#define PURPLE_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CIPHER, PurpleCipherClass)) -#define PURPLE_IS_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CIPHER)) -#define PURPLE_IS_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CIPHER)) -#define PURPLE_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CIPHER, PurpleCipherClass)) - -typedef struct _PurpleCipher PurpleCipher; -typedef struct _PurpleCipherClass PurpleCipherClass; - -#define PURPLE_TYPE_HASH (purple_hash_get_type()) -#define PURPLE_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_HASH, PurpleHash)) -#define PURPLE_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_HASH, PurpleHashClass)) -#define PURPLE_IS_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_HASH)) -#define PURPLE_IS_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_HASH)) -#define PURPLE_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_HASH, PurpleHashClass)) - -typedef struct _PurpleHash PurpleHash; -typedef struct _PurpleHashClass PurpleHashClass; - -/** - * PurpleCipherBatchMode: - * @PURPLE_CIPHER_BATCH_MODE_ECB: Electronic Codebook Mode - * @PURPLE_CIPHER_BATCH_MODE_CBC: Cipher Block Chaining Mode - * - * Modes for batch encrypters - */ -typedef enum { - PURPLE_CIPHER_BATCH_MODE_ECB, - PURPLE_CIPHER_BATCH_MODE_CBC -} PurpleCipherBatchMode; - -/** - * PurpleCipher: - * - * Purple Cipher is an opaque data structure and should not be used directly. - */ -struct _PurpleCipher { - GObject gparent; -}; - -struct _PurpleCipherClass { - GObjectClass parent_class; - - /** The reset function */ - void (*reset)(PurpleCipher *cipher); - - /** The reset state function */ - void (*reset_state)(PurpleCipher *cipher); - - /** The set initialization vector function */ - void (*set_iv)(PurpleCipher *cipher, guchar *iv, size_t len); - - /** The append data function */ - void (*append)(PurpleCipher *cipher, const guchar *data, size_t len); - - /** The digest function */ - gboolean (*digest)(PurpleCipher *cipher, guchar digest[], size_t len); - - /** The get digest size function */ - size_t (*get_digest_size)(PurpleCipher *cipher); - - /** The encrypt function */ - ssize_t (*encrypt)(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); - - /** The decrypt function */ - ssize_t (*decrypt)(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); - - /** The set salt function */ - void (*set_salt)(PurpleCipher *cipher, const guchar *salt, size_t len); - - /** The set key function */ - void (*set_key)(PurpleCipher *cipher, const guchar *key, size_t len); - - /** The get key size function */ - size_t (*get_key_size)(PurpleCipher *cipher); - - /** The set batch mode function */ - void (*set_batch_mode)(PurpleCipher *cipher, PurpleCipherBatchMode mode); - - /** The get batch mode function */ - PurpleCipherBatchMode (*get_batch_mode)(PurpleCipher *cipher); - - /** The get block size function */ - size_t (*get_block_size)(PurpleCipher *cipher); - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -/** - * PurpleHash: - * - * Purple Hash is an opaque data structure and should not be used directly. - */ -struct _PurpleHash { - GObject gparent; -}; - -struct _PurpleHashClass { - GObjectClass parent_class; - - /** The reset function */ - void (*reset)(PurpleHash *hash); - - /** The reset state function */ - void (*reset_state)(PurpleHash *hash); - - /** The append data function */ - void (*append)(PurpleHash *hash, const guchar *data, size_t len); - - /** The digest function */ - gboolean (*digest)(PurpleHash *hash, guchar digest[], size_t len); - - /** The get digest size function */ - size_t (*get_digest_size)(PurpleHash *hash); - - /** The get block size function */ - size_t (*get_block_size)(PurpleHash *hash); - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -/*****************************************************************************/ -/* PurpleCipher API */ -/*****************************************************************************/ - -/** - * purple_cipher_get_type: - * - * Returns: The #GType for the Cipher object. - */ -GType purple_cipher_get_type(void); - -/** - * purple_cipher_reset: - * @cipher: The cipher - * - * Resets a cipher to it's default value - * Note: If you have set an IV you will have to set it after resetting - */ -void purple_cipher_reset(PurpleCipher *cipher); - -/** - * purple_cipher_reset_state: - * @cipher: The cipher - * - * Resets a cipher state to it's default value, but doesn't touch stateless - * configuration. - * - * That means, IV and digest will be wiped out, but keys, ops or salt - * will remain untouched. - */ -void purple_cipher_reset_state(PurpleCipher *cipher); - -/** - * purple_cipher_set_iv: - * @cipher: The cipher - * @iv: The initialization vector to set - * @len: The len of the IV - * - * Sets the initialization vector for a cipher - * Note: This should only be called right after a cipher is created or reset - */ -void purple_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len); - -/** - * purple_cipher_append: - * @cipher: The cipher - * @data: The data to append - * @len: The length of the data - * - * Appends data to the cipher context - */ -void purple_cipher_append(PurpleCipher *cipher, const guchar *data, size_t len); - -/** - * purple_cipher_digest: - * @cipher: The cipher - * @digest: The return buffer for the digest - * @len: The length of the buffer - * - * Digests a cipher context - */ -gboolean purple_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len); - -/** - * purple_cipher_digest_to_str: - * @cipher: The cipher - * @digest_s: The return buffer for the string digest - * @len: The length of the buffer - * - * Converts a guchar digest into a hex string - */ -gboolean purple_cipher_digest_to_str(PurpleCipher *cipher, gchar digest_s[], size_t len); - -/** - * purple_cipher_get_digest_size: - * @cipher: The cipher whose digest size to get - * - * Gets the digest size of a cipher - * - * Returns: The digest size of the cipher - */ -size_t purple_cipher_get_digest_size(PurpleCipher *cipher); - -/** - * purple_cipher_encrypt: - * @cipher: The cipher - * @input: The data to encrypt - * @in_len: The length of the data - * @output: The output buffer - * @out_size: The size of the output buffer - * - * Encrypts data using the cipher - * - * Returns: A length of data that was outputed or -1, if failed - */ -ssize_t purple_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); - -/** - * purple_cipher_decrypt: - * @cipher: The cipher - * @input: The data to encrypt - * @in_len: The length of the returned value - * @output: The output buffer - * @out_size: The size of the output buffer - * - * Decrypts data using the cipher - * - * Returns: A length of data that was outputed or -1, if failed - */ -ssize_t purple_cipher_decrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); - -/** - * purple_cipher_set_salt: - * @cipher: The cipher whose salt to set - * @salt: The salt - * @len: The length of the salt - * - * Sets the salt on a cipher - */ -void purple_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len); - -/** - * purple_cipher_set_key: - * @cipher: The cipher whose key to set - * @key: The key - * @len: The size of the key - * - * Sets the key on a cipher - */ -void purple_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len); - -/** - * purple_cipher_get_key_size: - * @cipher: The cipher whose key size to get - * - * Gets the size of the key if the cipher supports it - * - * Returns: The size of the key - */ -size_t purple_cipher_get_key_size(PurpleCipher *cipher); - -/** - * purple_cipher_set_batch_mode: - * @cipher: The cipher whose batch mode to set - * @mode: The batch mode under which the cipher should operate - * - * Sets the batch mode of a cipher - */ -void purple_cipher_set_batch_mode(PurpleCipher *cipher, PurpleCipherBatchMode mode); - -/** - * purple_cipher_get_batch_mode: - * @cipher: The cipher whose batch mode to get - * - * Gets the batch mode of a cipher - * - * Returns: The batch mode under which the cipher is operating - */ -PurpleCipherBatchMode purple_cipher_get_batch_mode(PurpleCipher *cipher); - -/** - * purple_cipher_get_block_size: - * @cipher: The cipher whose block size to get - * - * Gets the block size of a cipher - * - * Returns: The block size of the cipher - */ -size_t purple_cipher_get_block_size(PurpleCipher *cipher); - -/*****************************************************************************/ -/* PurpleHash API */ -/*****************************************************************************/ - -/** - * purple_hash_get_type: - * - * Returns: The #GType for the Hash object. - */ -GType purple_hash_get_type(void); - -/** - * purple_hash_reset: - * @hash: The hash - * - * Resets a hash to it's default value - * Note: If you have set an IV you will have to set it after resetting - */ -void purple_hash_reset(PurpleHash *hash); - -/** - * purple_hash_reset_state: - * @hash: The hash - * - * Resets a hash state to it's default value, but doesn't touch stateless - * configuration. - * - * That means, IV and digest will be wiped out, but keys, ops or salt - * will remain untouched. - */ -void purple_hash_reset_state(PurpleHash *hash); - -/** - * purple_hash_append: - * @hash: The hash - * @data: The data to append - * @len: The length of the data - * - * Appends data to the hash context - */ -void purple_hash_append(PurpleHash *hash, const guchar *data, size_t len); - -/** - * purple_hash_digest: - * @hash: The hash - * @digest: The return buffer for the digest - * @len: The length of the buffer - * - * Digests a hash context - */ -gboolean purple_hash_digest(PurpleHash *hash, guchar digest[], size_t len); - -/** - * purple_hash_digest_to_str: - * @hash: The hash - * @digest_s: The return buffer for the string digest - * @len: The length of the buffer - * - * Converts a guchar digest into a hex string - */ -gboolean purple_hash_digest_to_str(PurpleHash *hash, gchar digest_s[], size_t len); - -/** - * purple_hash_get_digest_size: - * @hash: The hash whose digest size to get - * - * Gets the digest size of a hash - * - * Returns: The digest size of the hash - */ -size_t purple_hash_get_digest_size(PurpleHash *hash); - -/** - * purple_hash_get_block_size: - * @hash: The hash whose block size to get - * - * Gets the block size of a hash - * - * Returns: The block size of the hash - */ -size_t purple_hash_get_block_size(PurpleHash *hash); - -G_END_DECLS - -#endif /* PURPLE_CIPHER_H */
--- a/libpurple/ciphers/aescipher.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,725 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - * Written by Tomek Wasilczyk <twasilczyk@pidgin.im> - */ - -#include "internal.h" -#include "glibcompat.h" - -#include "aescipher.h" -#include "debug.h" -#include "enums.h" - -#include <string.h> - -#if defined(HAVE_GNUTLS) -# define PURPLE_AES_USE_GNUTLS 1 -# include <gnutls/gnutls.h> -# include <gnutls/crypto.h> -#elif defined(HAVE_NSS) -# define PURPLE_AES_USE_NSS 1 -# include <nss.h> -# include <pk11pub.h> -# include <prerror.h> -#else -# warning "No GnuTLS or NSS support" -#endif - -/* 128bit */ -#define PURPLE_AES_BLOCK_SIZE 16 - -/****************************************************************************** - * Structs - *****************************************************************************/ -#define PURPLE_AES_CIPHER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherPrivate)) - -typedef struct { - guchar iv[PURPLE_AES_BLOCK_SIZE]; - guchar key[32]; - guint key_size; - gboolean failure; - PurpleCipherBatchMode batch_mode; -} PurpleAESCipherPrivate; - -/****************************************************************************** - * Enums - *****************************************************************************/ -enum { - PROP_NONE, - PROP_BATCH_MODE, - PROP_IV, - PROP_KEY, - PROP_LAST, -}; - -/******************************************************************************* - * Globals - ******************************************************************************/ -static GParamSpec *properties[PROP_LAST]; - -/****************************************************************************** - * Cipher Stuff - *****************************************************************************/ - -typedef gboolean (*purple_aes_cipher_crypt_func)( - const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, - PurpleCipherBatchMode batch_mode); - -static void -purple_aes_cipher_reset(PurpleCipher *cipher) -{ - PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); - - g_return_if_fail(priv != NULL); - - memset(priv->iv, 0, sizeof(priv->iv)); - memset(priv->key, 0, sizeof(priv->key)); - priv->key_size = 32; /* 256bit */ - priv->failure = FALSE; -} - -static void -purple_aes_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) -{ - PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); - - if ((len > 0 && iv == NULL) || - (len != 0 && len != sizeof(priv->iv))) { - purple_debug_error("cipher-aes", "invalid IV length\n"); - priv->failure = TRUE; - return; - } - - if (len == 0) - memset(priv->iv, 0, sizeof(priv->iv)); - else - memcpy(priv->iv, iv, len); - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_IV]); -} - -static void -purple_aes_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) -{ - PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); - - if ((len > 0 && key == NULL) || - (len != 0 && len != 16 && len != 24 && len != 32)) { - purple_debug_error("cipher-aes", "invalid key length\n"); - priv->failure = TRUE; - return; - } - - priv->key_size = len; - memset(priv->key, 0, sizeof(priv->key)); - if (len > 0) - memcpy(priv->key, key, len); - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_KEY]); -} - -static guchar * -purple_aes_cipher_pad_pkcs7(const guchar input[], size_t in_len, size_t *out_len) -{ - int padding_len, total_len; - guchar *padded; - - g_return_val_if_fail(input != NULL, NULL); - g_return_val_if_fail(out_len != NULL, NULL); - - padding_len = PURPLE_AES_BLOCK_SIZE - (in_len % PURPLE_AES_BLOCK_SIZE); - total_len = in_len + padding_len; - g_assert((total_len % PURPLE_AES_BLOCK_SIZE) == 0); - - padded = g_new(guchar, total_len); - *out_len = total_len; - - memcpy(padded, input, in_len); - memset(padded + in_len, padding_len, padding_len); - - return padded; -} - -static ssize_t -purple_aes_cipher_unpad_pkcs7(guchar input[], size_t in_len) -{ - guchar padding_len, i; - size_t out_len; - - g_return_val_if_fail(input != NULL, -1); - g_return_val_if_fail(in_len > 0, -1); - - padding_len = input[in_len - 1]; - if (padding_len == 0 || padding_len > PURPLE_AES_BLOCK_SIZE || - padding_len > in_len) { - purple_debug_warning("cipher-aes", - "Invalid padding length: %d (total %" G_GSIZE_FORMAT ") - " - "most probably, the key was invalid\n", - padding_len, in_len); - return -1; - } - - out_len = in_len - padding_len; - for (i = 0; i < padding_len; i++) { - if (input[out_len + i] != padding_len) { - purple_debug_warning("cipher-aes", - "Padding doesn't match at pos %d (found %02x, " - "expected %02x) - " - "most probably, the key was invalid\n", - i, input[out_len + i], padding_len); - return -1; - } - } - - memset(input + out_len, 0, padding_len); - return out_len; -} - -#ifdef PURPLE_AES_USE_GNUTLS - -static gnutls_cipher_hd_t -purple_aes_cipher_gnutls_crypt_init(guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], - guint key_size) -{ - gnutls_cipher_hd_t handle; - gnutls_cipher_algorithm_t algorithm; - gnutls_datum_t key_info, iv_info; - int ret; - - if (key_size == 16) - algorithm = GNUTLS_CIPHER_AES_128_CBC; - else if (key_size == 24) - algorithm = GNUTLS_CIPHER_AES_192_CBC; - else if (key_size == 32) - algorithm = GNUTLS_CIPHER_AES_256_CBC; - else - g_return_val_if_reached(NULL); - - key_info.data = key; - key_info.size = key_size; - - iv_info.data = iv; - iv_info.size = PURPLE_AES_BLOCK_SIZE; - - ret = gnutls_cipher_init(&handle, algorithm, &key_info, &iv_info); - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_init failed: %d\n", ret); - return NULL; - } - - return handle; -} - -static gboolean -purple_aes_cipher_gnutls_encrypt(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, - PurpleCipherBatchMode batch_mode) -{ - gnutls_cipher_hd_t handle; - int ret; - - /* We have to simulate ECB mode, which is not supported by GnuTLS. */ - if (batch_mode == PURPLE_CIPHER_BATCH_MODE_ECB) { - size_t i; - for (i = 0; i < len / PURPLE_AES_BLOCK_SIZE; i++) { - int offset = i * PURPLE_AES_BLOCK_SIZE; - guchar iv_local[PURPLE_AES_BLOCK_SIZE]; - gboolean succ; - - memcpy(iv_local, iv, sizeof(iv_local)); - succ = purple_aes_cipher_gnutls_encrypt( - input + offset, output + offset, - PURPLE_AES_BLOCK_SIZE, - iv_local, key, key_size, - PURPLE_CIPHER_BATCH_MODE_CBC); - if (!succ) - return FALSE; - } - return TRUE; - } - - handle = purple_aes_cipher_gnutls_crypt_init(iv, key, key_size); - if (handle == NULL) - return FALSE; - - ret = gnutls_cipher_encrypt2(handle, (guchar *)input, len, output, len); - gnutls_cipher_deinit(handle); - - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_encrypt2 failed: %d\n", ret); - return FALSE; - } - - return TRUE; -} - -static gboolean -purple_aes_cipher_gnutls_decrypt(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, - PurpleCipherBatchMode batch_mode) -{ - gnutls_cipher_hd_t handle; - int ret; - - /* We have to simulate ECB mode, which is not supported by GnuTLS. */ - if (batch_mode == PURPLE_CIPHER_BATCH_MODE_ECB) { - size_t i; - for (i = 0; i < len / PURPLE_AES_BLOCK_SIZE; i++) { - int offset = i * PURPLE_AES_BLOCK_SIZE; - guchar iv_local[PURPLE_AES_BLOCK_SIZE]; - gboolean succ; - - memcpy(iv_local, iv, sizeof(iv_local)); - succ = purple_aes_cipher_gnutls_decrypt( - input + offset, output + offset, - PURPLE_AES_BLOCK_SIZE, - iv_local, key, key_size, - PURPLE_CIPHER_BATCH_MODE_CBC); - if (!succ) - return FALSE; - } - return TRUE; - } - - handle = purple_aes_cipher_gnutls_crypt_init(iv, key, key_size); - if (handle == NULL) - return FALSE; - - ret = gnutls_cipher_decrypt2(handle, input, len, output, len); - gnutls_cipher_deinit(handle); - - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_decrypt2 failed: %d\n", ret); - return FALSE; - } - - return TRUE; -} - -#elif defined(PURPLE_AES_USE_NSS) - -typedef struct { - PK11SlotInfo *slot; - PK11SymKey *sym_key; - SECItem *sec_param; - PK11Context *enc_context; -} PurpleAESCipherNSSContext; - -static void -purple_aes_cipher_nss_cleanup(PurpleAESCipherNSSContext *context) -{ - g_return_if_fail(context != NULL); - - if (context->enc_context != NULL) - PK11_DestroyContext(context->enc_context, TRUE); - if (context->sec_param != NULL) - SECITEM_FreeItem(context->sec_param, TRUE); - if (context->sym_key != NULL) - PK11_FreeSymKey(context->sym_key); - if (context->slot != NULL) - PK11_FreeSlot(context->slot); - - memset(context, 0, sizeof(PurpleAESCipherNSSContext)); -} - -static gboolean -purple_aes_cipher_nss_crypt(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, - CK_ATTRIBUTE_TYPE operation, CK_MECHANISM_TYPE cipher_mech) -{ - PurpleAESCipherNSSContext context; - SECItem key_item, iv_item; - SECStatus ret; - int outlen = 0; - unsigned int outlen_tmp = 0; - - memset(&context, 0, sizeof(PurpleAESCipherNSSContext)); - - if (NSS_NoDB_Init(NULL) != SECSuccess) { - purple_debug_error("cipher-aes", - "NSS_NoDB_Init failed: %d\n", PR_GetError()); - return FALSE; - } - - context.slot = PK11_GetBestSlot(cipher_mech, NULL); - if (context.slot == NULL) { - purple_debug_error("cipher-aes", - "PK11_GetBestSlot failed: %d\n", PR_GetError()); - return FALSE; - } - - key_item.type = siBuffer; - key_item.data = key; - key_item.len = key_size; - context.sym_key = PK11_ImportSymKey(context.slot, cipher_mech, - PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); - if (context.sym_key == NULL) { - purple_debug_error("cipher-aes", - "PK11_ImportSymKey failed: %d\n", PR_GetError()); - purple_aes_cipher_nss_cleanup(&context); - return FALSE; - } - - iv_item.type = siBuffer; - iv_item.data = iv; - iv_item.len = PURPLE_AES_BLOCK_SIZE; - context.sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); - if (context.sec_param == NULL) { - purple_debug_error("cipher-aes", - "PK11_ParamFromIV failed: %d\n", PR_GetError()); - purple_aes_cipher_nss_cleanup(&context); - return FALSE; - } - - context.enc_context = PK11_CreateContextBySymKey(cipher_mech, operation, - context.sym_key, context.sec_param); - if (context.enc_context == NULL) { - purple_debug_error("cipher-aes", - "PK11_CreateContextBySymKey failed: %d\n", - PR_GetError()); - purple_aes_cipher_nss_cleanup(&context); - return FALSE; - } - - ret = PK11_CipherOp(context.enc_context, output, &outlen, len, - (guchar *)input, len); - if (ret != SECSuccess) { - purple_debug_error("cipher-aes", - "PK11_CipherOp failed: %d\n", PR_GetError()); - purple_aes_cipher_nss_cleanup(&context); - return FALSE; - } - - ret = PK11_DigestFinal(context.enc_context, output + outlen, &outlen_tmp, - len - outlen); - if (ret != SECSuccess) { - purple_debug_error("cipher-aes", - "PK11_DigestFinal failed: %d\n", PR_GetError()); - purple_aes_cipher_nss_cleanup(&context); - return FALSE; - } - - purple_aes_cipher_nss_cleanup(&context); - - outlen += outlen_tmp; - if (outlen != (int)len) { - purple_debug_error("cipher-aes", - "resulting length doesn't match: %d (expected: %" - G_GSIZE_FORMAT ")\n", outlen, len); - return FALSE; - } - - return TRUE; -} - -static CK_MECHANISM_TYPE -purple_aes_cipher_nss_batch_mode(PurpleCipherBatchMode batch_mode) -{ - switch (batch_mode) { - case PURPLE_CIPHER_BATCH_MODE_CBC: - return CKM_AES_CBC; - case PURPLE_CIPHER_BATCH_MODE_ECB: - return CKM_AES_ECB; - } - - return CKM_AES_CBC; -} - -static gboolean -purple_aes_cipher_nss_encrypt(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, - PurpleCipherBatchMode batch_mode) -{ - return purple_aes_cipher_nss_crypt(input, output, len, iv, key, key_size, - CKA_ENCRYPT, purple_aes_cipher_nss_batch_mode(batch_mode)); -} - -static gboolean -purple_aes_cipher_nss_decrypt(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, - PurpleCipherBatchMode batch_mode) -{ - return purple_aes_cipher_nss_crypt(input, output, len, iv, key, key_size, - CKA_DECRYPT, purple_aes_cipher_nss_batch_mode(batch_mode)); -} - -#endif /* PURPLE_AES_USE_NSS */ - -static ssize_t -purple_aes_cipher_encrypt(PurpleCipher *cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); - purple_aes_cipher_crypt_func encrypt_func; - guchar *input_padded; - size_t out_len = 0; - gboolean succ; - - if (priv->failure) - return -1; - - input_padded = purple_aes_cipher_pad_pkcs7(input, in_len, &out_len); - - if (out_len > out_size) { - purple_debug_error("cipher-aes", "Output buffer too small (%" - G_GSIZE_FORMAT " > %" G_GSIZE_FORMAT ")", - out_len, out_size); - memset(input_padded, 0, out_len); - g_free(input_padded); - return -1; - } - -#if defined(PURPLE_AES_USE_GNUTLS) - encrypt_func = purple_aes_cipher_gnutls_encrypt; -#elif defined(PURPLE_AES_USE_NSS) - encrypt_func = purple_aes_cipher_nss_encrypt; -#else - purple_debug_error("cipher-aes", "No matching encrypt_func\n"); - return -1; -#endif - - succ = encrypt_func(input_padded, output, out_len, priv->iv, - priv->key, priv->key_size, priv->batch_mode); - - memset(input_padded, 0, out_len); - g_free(input_padded); - - if (!succ) { - memset(output, 0, out_len); - return -1; - } - - return out_len; -} - -static ssize_t -purple_aes_cipher_decrypt(PurpleCipher *cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); - purple_aes_cipher_crypt_func decrypt_func; - gboolean succ; - ssize_t out_len; - - if (priv->failure) - return -1; - - if (in_len > out_size) { - purple_debug_error("cipher-aes", "Output buffer too small\n"); - return -1; - } - - if ((in_len % PURPLE_AES_BLOCK_SIZE) != 0 || in_len == 0) { - purple_debug_error("cipher-aes", "Malformed data\n"); - return -1; - } - -#if defined(PURPLE_AES_USE_GNUTLS) - decrypt_func = purple_aes_cipher_gnutls_decrypt; -#elif defined(PURPLE_AES_USE_NSS) - decrypt_func = purple_aes_cipher_nss_decrypt; -#else - purple_debug_error("cipher-aes", "No matching decrypt_func\n"); - return -1; -#endif - - succ = decrypt_func(input, output, in_len, priv->iv, priv->key, - priv->key_size, priv->batch_mode); - - if (!succ) { - memset(output, 0, in_len); - return -1; - } - - out_len = purple_aes_cipher_unpad_pkcs7(output, in_len); - if (out_len < 0) { - memset(output, 0, in_len); - return -1; - } - - return out_len; -} - -static size_t -purple_aes_cipher_get_key_size(PurpleCipher *cipher) -{ - PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); - - return priv->key_size; -} - -static void -purple_aes_cipher_set_batch_mode(PurpleCipher *cipher, - PurpleCipherBatchMode mode) -{ - PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); - - if (mode != PURPLE_CIPHER_BATCH_MODE_CBC && - mode != PURPLE_CIPHER_BATCH_MODE_ECB) - { - purple_debug_error("cipher-aes", "unsupported batch mode\n"); - priv->failure = TRUE; - } - - priv->batch_mode = mode; - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_BATCH_MODE]); -} - -static PurpleCipherBatchMode -purple_aes_cipher_get_batch_mode(PurpleCipher *cipher) -{ - PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); - - return priv->batch_mode; -} - -static size_t -purple_aes_cipher_get_block_size(PurpleCipher *cipher) -{ - return PURPLE_AES_BLOCK_SIZE; -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ -static void -purple_aes_cipher_get_property(GObject *obj, guint param_id, GValue *value, - GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - - switch(param_id) { - case PROP_BATCH_MODE: - g_value_set_enum(value, - purple_cipher_get_batch_mode(cipher)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_aes_cipher_set_property(GObject *obj, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - - switch(param_id) { - case PROP_BATCH_MODE: - purple_cipher_set_batch_mode(cipher, - g_value_get_enum(value)); - break; - case PROP_IV: - { - guchar *iv = (guchar *)g_value_get_string(value); - purple_cipher_set_iv(cipher, iv, strlen((gchar*)iv)); - } - break; - case PROP_KEY: - purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), - purple_aes_cipher_get_key_size(cipher)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_aes_cipher_class_init(PurpleAESCipherClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); - - obj_class->get_property = purple_aes_cipher_get_property; - obj_class->set_property = purple_aes_cipher_set_property; - - cipher_class->reset = purple_aes_cipher_reset; - cipher_class->set_iv = purple_aes_cipher_set_iv; - cipher_class->encrypt = purple_aes_cipher_encrypt; - cipher_class->decrypt = purple_aes_cipher_decrypt; - cipher_class->set_key = purple_aes_cipher_set_key; - cipher_class->get_key_size = purple_aes_cipher_get_key_size; - cipher_class->set_batch_mode = purple_aes_cipher_set_batch_mode; - cipher_class->get_batch_mode = purple_aes_cipher_get_batch_mode; - cipher_class->get_block_size = purple_aes_cipher_get_block_size; - - g_type_class_add_private(klass, sizeof(PurpleAESCipherPrivate)); - - properties[PROP_BATCH_MODE] = g_param_spec_enum("batch-mode", - "batch-mode", "batch-mode", PURPLE_TYPE_CIPHER_BATCH_MODE, - PURPLE_CIPHER_BATCH_MODE_CBC, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); - - properties[PROP_IV] = g_param_spec_string("iv", "iv", "iv", NULL, - G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); - - properties[PROP_KEY] = g_param_spec_string("key", "key", "key", NULL, - G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(obj_class, PROP_LAST, properties); -} - -static void -purple_aes_cipher_init(PurpleCipher *cipher) { - purple_cipher_reset(cipher); -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_aes_cipher_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleAESCipherClass), - NULL, - NULL, - (GClassInitFunc)purple_aes_cipher_class_init, - NULL, - NULL, - sizeof(PurpleAESCipher), - 0, - (GInstanceInitFunc)purple_aes_cipher_init, - NULL - }; - - type = g_type_register_static(PURPLE_TYPE_CIPHER, - "PurpleAESCipher", - &info, 0); - } - - return type; -} - -PurpleCipher * -purple_aes_cipher_new(void) { - return g_object_new(PURPLE_TYPE_AES_CIPHER, NULL); -}
--- a/libpurple/ciphers/aescipher.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef PURPLE_AES_CIPHER_H -#define PURPLE_AES_CIPHER_H -/** - * SECTION:aescipher - * @section_id: libpurple-aescipher - * @short_description: <filename>ciphers/aescipher.h</filename> - * @title: AES Cipher - */ - -#include "cipher.h" - -#define PURPLE_TYPE_AES_CIPHER (purple_aes_cipher_get_type()) -#define PURPLE_AES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipher)) -#define PURPLE_AES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherClass)) -#define PURPLE_IS_AES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_AES_CIPHER)) -#define PURPLE_IS_AES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_AES_CIPHER)) -#define PURPLE_AES_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherClass)) - -typedef struct _PurpleAESCipher PurpleAESCipher; -typedef struct _PurpleAESCipherClass PurpleAESCipherClass; - -struct _PurpleAESCipher { - PurpleCipher gparent; -}; - -struct _PurpleAESCipherClass { - PurpleCipherClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_aes_cipher_get_type(void); - -PurpleCipher *purple_aes_cipher_new(void); - -G_END_DECLS - -#endif /* PURPLE_AES_CIPHER_H */
--- a/libpurple/ciphers/des3cipher.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,524 +0,0 @@ -/* - * Original des taken from gpg - * - * des.c - Triple-DES encryption/decryption Algorithm - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * Please see below for more legal information! - * - * According to the definition of DES in FIPS PUB 46-2 from December 1993. - * For a description of triple encryption, see: - * Bruce Schneier: Applied Cryptography. Second Edition. - * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "internal.h" -#include "glibcompat.h" - -#include "des3cipher.h" -#include "descipher.h" -#include "enums.h" - -#include <string.h> - -/****************************************************************************** - * Structs - *****************************************************************************/ - -#define PURPLE_DES3_CIPHER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherPrivate)) - -typedef struct _PurpleDES3CipherPrivate PurpleDES3CipherPrivate; -struct _PurpleDES3CipherPrivate -{ - PurpleCipherBatchMode mode; - guchar iv[8]; - /* First key for encryption */ - PurpleCipher *key1; - /* Second key for decryption */ - PurpleCipher *key2; - /* Third key for encryption */ - PurpleCipher *key3; -}; - -/****************************************************************************** - * Enums - *****************************************************************************/ -enum { - PROP_NONE, - PROP_BATCH_MODE, - PROP_IV, - PROP_KEY, - PROP_LAST, -}; - -/****************************************************************************** - * Globals - *****************************************************************************/ -static GObjectClass *parent_class = NULL; -static GParamSpec *properties[PROP_LAST]; - -/****************************************************************************** - * Cipher Stuff - *****************************************************************************/ - -static size_t -purple_des3_cipher_get_key_size(PurpleCipher *cipher) -{ - return 24; -} - -/* - * Fill a DES3 context with subkeys calculated from 3 64bit key. - * Does not check parity bits, but simply ignore them. - * Does not check for weak keys. - **/ -static void -purple_des3_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) -{ - PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - g_return_if_fail(len == 24); - - purple_cipher_set_key(PURPLE_CIPHER(priv->key1), key + 0, - purple_cipher_get_key_size(PURPLE_CIPHER(priv->key1))); - purple_cipher_set_key(PURPLE_CIPHER(priv->key2), key + 8, - purple_cipher_get_key_size(PURPLE_CIPHER(priv->key2))); - purple_cipher_set_key(PURPLE_CIPHER(priv->key3), key + 16, - purple_cipher_get_key_size(PURPLE_CIPHER(priv->key3))); - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_KEY]); -} - -static ssize_t -purple_des3_cipher_ecb_encrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - gsize out_len; - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), - input + offset, output + offset, 0); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), - output + offset, buf, 1); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), - buf, output + offset, 0); - - offset += 8; - } - - out_len = in_len; - if (offset < in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - while (tmp < in_len) { - buf[i++] = input[tmp]; - tmp++; - } - - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), - buf, output + offset, 0); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), - output + offset, buf, 1); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), - buf, output + offset, 0); - } - - return out_len; -} - -static ssize_t -purple_des3_cipher_cbc_encrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8]; - gsize out_len; - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - memcpy(buf, priv->iv, 8); - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - for (i = 0; i < 8; i++) - buf[i] ^= input[offset + i]; - - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), - buf, output + offset, 0); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), - output + offset, buf, 1); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), - buf, output + offset, 0); - - memcpy(buf, output+offset, 8); - offset += 8; - } - - out_len = in_len; - if (offset < in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - i = 0; - while (tmp < in_len) { - buf[i++] ^= input[tmp]; - tmp++; - } - - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), - buf, output + offset, 0); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), - output + offset, buf, 1); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), - buf, output + offset, 0); - } - - return out_len; -} - -static ssize_t -purple_des3_cipher_encrypt(PurpleCipher *cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - if (priv->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { - return purple_des3_cipher_ecb_encrypt(des3_cipher, input, in_len, output, out_size); - } else if (priv->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { - return purple_des3_cipher_cbc_encrypt(des3_cipher, input, in_len, output, out_size); - } else { - g_return_val_if_reached(0); - } - - return 0; -} - -static ssize_t -purple_des3_cipher_ecb_decrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - gsize out_len; - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - /* NOTE: Apply key in reverse */ - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), - input + offset, output + offset, 1); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), - output + offset, buf, 0); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), - buf, output + offset, 1); - - offset += 8; - } - - out_len = in_len; - if (offset < in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - while (tmp < in_len) { - buf[i++] = input[tmp]; - tmp++; - } - - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), - buf, output + offset, 1); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), - output + offset, buf, 0); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), - buf, output + offset, 1); - } - - return out_len; -} - -static ssize_t -purple_des3_cipher_cbc_decrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - guint8 link[8]; - gsize out_len; - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - g_return_val_if_fail(out_size >= in_len, -1); - - memcpy(link, priv->iv, 8); - while (offset + 8 <= in_len) { - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), - input + offset, output + offset, 1); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), - output + offset, buf, 0); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), - buf, output + offset, 1); - - for (i = 0; i < 8; i++) - output[offset + i] ^= link[i]; - - memcpy(link, input + offset, 8); - - offset+=8; - } - - out_len = in_len; - if(offset<in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - i = 0; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), - buf, output + offset, 1); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), - output + offset, buf, 0); - purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), - buf, output + offset, 1); - - for (i = 0; i < 8; i++) - output[offset + i] ^= link[i]; - } - - return out_len; -} - -static ssize_t -purple_des3_cipher_decrypt(PurpleCipher *cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(cipher); - - if (priv->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { - return purple_des3_cipher_ecb_decrypt(des3_cipher, input, in_len, output, out_size); - } else if (priv->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { - return purple_des3_cipher_cbc_decrypt(des3_cipher, input, in_len, output, out_size); - } else { - g_return_val_if_reached(0); - } - - return 0; -} - -static void -purple_des3_cipher_set_batch_mode(PurpleCipher *cipher, PurpleCipherBatchMode mode) -{ - PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - priv->mode = mode; - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_BATCH_MODE]); -} - -static PurpleCipherBatchMode -purple_des3_cipher_get_batch_mode(PurpleCipher *cipher) -{ - PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - return priv->mode; -} - -static void -purple_des3_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) -{ - PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - g_return_if_fail(len == 8); - - memcpy(priv->iv, iv, len); - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_IV]); -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ -static void -purple_des3_cipher_get_property(GObject *obj, guint param_id, GValue *value, - GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - - switch(param_id) { - case PROP_BATCH_MODE: - g_value_set_enum(value, - purple_cipher_get_batch_mode(cipher)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_des3_cipher_set_property(GObject *obj, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - - switch(param_id) { - case PROP_BATCH_MODE: - purple_cipher_set_batch_mode(cipher, - g_value_get_enum(value)); - break; - case PROP_IV: - { - guchar *iv = (guchar *)g_value_get_string(value); - purple_cipher_set_iv(cipher, iv, strlen((gchar*)iv)); - } - break; - case PROP_KEY: - purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), - purple_des3_cipher_get_key_size(cipher)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_des3_cipher_finalize(GObject *obj) -{ - PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(obj); - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - g_object_unref(G_OBJECT(priv->key1)); - g_object_unref(G_OBJECT(priv->key2)); - g_object_unref(G_OBJECT(priv->key3)); - - memset(priv->iv, 0, sizeof(priv->iv)); - - parent_class->finalize(obj); -} - -static void -purple_des3_cipher_class_init(PurpleDES3CipherClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - obj_class->finalize = purple_des3_cipher_finalize; - obj_class->get_property = purple_des3_cipher_get_property; - obj_class->set_property = purple_des3_cipher_set_property; - - cipher_class->set_iv = purple_des3_cipher_set_iv; - cipher_class->encrypt = purple_des3_cipher_encrypt; - cipher_class->decrypt = purple_des3_cipher_decrypt; - cipher_class->set_key = purple_des3_cipher_set_key; - cipher_class->set_batch_mode = purple_des3_cipher_set_batch_mode; - cipher_class->get_batch_mode = purple_des3_cipher_get_batch_mode; - cipher_class->get_key_size = purple_des3_cipher_get_key_size; - - g_type_class_add_private(klass, sizeof(PurpleDES3CipherPrivate)); - - properties[PROP_BATCH_MODE] = g_param_spec_enum("batch-mode", "batch-mode", - "batch-mode", PURPLE_TYPE_CIPHER_BATCH_MODE, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - properties[PROP_IV] = g_param_spec_string("iv", "iv", "iv", NULL, - G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); - - properties[PROP_KEY] = g_param_spec_string("key", "key", "key", NULL, - G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(obj_class, PROP_LAST, properties); -} - -static void -purple_des3_cipher_init(PurpleCipher *cipher) { - PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); - PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); - - priv->key1 = purple_des_cipher_new(); - priv->key2 = purple_des_cipher_new(); - priv->key3 = purple_des_cipher_new(); -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_des3_cipher_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleDES3CipherClass), - NULL, - NULL, - (GClassInitFunc)purple_des3_cipher_class_init, - NULL, - NULL, - sizeof(PurpleDES3Cipher), - 0, - (GInstanceInitFunc)purple_des3_cipher_init, - NULL - }; - - type = g_type_register_static(PURPLE_TYPE_CIPHER, - "PurpleDES3Cipher", - &info, 0); - } - - return type; -} - -PurpleCipher * -purple_des3_cipher_new(void) { - return g_object_new(PURPLE_TYPE_DES3_CIPHER, NULL); -}
--- a/libpurple/ciphers/des3cipher.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef PURPLE_DES3_CIPHER_H -#define PURPLE_DES3_CIPHER_H -/** - * SECTION:des3cipher - * @section_id: libpurple-des3cipher - * @short_description: <filename>ciphers/des3cipher.h</filename> - * @title: Triple-DES Cipher - */ - -#include "cipher.h" - -#define PURPLE_TYPE_DES3_CIPHER (purple_des3_cipher_get_type()) -#define PURPLE_DES3_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3Cipher)) -#define PURPLE_DES3_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherClass)) -#define PURPLE_IS_DES3_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_DES3_CIPHER)) -#define PURPLE_IS_DES3_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_DES3_CIPHER)) -#define PURPLE_DES3_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherClass)) - -typedef struct _PurpleDES3Cipher PurpleDES3Cipher; -typedef struct _PurpleDES3CipherClass PurpleDES3CipherClass; - -struct _PurpleDES3Cipher { - PurpleCipher gparent; -}; - -struct _PurpleDES3CipherClass { - PurpleCipherClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_des3_cipher_get_type(void); - -PurpleCipher *purple_des3_cipher_new(void); - -G_END_DECLS - -#endif /* PURPLE_DES3_CIPHER_H */ -
--- a/libpurple/ciphers/descipher.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,581 +0,0 @@ -/* - * Original des taken from gpg - * - * des.c - DES encryption/decryption Algorithm - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * Please see below for more legal information! - * - * According to the definition of DES in FIPS PUB 46-2 from December 1993. - * For a description of triple encryption, see: - * Bruce Schneier: Applied Cryptography. Second Edition. - * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "internal.h" -#include "glibcompat.h" - -#include "descipher.h" -#include "enums.h" - -#include <string.h> - -/****************************************************************************** - * Structs - *****************************************************************************/ -#define PURPLE_DES_CIPHER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherPrivate)) - -typedef struct { - guint32 encrypt_subkeys[32]; - guint32 decrypt_subkeys[32]; -} PurpleDESCipherPrivate; - -/****************************************************************************** - * Enums - *****************************************************************************/ -enum { - PROP_NONE, - PROP_KEY, - PROP_LAST, -}; - -/****************************************************************************** - * Globals - *****************************************************************************/ -static GObjectClass *parent_class = NULL; -static GParamSpec *properties[PROP_LAST]; - -/* - * The s-box values are permuted according to the 'primitive function P' - */ -static guint32 sbox1[64] = { - 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, - 0x00000002, 0x00008000, 0x00000200, 0x00808200, 0x00808202, 0x00000200, - 0x00800202, 0x00808002, 0x00800000, 0x00000002, 0x00000202, 0x00800200, - 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, - 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, - 0x00008202, 0x00800000, 0x00008000, 0x00808202, 0x00000002, 0x00808000, - 0x00808200, 0x00800000, 0x00800000, 0x00000200, 0x00808002, 0x00008000, - 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, - 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, - 0x00008202, 0x00808200, 0x00000202, 0x00800200, 0x00800200, 0x00000000, - 0x00008002, 0x00008200, 0x00000000, 0x00808002 -}; - -static guint32 sbox2[64] = { - 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, - 0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000, - 0x40004000, 0x00080000, 0x00000010, 0x40080010, 0x00084000, 0x00080010, - 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, - 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, - 0x40080000, 0x00004010, 0x00000000, 0x00084010, 0x40080010, 0x00080000, - 0x40004010, 0x40080000, 0x40084000, 0x00004000, 0x40080000, 0x40004000, - 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, - 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, - 0x40000010, 0x00080010, 0x00084000, 0x00000000, 0x40004000, 0x00004010, - 0x40000000, 0x40080010, 0x40084010, 0x00084000 -}; - -static guint32 sbox3[64] = { - 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, - 0x00010104, 0x04000100, 0x00010004, 0x04000004, 0x04000004, 0x00010000, - 0x04010104, 0x00010004, 0x04010000, 0x00000104, 0x04000000, 0x00000004, - 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, - 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, - 0x00000100, 0x04000000, 0x04010100, 0x04000000, 0x00010004, 0x00000104, - 0x00010000, 0x04010100, 0x04000100, 0x00000000, 0x00000100, 0x00010004, - 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, - 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, - 0x00010100, 0x04000004, 0x04010000, 0x04000104, 0x00000104, 0x04010000, - 0x00010104, 0x00000004, 0x04010004, 0x00010100 -}; - -static guint32 sbox4[64] = { - 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, - 0x80400000, 0x80001000, 0x00000000, 0x00401000, 0x00401000, 0x80401040, - 0x80000040, 0x00000000, 0x00400040, 0x80400000, 0x80000000, 0x00001000, - 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, - 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, - 0x80401040, 0x80000040, 0x00400040, 0x80400000, 0x00401000, 0x80401040, - 0x80000040, 0x00000000, 0x00000000, 0x00401000, 0x00001040, 0x00400040, - 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, - 0x00401040, 0x80400040, 0x80001000, 0x00001040, 0x00400000, 0x80401000, - 0x00000040, 0x00400000, 0x00001000, 0x00401040 -}; - -static guint32 sbox5[64] = { - 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, - 0x20000000, 0x01040000, 0x20040080, 0x00040000, 0x01000080, 0x20040080, - 0x21000080, 0x21040000, 0x00040080, 0x20000000, 0x01000000, 0x20040000, - 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, - 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, - 0x21000000, 0x00040080, 0x00040000, 0x21000080, 0x00000080, 0x01000000, - 0x20000000, 0x01040000, 0x21000080, 0x20040080, 0x01000080, 0x20000000, - 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, - 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, - 0x20040000, 0x21000000, 0x00040080, 0x01000080, 0x20000080, 0x00040000, - 0x00000000, 0x20040000, 0x01040080, 0x20000080 -}; - -static guint32 sbox6[64] = { - 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, - 0x10202008, 0x00200000, 0x10002000, 0x00202008, 0x00200000, 0x10000008, - 0x00200008, 0x10002000, 0x10000000, 0x00002008, 0x00000000, 0x00200008, - 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, - 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, - 0x10202000, 0x10000000, 0x10002000, 0x00000008, 0x10200008, 0x00202000, - 0x10202008, 0x00200000, 0x00002008, 0x10000008, 0x00200000, 0x10002000, - 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, - 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, - 0x10200000, 0x00202008, 0x00002000, 0x00200008, 0x10002008, 0x00000000, - 0x10202000, 0x10000000, 0x00200008, 0x10002008 -}; - -static guint32 sbox7[64] = { - 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, - 0x00100401, 0x02100400, 0x02100401, 0x00100000, 0x00000000, 0x02000001, - 0x00000001, 0x02000000, 0x02100001, 0x00000401, 0x02000400, 0x00100401, - 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, - 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, - 0x02000000, 0x00100400, 0x02000000, 0x00100400, 0x00100000, 0x02000401, - 0x02000401, 0x02100001, 0x02100001, 0x00000001, 0x00100001, 0x02000000, - 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, - 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, - 0x00000001, 0x02100401, 0x00000000, 0x00100401, 0x02100000, 0x00000400, - 0x02000001, 0x02000400, 0x00000400, 0x00100001 -}; - -static guint32 sbox8[64] = { - 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, - 0x00000020, 0x08000000, 0x00020020, 0x08020000, 0x08020820, 0x00020800, - 0x08020800, 0x00020820, 0x00000800, 0x00000020, 0x08020000, 0x08000020, - 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, - 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, - 0x00020820, 0x00020000, 0x00020820, 0x00020000, 0x08020800, 0x00000800, - 0x00000020, 0x08020020, 0x00000800, 0x00020820, 0x08000800, 0x00000020, - 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, - 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, - 0x08000820, 0x00000000, 0x08020820, 0x00020800, 0x00020800, 0x00000820, - 0x00000820, 0x00020020, 0x08000000, 0x08020800 -}; - -/* - * These two tables are part of the 'permuted choice 1' function. - * In this implementation several speed improvements are done. - */ -static guint32 leftkey_swap[16] = { - 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, - 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static guint32 rightkey_swap[16] = { - 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, - 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - -/* - * Numbers of left shifts per round for encryption subkey schedule - * To calculate the decryption key scheduling we just reverse the - * ordering of the subkeys so we can omit the table for decryption - * subkey schedule. - */ -static guint8 encrypt_rotate_tab[16] = { - 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 -}; - - -/****************************************************************************** - * Helpers - *****************************************************************************/ -/* - * Macro to swap bits across two words - */ -#define DO_PERMUTATION(a, temp, b, offset, mask) \ - temp = ((a>>offset) ^ b) & mask; \ - b ^= temp; \ - a ^= temp<<offset; - -/* - * This performs the 'initial permutation' for the data to be encrypted or - * decrypted - */ -#define INITIAL_PERMUTATION(left, temp, right) \ - DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ - DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ - DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ - DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ - DO_PERMUTATION(left, temp, right, 1, 0x55555555) - -/* - * The 'inverse initial permutation' - */ -#define FINAL_PERMUTATION(left, temp, right) \ - DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ - DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ - DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ - DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ - DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) - -/* - * A full DES round including 'expansion function', 'sbox substitution' - * and 'primitive function P' but without swapping the left and right word. - */ -#define DES_ROUND(from, to, work, subkey) \ - work = ((from<<1) | (from>>31)) ^ *subkey++; \ - to ^= sbox8[ work & 0x3f ]; \ - to ^= sbox6[ (work>>8) & 0x3f ]; \ - to ^= sbox4[ (work>>16) & 0x3f ]; \ - to ^= sbox2[ (work>>24) & 0x3f ]; \ - work = ((from>>3) | (from<<29)) ^ *subkey++; \ - to ^= sbox7[ work & 0x3f ]; \ - to ^= sbox5[ (work>>8) & 0x3f ]; \ - to ^= sbox3[ (work>>16) & 0x3f ]; \ - to ^= sbox1[ (work>>24) & 0x3f ]; - - -/* - * Macros to convert 8 bytes from/to 32bit words - */ -#define READ_64BIT_DATA(data, left, right) \ - left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ - right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; - -#define WRITE_64BIT_DATA(data, left, right) \ - data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ - data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ - data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ - data[6] = (right >> 8) &0xff; data[7] = right &0xff; - -/****************************************************************************** - * Cipher Stuff - *****************************************************************************/ -/* - * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for - * 16 encryption rounds. - * To calculate subkeys for decryption the caller - * have to reorder the generated subkeys. - * - * rawkey: 8 Bytes of key data - * subkey: Array of at least 32 guint32s. Will be filled - * with calculated subkeys. - * - */ -static void -purple_des_cipher_key_schedule(const guint8 * rawkey, guint32 * subkey) { - guint32 left, right, work; - int round; - - READ_64BIT_DATA (rawkey, left, right) - - DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) - DO_PERMUTATION (right, work, left, 0, 0x10101010) - - left = (leftkey_swap[(left >> 0) & 0xf] << 3) - | (leftkey_swap[(left >> 8) & 0xf] << 2) - | (leftkey_swap[(left >> 16) & 0xf] << 1) - | (leftkey_swap[(left >> 24) & 0xf] ) - | (leftkey_swap[(left >> 5) & 0xf] << 7) - | (leftkey_swap[(left >> 13) & 0xf] << 6) - | (leftkey_swap[(left >> 21) & 0xf] << 5) - | (leftkey_swap[(left >> 29) & 0xf] << 4); - - left &= 0x0fffffff; - - right = (rightkey_swap[(right >> 1) & 0xf] << 3) - | (rightkey_swap[(right >> 9) & 0xf] << 2) - | (rightkey_swap[(right >> 17) & 0xf] << 1) - | (rightkey_swap[(right >> 25) & 0xf] ) - | (rightkey_swap[(right >> 4) & 0xf] << 7) - | (rightkey_swap[(right >> 12) & 0xf] << 6) - | (rightkey_swap[(right >> 20) & 0xf] << 5) - | (rightkey_swap[(right >> 28) & 0xf] << 4); - - right &= 0x0fffffff; - - for (round = 0; round < 16; ++round) { - left = ((left << encrypt_rotate_tab[round]) | - (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; - right = ((right << encrypt_rotate_tab[round]) | - (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; - - *subkey++ = ((left << 4) & 0x24000000) - | ((left << 28) & 0x10000000) - | ((left << 14) & 0x08000000) - | ((left << 18) & 0x02080000) - | ((left << 6) & 0x01000000) - | ((left << 9) & 0x00200000) - | ((left >> 1) & 0x00100000) - | ((left << 10) & 0x00040000) - | ((left << 2) & 0x00020000) - | ((left >> 10) & 0x00010000) - | ((right >> 13) & 0x00002000) - | ((right >> 4) & 0x00001000) - | ((right << 6) & 0x00000800) - | ((right >> 1) & 0x00000400) - | ((right >> 14) & 0x00000200) - | (right & 0x00000100) - | ((right >> 5) & 0x00000020) - | ((right >> 10) & 0x00000010) - | ((right >> 3) & 0x00000008) - | ((right >> 18) & 0x00000004) - | ((right >> 26) & 0x00000002) - | ((right >> 24) & 0x00000001); - - *subkey++ = ((left << 15) & 0x20000000) - | ((left << 17) & 0x10000000) - | ((left << 10) & 0x08000000) - | ((left << 22) & 0x04000000) - | ((left >> 2) & 0x02000000) - | ((left << 1) & 0x01000000) - | ((left << 16) & 0x00200000) - | ((left << 11) & 0x00100000) - | ((left << 3) & 0x00080000) - | ((left >> 6) & 0x00040000) - | ((left << 15) & 0x00020000) - | ((left >> 4) & 0x00010000) - | ((right >> 2) & 0x00002000) - | ((right << 8) & 0x00001000) - | ((right >> 14) & 0x00000808) - | ((right >> 9) & 0x00000400) - | ((right) & 0x00000200) - | ((right << 7) & 0x00000100) - | ((right >> 7) & 0x00000020) - | ((right >> 3) & 0x00000011) - | ((right << 2) & 0x00000004) - | ((right >> 21) & 0x00000002); - } -} - -/* - * Fill a DES context with subkeys calculated from a 64bit key. - * Does not check parity bits, but simply ignore them. - * Does not check for weak keys. - */ -static void -purple_des_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { - PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); - PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher); - int i; - - g_return_if_fail(len == 8); - - purple_des_cipher_key_schedule(key, priv->encrypt_subkeys); - - for(i = 0; i < 32; i += 2) { - priv->decrypt_subkeys[i] = priv->encrypt_subkeys[30 - i]; - priv->decrypt_subkeys[i + 1] = priv->encrypt_subkeys[31 - i]; - } - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_KEY]); -} - -static size_t -purple_des_cipher_get_key_size(PurpleCipher *cipher) -{ - return 8; -} - -/* - * Electronic Codebook Mode DES encryption/decryption of data according to - * 'mode'. - */ -int -purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to, - int mode) -{ - guint32 left, right, work; - guint32 *keys; - PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher); - - keys = mode ? priv->decrypt_subkeys : - priv->encrypt_subkeys; - - READ_64BIT_DATA (from, left, right) - INITIAL_PERMUTATION (left, work, right) - - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - - FINAL_PERMUTATION (right, work, left) - WRITE_64BIT_DATA (to, right, left) - - return 0; -} - -static ssize_t -purple_des_cipher_encrypt(PurpleCipher *cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); - - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - gsize out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while(offset + 8 <= in_len) { - purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 0); - offset += 8; - } - - out_len = in_len; - - if(offset<in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - - purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 0); - } - - return out_len; -} - -static ssize_t -purple_des_cipher_decrypt(PurpleCipher *cipher, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); - - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - gsize out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while(offset + 8 <= in_len) { - purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 1); - offset += 8; - } - - out_len = in_len; - if(offset<in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - - purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 1); - } - - return out_len; -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ -static void -purple_des_cipher_set_property(GObject *obj, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - - switch(param_id) { - case PROP_KEY: - purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), - purple_des_cipher_get_key_size(cipher)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_des_cipher_class_init(PurpleDESCipherClass *klass) -{ - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - obj_class->set_property = purple_des_cipher_set_property; - - cipher_class->encrypt = purple_des_cipher_encrypt; - cipher_class->decrypt = purple_des_cipher_decrypt; - cipher_class->set_key = purple_des_cipher_set_key; - cipher_class->get_key_size = purple_des_cipher_get_key_size; - - g_type_class_add_private(klass, sizeof(PurpleDESCipherPrivate)); - - properties[PROP_KEY] = g_param_spec_string("key", "key", "key", NULL, - G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(obj_class, PROP_LAST, properties); -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_des_cipher_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - .class_size = sizeof(PurpleDESCipherClass), - .class_init = (GClassInitFunc)purple_des_cipher_class_init, - .instance_size = sizeof(PurpleDESCipher), - .instance_init = (GInstanceInitFunc)purple_cipher_reset, - }; - - type = g_type_register_static(PURPLE_TYPE_CIPHER, - "PurpleDESCipher", - &info, 0); - } - - return type; -} - -/** - * purple_des_cipher_new: - * - * Creates a new #PurpleCipher instance which implements the DES block cipher. - * - * Return Value: The new DES implementation of #PurpleCipher. - */ -PurpleCipher * -purple_des_cipher_new(void) { - return g_object_new(PURPLE_TYPE_DES_CIPHER, NULL); -}
--- a/libpurple/ciphers/descipher.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PURPLE_DES_CIPHER_H -#define PURPLE_DES_CIPHER_H -/** - * SECTION:descipher - * @section_id: libpurple-descipher - * @short_description: <filename>ciphers/descipher.h</filename> - * @title: DES Cipher - */ - -#include "cipher.h" - -#define PURPLE_TYPE_DES_CIPHER (purple_des_cipher_get_type()) -#define PURPLE_DES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipher)) -#define PURPLE_DES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherClass)) -#define PURPLE_IS_DES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_DES_CIPHER)) -#define PURPLE_IS_DES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_DES_CIPHER)) -#define PURPLE_DES_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherClass)) - -typedef struct _PurpleDESCipher PurpleDESCipher; -typedef struct _PurpleDESCipherClass PurpleDESCipherClass; - -struct _PurpleDESCipher { - PurpleCipher gparent; -}; - -struct _PurpleDESCipherClass { - PurpleCipherClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_des_cipher_get_type(void); - -PurpleCipher *purple_des_cipher_new(void); - -int purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to, int mode); - -G_END_DECLS - -#endif /* PURPLE_DES_CIPHER_H */
--- a/libpurple/ciphers/md4hash.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,311 +0,0 @@ -/* - * Original md4 taken from linux kernel - * MD4 Message Digest Algorithm (RFC1320). - * - * Implementation derived from Andrew Tridgell and Steve French's - * CIFS MD4 implementation, and the cryptoapi implementation - * originally based on the public domain implementation written - * by Colin Plumb in 1993. - * - * Copyright (c) Andrew Tridgell 1997-1998. - * Modified by Steve French (sfrench@us.ibm.com) 2002 - * Copyright (c) Cryptoapi developers. - * Copyright (c) 2002 David S. Miller (davem@redhat.com) - * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> - */ -#include "internal.h" -#include "md4hash.h" - -#include <string.h> - -#define MD4_DIGEST_SIZE 16 -#define MD4_BLOCK_WORDS 16 -#define MD4_HASH_WORDS 4 - -#define PURPLE_MD4_HASH_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4HashPrivate)) - -/****************************************************************************** - * Structs - *****************************************************************************/ -typedef struct { - guint32 hash[MD4_HASH_WORDS]; - guint32 block[MD4_BLOCK_WORDS]; - guint64 byte_count; -} PurpleMD4HashPrivate; - -/****************************************************************************** - * Globals - *****************************************************************************/ -static GObjectClass *parent_class = NULL; - -/****************************************************************************** - * Helpers - *****************************************************************************/ -#define ROUND1(a,b,c,d,k,s) \ - (a = lshift(a + F(b,c,d) + k, s)) - -#define ROUND2(a,b,c,d,k,s) \ - (a = lshift(a + G(b,c,d) + k + (guint32)0x5a827999,s)) - -#define ROUND3(a,b,c,d,k,s) \ - (a = lshift(a + H(b,c,d) + k + (guint32)0x6ed9eba1,s)) - -static inline guint32 -lshift(guint32 x, unsigned int s) { - x &= 0xffffffff; - return (((x << s) & 0xffffffff) | (x >> (32 - s))); -} - -static inline guint32 -F(guint32 x, guint32 y, guint32 z) { - return ((x & y) | ((~x) & z)); -} - -static inline guint32 -G(guint32 x, guint32 y, guint32 z) { - return ((x & y) | (x & z) | (y & z)); -} - -static inline guint32 -H(guint32 x, guint32 y, guint32 z) { - return (x ^ y ^ z); -} - -static inline void -le32_to_cpu_array(guint32 *buf, unsigned int words) { - while(words--) { - *buf = GUINT_FROM_LE(*buf); - buf++; - } -} - -static inline void -cpu_to_le32_array(guint32 *buf, unsigned int words) { - while(words--) { - *buf = GUINT_TO_LE(*buf); - buf++; - } -} - -static void -md4_transform(guint32 *hash, guint32 const *in) { - guint32 a, b, c, d; - - a = hash[0]; - b = hash[1]; - c = hash[2]; - d = hash[3]; - - ROUND1(a, b, c, d, in[0], 3); - ROUND1(d, a, b, c, in[1], 7); - ROUND1(c, d, a, b, in[2], 11); - ROUND1(b, c, d, a, in[3], 19); - ROUND1(a, b, c, d, in[4], 3); - ROUND1(d, a, b, c, in[5], 7); - ROUND1(c, d, a, b, in[6], 11); - ROUND1(b, c, d, a, in[7], 19); - ROUND1(a, b, c, d, in[8], 3); - ROUND1(d, a, b, c, in[9], 7); - ROUND1(c, d, a, b, in[10], 11); - ROUND1(b, c, d, a, in[11], 19); - ROUND1(a, b, c, d, in[12], 3); - ROUND1(d, a, b, c, in[13], 7); - ROUND1(c, d, a, b, in[14], 11); - ROUND1(b, c, d, a, in[15], 19); - - ROUND2(a, b, c, d,in[ 0], 3); - ROUND2(d, a, b, c, in[4], 5); - ROUND2(c, d, a, b, in[8], 9); - ROUND2(b, c, d, a, in[12], 13); - ROUND2(a, b, c, d, in[1], 3); - ROUND2(d, a, b, c, in[5], 5); - ROUND2(c, d, a, b, in[9], 9); - ROUND2(b, c, d, a, in[13], 13); - ROUND2(a, b, c, d, in[2], 3); - ROUND2(d, a, b, c, in[6], 5); - ROUND2(c, d, a, b, in[10], 9); - ROUND2(b, c, d, a, in[14], 13); - ROUND2(a, b, c, d, in[3], 3); - ROUND2(d, a, b, c, in[7], 5); - ROUND2(c, d, a, b, in[11], 9); - ROUND2(b, c, d, a, in[15], 13); - - ROUND3(a, b, c, d,in[ 0], 3); - ROUND3(d, a, b, c, in[8], 9); - ROUND3(c, d, a, b, in[4], 11); - ROUND3(b, c, d, a, in[12], 15); - ROUND3(a, b, c, d, in[2], 3); - ROUND3(d, a, b, c, in[10], 9); - ROUND3(c, d, a, b, in[6], 11); - ROUND3(b, c, d, a, in[14], 15); - ROUND3(a, b, c, d, in[1], 3); - ROUND3(d, a, b, c, in[9], 9); - ROUND3(c, d, a, b, in[5], 11); - ROUND3(b, c, d, a, in[13], 15); - ROUND3(a, b, c, d, in[3], 3); - ROUND3(d, a, b, c, in[11], 9); - ROUND3(c, d, a, b, in[7], 11); - ROUND3(b, c, d, a, in[15], 15); - - hash[0] += a; - hash[1] += b; - hash[2] += c; - hash[3] += d; -} - -static inline void -md4_transform_helper(PurpleHash *hash) { - PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); - - le32_to_cpu_array(priv->block, sizeof(priv->block) / sizeof(guint32)); - md4_transform(priv->hash, priv->block); -} - -/****************************************************************************** - * Hash Stuff - *****************************************************************************/ -static void -purple_md4_hash_reset(PurpleHash *hash) { - PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); - - priv->hash[0] = 0x67452301; - priv->hash[1] = 0xefcdab89; - priv->hash[2] = 0x98badcfe; - priv->hash[3] = 0x10325476; - - priv->byte_count = 0; - - memset(priv->block, 0, sizeof(priv->block)); -} - -static void -purple_md4_hash_append(PurpleHash *hash, const guchar *data, size_t len) { - PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); - const guint32 avail = sizeof(priv->block) - (priv->byte_count & 0x3f); - - priv->byte_count += len; - - if(avail > len) { - memcpy((char *)priv->block + - (sizeof(priv->block) - avail), - data, len); - return; - } - - memcpy((char *)priv->block + - (sizeof(priv->block) - avail), - data, avail); - - md4_transform_helper(hash); - data += avail; - len -= avail; - - while(len >= sizeof(priv->block)) { - memcpy(priv->block, data, sizeof(priv->block)); - md4_transform_helper(hash); - data += sizeof(priv->block); - len -= sizeof(priv->block); - } - - memcpy(priv->block, data, len); -} - -static gboolean -purple_md4_hash_digest(PurpleHash *hash, guchar *out, size_t len) -{ - PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); - const unsigned int offset = priv->byte_count & 0x3f; - gchar *p = (gchar *)priv->block + offset; - gint padding = 56 - (offset + 1); - - if(len < 16) - return FALSE; - - *p++ = 0x80; - - if(padding < 0) { - memset(p, 0x00, padding + sizeof(guint64)); - md4_transform_helper(hash); - p = (gchar *)priv->block; - padding = 56; - } - - memset(p, 0, padding); - priv->block[14] = priv->byte_count << 3; - priv->block[15] = priv->byte_count >> 29; - le32_to_cpu_array(priv->block, - (sizeof(priv->block) - sizeof(guint64)) / - sizeof(guint32)); - md4_transform(priv->hash, priv->block); - cpu_to_le32_array(priv->hash, sizeof(priv->hash) / sizeof(guint32)); - memcpy(out, priv->hash, sizeof(priv->hash)); - - return TRUE; -} - -static size_t -purple_md4_hash_get_digest_size(PurpleHash *hash) -{ - return 16; -} - -static size_t -purple_md4_hash_get_block_size(PurpleHash *hash) -{ - /* This does not change (in this case) */ - return 64; -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ -static void -purple_md4_hash_class_init(PurpleMD4HashClass *klass) { - PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - g_type_class_add_private(klass, sizeof(PurpleMD4HashPrivate)); - - hash_class->reset = purple_md4_hash_reset; - hash_class->reset_state = purple_md4_hash_reset; - hash_class->append = purple_md4_hash_append; - hash_class->digest = purple_md4_hash_digest; - hash_class->get_digest_size = purple_md4_hash_get_digest_size; - hash_class->get_block_size = purple_md4_hash_get_block_size; -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_md4_hash_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleMD4HashClass), - NULL, - NULL, - (GClassInitFunc)purple_md4_hash_class_init, - NULL, - NULL, - sizeof(PurpleMD4Hash), - 0, - (GInstanceInitFunc)purple_hash_reset, - NULL, - }; - - type = g_type_register_static(PURPLE_TYPE_HASH, - "PurpleMD4Hash", - &info, 0); - } - - return type; -} - -PurpleHash * -purple_md4_hash_new(void) { - return g_object_new(PURPLE_TYPE_MD4_HASH, NULL); -}
--- a/libpurple/ciphers/md4hash.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PURPLE_MD4_HASH_H -#define PURPLE_MD4_HASH_H -/** - * SECTION:md4hash - * @section_id: libpurple-md4hash - * @short_description: <filename>ciphers/md4hash.h</filename> - * @title: MD4 Hash - */ - -#include "cipher.h" - -#define PURPLE_TYPE_MD4_HASH (purple_md4_hash_get_type()) -#define PURPLE_MD4_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4Hash)) -#define PURPLE_MD4_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MD4_HASH, PurpleMD4HashClass)) -#define PURPLE_IS_MD4_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MD4_HASH)) -#define PURPLE_IS_MD4_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_MD4_HASH)) -#define PURPLE_MD4_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4HashClass)) - -typedef struct _PurpleMD4Hash PurpleMD4Hash; -typedef struct _PurpleMD4HashClass PurpleMD4HashClass; - -struct _PurpleMD4Hash { - PurpleHash parent; -}; - -struct _PurpleMD4HashClass { - PurpleHashClass parent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_md4_hash_get_type(void); - -PurpleHash *purple_md4_hash_new(void); - -G_END_DECLS - -#endif /* PURPLE_MD4_HASH_H */
--- a/libpurple/ciphers/pbkdf2cipher.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,392 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - * Written by Tomek Wasilczyk <twasilczyk@pidgin.im> - */ -#include "internal.h" -#include "glibcompat.h" - -#include "pbkdf2cipher.h" -#include "debug.h" - -/* 1024bit */ -#define PBKDF2_HASH_MAX_LEN 128 - -/****************************************************************************** - * Structs - *****************************************************************************/ -#define PURPLE_PBKDF2_CIPHER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherPrivate)) - -typedef struct { - GChecksumType hash_type; - guint iter_count; - size_t out_len; - - guchar *salt; - size_t salt_len; - guchar *passphrase; - size_t passphrase_len; -} PurplePBKDF2CipherPrivate; - -/****************************************************************************** - * Enums - *****************************************************************************/ -enum { - PROP_NONE, - PROP_HASH_TYPE, - PROP_ITER_COUNT, - PROP_OUT_LEN, - PROP_LAST, -}; - -/******************************************************************************* - * Globals - ******************************************************************************/ -static GObjectClass *parent_class = NULL; -static GParamSpec *properties[PROP_LAST]; - -/****************************************************************************** - * Cipher Stuff - *****************************************************************************/ -static void -purple_pbkdf2_cipher_reset(PurpleCipher *cipher) -{ - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - g_return_if_fail(priv != NULL); - - priv->iter_count = 1; - priv->out_len = 256; - - purple_cipher_reset_state(cipher); -} - -static void -purple_pbkdf2_cipher_reset_state(PurpleCipher *cipher) -{ - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - g_return_if_fail(priv != NULL); - - purple_cipher_set_salt(cipher, NULL, 0); - purple_cipher_set_key(cipher, NULL, 0); -} - -static size_t -purple_pbkdf2_cipher_get_digest_size(PurpleCipher *cipher) -{ - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - g_return_val_if_fail(priv != NULL, 0); - - return priv->out_len; -} - -static void -purple_pbkdf2_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len) -{ - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - g_return_if_fail(priv != NULL); - - g_free(priv->salt); - priv->salt = NULL; - priv->salt_len = 0; - - if (len == 0) - return; - g_return_if_fail(salt != NULL); - - priv->salt = g_memdup(salt, len); - priv->salt_len = len; -} - -static void -purple_pbkdf2_cipher_set_key(PurpleCipher *cipher, const guchar *key, - size_t len) -{ - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - g_return_if_fail(priv != NULL); - - if (priv->passphrase != NULL) { - memset(priv->passphrase, 0, priv->passphrase_len); - g_free(priv->passphrase); - priv->passphrase = NULL; - } - priv->passphrase_len = 0; - - if (len == 0) - return; - g_return_if_fail(key != NULL); - - priv->passphrase = g_memdup(key, len); - priv->passphrase_len = len; -} - -/* inspired by gnutls 3.1.10, pbkdf2-sha1.c */ -static gboolean -purple_pbkdf2_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len) -{ - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - guchar halfkey[PBKDF2_HASH_MAX_LEN], halfkey_hash[PBKDF2_HASH_MAX_LEN]; - guint halfkey_count, halfkey_pad, halfkey_no; - gsize halfkey_len; - guchar *salt_ext; - size_t salt_ext_len; - guint iter_no; - - g_return_val_if_fail(priv != NULL, FALSE); - g_return_val_if_fail(digest != NULL, FALSE); - g_return_val_if_fail(len >= priv->out_len, FALSE); - - g_return_val_if_fail(priv->iter_count > 0, FALSE); - g_return_val_if_fail(priv->passphrase != NULL || - priv->passphrase_len == 0, FALSE); - g_return_val_if_fail(priv->salt != NULL || priv->salt_len == 0, - FALSE); - g_return_val_if_fail(priv->out_len > 0, FALSE); - g_return_val_if_fail(priv->out_len < 0xFFFFFFFFU, FALSE); - - salt_ext_len = priv->salt_len + 4; - - halfkey_len = g_checksum_type_get_length(priv->hash_type); - if (halfkey_len <= 0 || halfkey_len > PBKDF2_HASH_MAX_LEN) { - purple_debug_error("pbkdf2", "Unsupported hash function. " - "(digest size: %" G_GSIZE_FORMAT ")\n", halfkey_len); - return FALSE; - } - - halfkey_count = ((priv->out_len - 1) / halfkey_len) + 1; - halfkey_pad = priv->out_len - (halfkey_count - 1) * halfkey_len; - - salt_ext = g_new(guchar, salt_ext_len); - if (priv->salt_len > 0) - memcpy(salt_ext, priv->salt, priv->salt_len); - - for (halfkey_no = 1; halfkey_no <= halfkey_count; halfkey_no++) { - memset(halfkey, 0, halfkey_len); - - for (iter_no = 1; iter_no <= priv->iter_count; iter_no++) { - GHmac *hmac; - guint i; - - hmac = g_hmac_new(priv->hash_type, - (const guchar*)priv->passphrase, - priv->passphrase_len); - if (hmac == NULL) { - purple_debug_error("pbkdf2", - "Couldn't create new hmac cipher\n"); - g_free(salt_ext); - return FALSE; - } - - if (iter_no == 1) { - salt_ext[salt_ext_len - 4] = - (halfkey_no & 0xff000000) >> 24; - salt_ext[salt_ext_len - 3] = - (halfkey_no & 0x00ff0000) >> 16; - salt_ext[salt_ext_len - 2] = - (halfkey_no & 0x0000ff00) >> 8; - salt_ext[salt_ext_len - 1] = - (halfkey_no & 0x000000ff) >> 0; - - g_hmac_update(hmac, salt_ext, salt_ext_len); - } - else - g_hmac_update(hmac, halfkey_hash, halfkey_len); - - g_hmac_get_digest(hmac, halfkey_hash, &halfkey_len); - g_hmac_unref(hmac); - - for (i = 0; i < halfkey_len; i++) - halfkey[i] ^= halfkey_hash[i]; - } - - memcpy(digest + (halfkey_no - 1) * halfkey_len, halfkey, - (halfkey_no == halfkey_count) ? halfkey_pad : - halfkey_len); - } - - g_free(salt_ext); - - return TRUE; -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ -static void -purple_pbkdf2_cipher_get_property(GObject *obj, guint param_id, GValue *value, - GParamSpec *pspec) -{ - PurplePBKDF2Cipher *cipher = PURPLE_PBKDF2_CIPHER(obj); - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - switch(param_id) { - case PROP_HASH_TYPE: - g_value_set_int(value, priv->hash_type); - break; - case PROP_ITER_COUNT: - g_value_set_uint(value, priv->iter_count); - break; - case PROP_OUT_LEN: - g_value_set_uint(value, priv->out_len); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_pbkdf2_cipher_set_property(GObject *obj, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - switch(param_id) { - case PROP_HASH_TYPE: - priv->hash_type = g_value_get_int(value); - break; - case PROP_ITER_COUNT: - priv->iter_count = g_value_get_uint(value); - break; - case PROP_OUT_LEN: - priv->out_len = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_pbkdf2_cipher_finalize(GObject *obj) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - - purple_pbkdf2_cipher_reset(cipher); - - parent_class->finalize(obj); -} - -static void -purple_pbkdf2_cipher_class_init(PurplePBKDF2CipherClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - obj_class->finalize = purple_pbkdf2_cipher_finalize; - obj_class->get_property = purple_pbkdf2_cipher_get_property; - obj_class->set_property = purple_pbkdf2_cipher_set_property; - - cipher_class->reset = purple_pbkdf2_cipher_reset; - cipher_class->reset_state = purple_pbkdf2_cipher_reset_state; - cipher_class->digest = purple_pbkdf2_cipher_digest; - cipher_class->get_digest_size = purple_pbkdf2_cipher_get_digest_size; - cipher_class->set_salt = purple_pbkdf2_cipher_set_salt; - cipher_class->set_key = purple_pbkdf2_cipher_set_key; - - g_type_class_add_private(klass, sizeof(PurplePBKDF2CipherPrivate)); - - properties[PROP_HASH_TYPE] = g_param_spec_int("hash-type", "hash-type", "hash-type", - G_MININT, G_MAXINT, -1, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - properties[PROP_ITER_COUNT] = g_param_spec_uint("iter-count", "iter-count", - "iter-count", 0, - G_MAXUINT, 0, G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - properties[PROP_OUT_LEN] = g_param_spec_uint("out-len", "out-len", - "out-len", 0, - G_MAXUINT, 0, G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(obj_class, PROP_LAST, properties); -} - -static void -purple_pbkdf2_cipher_init(PurpleCipher *cipher) -{ - PurplePBKDF2CipherPrivate *priv = - PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - priv->hash_type = -1; - - purple_cipher_reset(cipher); -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_pbkdf2_cipher_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurplePBKDF2CipherClass), - NULL, - NULL, - (GClassInitFunc)purple_pbkdf2_cipher_class_init, - NULL, - NULL, - sizeof(PurplePBKDF2Cipher), - 0, - (GInstanceInitFunc)purple_pbkdf2_cipher_init, - NULL - }; - - type = g_type_register_static(PURPLE_TYPE_CIPHER, - "PurplePBKDF2Cipher", - &info, 0); - } - - return type; -} - -PurpleCipher * -purple_pbkdf2_cipher_new(GChecksumType hash_type) { - return g_object_new(PURPLE_TYPE_PBKDF2_CIPHER, - "hash-type", hash_type, - NULL); -} - -GChecksumType -purple_pbkdf2_cipher_get_hash_type(const PurplePBKDF2Cipher *cipher) { - PurplePBKDF2CipherPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_PBKDF2_CIPHER(cipher), -1); - - priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - if(priv) - return priv->hash_type; - - return -1; -}
--- a/libpurple/ciphers/pbkdf2cipher.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef PURPLE_PBKDF2_CIPHER_H -#define PURPLE_PBKDF2_CIPHER_H -/** - * SECTION:pbkdf2cipher - * @section_id: libpurple-pbkdf2cipher - * @short_description: <filename>ciphers/pbkdf2cipher.h</filename> - * @title: PBKDF2 Cipher - */ - -#include "cipher.h" - -#define PURPLE_TYPE_PBKDF2_CIPHER (purple_pbkdf2_cipher_get_type()) -#define PURPLE_PBKDF2_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2Cipher)) -#define PURPLE_PBKDF2_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherClass)) -#define PURPLE_IS_PBKDF2_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PBKDF2_CIPHER)) -#define PURPLE_IS_PBKDF2_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_PBKDF2_CIPHER)) -#define PURPLE_PBKDF2_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherClass)) - -typedef struct _PurplePBKDF2Cipher PurplePBKDF2Cipher; -typedef struct _PurplePBKDF2CipherClass PurplePBKDF2CipherClass; - -struct _PurplePBKDF2Cipher { - PurpleCipher gparent; -}; - -struct _PurplePBKDF2CipherClass { - PurpleCipherClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_pbkdf2_cipher_get_type(void); - -PurpleCipher *purple_pbkdf2_cipher_new(GChecksumType hash_type); - -GChecksumType purple_pbkdf2_cipher_get_hash_type(const PurplePBKDF2Cipher *cipher); - -G_END_DECLS - -#endif /* PURPLE_PBKDF2_CIPHER_H */ -
--- a/libpurple/ciphers/rc4cipher.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,262 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "internal.h" -#include "glibcompat.h" - -#include "rc4cipher.h" - -/******************************************************************************* - * Structs - ******************************************************************************/ -#define PURPLE_RC4_CIPHER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherPrivate)) - -typedef struct { - guchar state[256]; - guchar x; - guchar y; - gint key_len; -} PurpleRC4CipherPrivate; - -/****************************************************************************** - * Enums - *****************************************************************************/ -enum { - PROP_ZERO, - PROP_KEY_LEN, - PROP_KEY, - PROP_LAST, -}; - -/****************************************************************************** - * Globals - *****************************************************************************/ -static GObjectClass *parent_class = NULL; -static GParamSpec *properties[PROP_LAST]; - -/****************************************************************************** - * Cipher Stuff - *****************************************************************************/ -static void -purple_rc4_cipher_reset(PurpleCipher *cipher) { - PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); - PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); - guint i; - - for(i = 0; i < 256; i++) - priv->state[i] = i; - priv->x = 0; - priv->y = 0; - - /* default is 5 bytes (40bit key) */ - priv->key_len = 5; -} - -static void -purple_rc4_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { - PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); - PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); - guchar *state; - guchar temp_swap; - guchar x, y; - guint i; - - x = 0; - y = 0; - state = &priv->state[0]; - priv->key_len = len; - for(i = 0; i < 256; i++) - { - y = (key[x] + state[i] + y) % 256; - temp_swap = state[i]; - state[i] = state[y]; - state[y] = temp_swap; - x = (x + 1) % len; - } - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_KEY]); -} - -static ssize_t -purple_rc4_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); - guchar temp_swap; - guchar x, y, z; - guchar *state; - guint i; - PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); - - x = priv->x; - y = priv->y; - state = &priv->state[0]; - - for(i = 0; i < in_len; i++) - { - x = (x + 1) % 256; - y = (state[x] + y) % 256; - temp_swap = state[x]; - state[x] = state[y]; - state[y] = temp_swap; - z = state[x] + (state[y]) % 256; - output[i] = input[i] ^ state[z]; - } - priv->x = x; - priv->y = y; - - return in_len; -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ -static void -purple_rc4_cipher_set_property(GObject *obj, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj); - - switch(param_id) { - case PROP_KEY_LEN: - purple_rc4_cipher_set_key_len(rc4_cipher, g_value_get_int(value)); - break; - case PROP_KEY: - { - guchar *key = (guchar *)g_value_get_string(value); - purple_rc4_cipher_set_key(cipher, key, strlen((gchar *) key)); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_rc4_cipher_get_property(GObject *obj, guint param_id, GValue *value, - GParamSpec *pspec) -{ - PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj); - - switch(param_id) { - case PROP_KEY_LEN: - g_value_set_int(value, - purple_rc4_cipher_get_key_len(rc4_cipher)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_rc4_cipher_class_init(PurpleRC4CipherClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - obj_class->set_property = purple_rc4_cipher_set_property; - obj_class->get_property = purple_rc4_cipher_get_property; - - cipher_class->reset = purple_rc4_cipher_reset; - cipher_class->encrypt = purple_rc4_cipher_encrypt; - cipher_class->set_key = purple_rc4_cipher_set_key; - - g_type_class_add_private(klass, sizeof(PurpleRC4CipherPrivate)); - - properties[PROP_KEY_LEN] = g_param_spec_int("key-len", "key-len", "key-len", - G_MININT, G_MAXINT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - properties[PROP_KEY] = g_param_spec_string("key", "key", "key", NULL, - G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(obj_class, PROP_LAST, properties); -} - -static void -purple_rc4_cipher_init(PurpleCipher *cipher) { - purple_rc4_cipher_reset(cipher); -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_rc4_cipher_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleRC4CipherClass), - NULL, - NULL, - (GClassInitFunc)purple_rc4_cipher_class_init, - NULL, - NULL, - sizeof(PurpleRC4Cipher), - 0, - (GInstanceInitFunc)purple_rc4_cipher_init, - NULL, - }; - - type = g_type_register_static(PURPLE_TYPE_CIPHER, - "PurpleRC4Cipher", - &info, 0); - } - - return type; -} - -PurpleCipher * -purple_rc4_cipher_new(void) { - return g_object_new(PURPLE_TYPE_RC4_CIPHER, NULL); -} - -void -purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher, - gint key_len) -{ - PurpleRC4CipherPrivate *priv; - - g_return_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher)); - - priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); - priv->key_len = key_len; - - g_object_notify_by_pspec(G_OBJECT(rc4_cipher), properties[PROP_KEY_LEN]); -} - -gint -purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher) -{ - PurpleRC4CipherPrivate *priv; - - g_return_val_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher), 0); - - priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); - - return priv->key_len; -}
--- a/libpurple/ciphers/rc4cipher.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef PURPLE_RC4_CIPHER_H -#define PURPLE_RC4_CIPHER_H -/** - * SECTION:rc4cipher - * @section_id: libpurple-rc4cipher - * @short_description: <filename>ciphers/rc4cipher.h</filename> - * @title: RC4 Cipher - */ - -#include "cipher.h" - -#define PURPLE_TYPE_RC4_CIPHER (purple_rc4_cipher_get_type()) -#define PURPLE_RC4_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4Cipher)) -#define PURPLE_RC4_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherClass)) -#define PURPLE_IS_RC4_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_RC4_CIPHER)) -#define PURPLE_IS_RC4_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_RC4_CIPHER)) -#define PURPLE_RC4_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherClass)) - -typedef struct _PurpleRC4Cipher PurpleRC4Cipher; -typedef struct _PurpleRC4CipherClass PurpleRC4CipherClass; - -struct _PurpleRC4Cipher { - PurpleCipher gparent; -}; - -struct _PurpleRC4CipherClass { - PurpleCipherClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_rc4_cipher_get_type(void); - -PurpleCipher *purple_rc4_cipher_new(void); - -gint purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher); -void purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher, gint key_len); - -G_END_DECLS - -#endif /* PURPLE_RC4_CIPHER_H */ - -
--- a/libpurple/core.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/core.c Fri Jun 30 15:03:16 2017 +0300 @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include "internal.h" -#include "cipher.h" #include "cmds.h" #include "connection.h" #include "conversation.h"
--- a/libpurple/eventloop.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/eventloop.c Fri Jun 30 15:03:16 2017 +0300 @@ -21,69 +21,88 @@ #include "internal.h" #include "eventloop.h" -static PurpleEventLoopUiOps *eventloop_ui_ops = NULL; +#define PURPLE_GLIB_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) +#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) + +typedef struct _PurpleIOClosure { + PurpleInputFunction function; + guint result; + gpointer data; +} PurpleIOClosure; guint purple_timeout_add(guint interval, GSourceFunc function, gpointer data) { - PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops(); - - return ops->timeout_add(interval, function, data); + return g_timeout_add(interval, function, data); } guint purple_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data) { - PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops(); - - if (ops->timeout_add_seconds) - return ops->timeout_add_seconds(interval, function, data); - else - return ops->timeout_add(1000 * interval, function, data); + return g_timeout_add_seconds(interval, function, data); } gboolean purple_timeout_remove(guint tag) { - PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops(); + return g_source_remove(tag); +} + +static gboolean +purple_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) +{ + PurpleIOClosure *closure = data; + PurpleInputCondition purple_cond = 0; - return ops->timeout_remove(tag); + if (condition & PURPLE_GLIB_READ_COND) + purple_cond |= PURPLE_INPUT_READ; + if (condition & PURPLE_GLIB_WRITE_COND) + purple_cond |= PURPLE_INPUT_WRITE; + +#ifdef _WIN32 + if(!purple_cond) { + return TRUE; + } +#endif /* _WIN32 */ + + closure->function(closure->data, g_io_channel_unix_get_fd(source), + purple_cond); + + return TRUE; } guint purple_input_add(int source, PurpleInputCondition condition, PurpleInputFunction func, gpointer user_data) { - PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops(); + PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1); + GIOChannel *channel; + GIOCondition cond = 0; + + closure->function = func; + closure->data = user_data; + + if (condition & PURPLE_INPUT_READ) + cond |= PURPLE_GLIB_READ_COND; + if (condition & PURPLE_INPUT_WRITE) + cond |= PURPLE_GLIB_WRITE_COND; - return ops->input_add(source, condition, func, user_data); +#ifdef _WIN32 + channel = g_io_channel_win32_new_socket(source); +#else + channel = g_io_channel_unix_new(source); +#endif + + closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, + cond, purple_io_invoke, closure, g_free); + + g_io_channel_unref(channel); + return closure->result; } gboolean purple_input_remove(guint tag) { - PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops(); - - return ops->input_remove(tag); -} - -int -purple_input_get_error(int fd, int *error) -{ - PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops(); - - if (ops->input_get_error) - { - int ret = ops->input_get_error(fd, error); - errno = *error; - return ret; - } - else - { - socklen_t len; - len = sizeof(*error); - - return getsockopt(fd, SOL_SOCKET, SO_ERROR, error, &len); - } + return g_source_remove(tag); } int @@ -95,47 +114,3 @@ return pipe(pipefd); #endif } - -void -purple_eventloop_set_ui_ops(PurpleEventLoopUiOps *ops) -{ - eventloop_ui_ops = ops; -} - -PurpleEventLoopUiOps * -purple_eventloop_get_ui_ops(void) -{ - g_return_val_if_fail(eventloop_ui_ops != NULL, NULL); - - return eventloop_ui_ops; -} - -/************************************************************************** - * GBoxed code - **************************************************************************/ -static PurpleEventLoopUiOps * -purple_eventloop_ui_ops_copy(PurpleEventLoopUiOps *ops) -{ - PurpleEventLoopUiOps *ops_new; - - g_return_val_if_fail(ops != NULL, NULL); - - ops_new = g_new(PurpleEventLoopUiOps, 1); - *ops_new = *ops; - - return ops_new; -} - -GType -purple_eventloop_ui_ops_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - type = g_boxed_type_register_static("PurpleEventLoopUiOps", - (GBoxedCopyFunc)purple_eventloop_ui_ops_copy, - (GBoxedFreeFunc)g_free); - } - - return type; -}
--- a/libpurple/eventloop.h Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/eventloop.h Fri Jun 30 15:03:16 2017 +0300 @@ -31,8 +31,6 @@ #include <glib.h> #include <glib-object.h> -#define PURPLE_TYPE_EVENTLOOP_UI_OPS (purple_eventloop_ui_ops_get_type()) - /** * PurpleInputCondition: * @PURPLE_INPUT_READ: A read condition. @@ -57,99 +55,6 @@ */ typedef void (*PurpleInputFunction)(gpointer, gint, PurpleInputCondition); -typedef struct _PurpleEventLoopUiOps PurpleEventLoopUiOps; - -/** - * PurpleEventLoopUiOps: - * @timeout_add: Should create a callback timer with an interval measured in - * milliseconds. The supplied @function should be called every - * @interval seconds until it returns %FALSE, after which it - * should not be called again. - * <sbr/>Analogous to g_timeout_add in glib. - * <sbr/>Note: On Win32, this function may be called from a thread - * other than the libpurple thread. You should make sure to detect - * this situation and to only call "function" from the libpurple - * thread. - * <sbr/>See purple_timeout_add(). - * <sbr/>@interval: the interval in - * <emphasis>milliseconds</emphasis> between - * calls to @function. - * <sbr/>@data: arbitrary data to be passed to @function at each - * call. - * <sbr/>Returns: a handle for the timeout, which can be passed to - * @timeout_remove. - * @timeout_remove: Should remove a callback timer. Analogous to - * g_source_remove() in glib. - * <sbr/>See purple_timeout_remove(). - * <sbr/>@handle: an identifier for a timeout, as returned by - * @timeout_add. - * <sbr/>Returns: %TRUE if the timeout identified by @handle - * was found and removed. - * @input_add: Should add an input handler. Analogous to g_io_add_watch_full() - * in glib. - * <sbr/>See purple_input_add(). - * <sbr/>@fd: a file descriptor to watch for events - * <sbr/>@cond: a bitwise OR of events on @fd for which @func - * should be called. - * <sbr/>@func: a callback to fire whenever a relevant event on - * @fd occurs. - * <sbr/>@user_data: arbitrary data to pass to @fd. - * <sbr/>Returns: an identifier for this input handler, which can - * be passed to @input_remove. - * @input_remove: Should remove an input handler. Analogous to g_source_remove() - * in glib. - * <sbr/>See purple_input_remove(). - * <sbr/>@handle: an identifier, as returned by #input_add. - * <sbr/>Returns: %TRUE if the input handler was found and - * removed. - * @input_get_error: If implemented, should get the current error status for an - * input. - * <sbr/>Implementation of this UI op is optional. Implement - * it if the UI's sockets or event loop needs to customize - * determination of socket error status. If unimplemented, - * <literal>getsockopt(2)</literal> will be used instead. - * <sbr/>See purple_input_get_error(). - * @timeout_add_seconds: If implemented, should create a callback timer with an - * interval measured in seconds. Analogous to - * g_timeout_add_seconds() in glib. - * <sbr/>This allows UIs to group timers for better power - * efficiency. For this reason, @interval may be rounded - * by up to a second. - * <sbr/>Implementation of this UI op is optional. If it's - * not implemented, calls to purple_timeout_add_seconds() - * will be serviced by @timeout_add. - * <sbr/>See purple_timeout_add_seconds(). - * - * An abstraction of an application's mainloop; libpurple will use this to - * watch file descriptors and schedule timed callbacks. If your application - * uses the glib mainloop, there is an implementation of this struct in - * <filename>libpurple/example/nullclient.c</filename> which you can use - * verbatim. - */ -struct _PurpleEventLoopUiOps -{ - /* TODO Who is responsible for freeing @data? */ - guint (*timeout_add)(guint interval, GSourceFunc function, gpointer data); - - gboolean (*timeout_remove)(guint handle); - - guint (*input_add)(int fd, PurpleInputCondition cond, - PurpleInputFunction func, gpointer user_data); - - gboolean (*input_remove)(guint handle); - - int (*input_get_error)(int fd, int *error); - - guint (*timeout_add_seconds)(guint interval, GSourceFunc function, - gpointer data); - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - G_BEGIN_DECLS /**************************************************************************/ @@ -231,24 +136,6 @@ gboolean purple_input_remove(guint handle); /** - * purple_input_get_error: - * @fd: The input file descriptor. - * @error: A pointer to an #int which on return will have the error, or - * 0 if no error. - * - * Get the current error status for an input. - * - * The return value and error follow getsockopt() with a level of SOL_SOCKET and an - * option name of SO_ERROR, and this is how the error is determined if the UI does not - * implement the input_get_error UI op. - * - * Returns: 0 if there is no error; -1 if there is an error, in which case - * #errno will be set. - */ -int -purple_input_get_error(int fd, int *error); - -/** * purple_input_pipe: * @pipefd: Array used to return file descriptors for both ends of pipe. * @@ -267,36 +154,6 @@ int purple_input_pipe(int pipefd[2]); - - -/**************************************************************************/ -/* UI Registration Functions */ -/**************************************************************************/ - -/** - * purple_eventloop_ui_ops_get_type: - * - * Returns: The #GType for the #PurpleEventLoopUiOps boxed structure. - */ -GType purple_eventloop_ui_ops_get_type(void); - -/** - * purple_eventloop_set_ui_ops: - * @ops: The UI operations structure. - * - * Sets the UI operations structure to be used for accounts. - */ -void purple_eventloop_set_ui_ops(PurpleEventLoopUiOps *ops); - -/** - * purple_eventloop_get_ui_ops: - * - * Returns the UI operations structure used for accounts. - * - * Returns: The UI operations structure in use. - */ -PurpleEventLoopUiOps *purple_eventloop_get_ui_ops(void); - G_END_DECLS #endif /* _PURPLE_EVENTLOOP_H_ */
--- a/libpurple/example/nullclient.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/example/nullclient.c Fri Jun 30 15:03:16 2017 +0300 @@ -36,84 +36,6 @@ #include "defines.h" -/** - * The following eventloop functions are used in both pidgin and purple-text. If your - * application uses glib mainloop, you can safely use this verbatim. - */ -#define PURPLE_GLIB_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) -#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) - -typedef struct _PurpleGLibIOClosure { - PurpleInputFunction function; - guint result; - gpointer data; -} PurpleGLibIOClosure; - -static void purple_glib_io_destroy(gpointer data) -{ - g_free(data); -} - -static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) -{ - PurpleGLibIOClosure *closure = data; - PurpleInputCondition purple_cond = 0; - - if (condition & PURPLE_GLIB_READ_COND) - purple_cond |= PURPLE_INPUT_READ; - if (condition & PURPLE_GLIB_WRITE_COND) - purple_cond |= PURPLE_INPUT_WRITE; - - closure->function(closure->data, g_io_channel_unix_get_fd(source), - purple_cond); - - return TRUE; -} - -static guint glib_input_add(gint fd, PurpleInputCondition condition, - PurpleInputFunction function, gpointer data) -{ - PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1); - GIOChannel *channel; - GIOCondition cond = 0; - - closure->function = function; - closure->data = data; - - if (condition & PURPLE_INPUT_READ) - cond |= PURPLE_GLIB_READ_COND; - if (condition & PURPLE_INPUT_WRITE) - cond |= PURPLE_GLIB_WRITE_COND; - -#ifdef _WIN32 - channel = g_io_channel_win32_new_socket(fd); -#else - channel = g_io_channel_unix_new(fd); -#endif - closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, - cond, purple_glib_io_invoke, closure, purple_glib_io_destroy); - - g_io_channel_unref(channel); - return closure->result; -} - -static PurpleEventLoopUiOps glib_eventloops = -{ - g_timeout_add, - g_source_remove, - glib_input_add, - g_source_remove, - NULL, - g_timeout_add_seconds, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; -/*** End of the eventloop functions. ***/ - /*** Conversation uiops ***/ static void null_write_conv(PurpleConversation *conv, PurpleMessage *msg) @@ -189,10 +111,6 @@ */ purple_core_set_ui_ops(&null_core_uiops); - /* Set the uiops for the eventloop. If your client is glib-based, you can safely - * copy this verbatim. */ - purple_eventloop_set_ui_ops(&glib_eventloops); - /* Now that all the essential stuff has been set, let's try to init the core. It's * necessary to provide a non-NULL name for the current ui to the core. This name * is used by stuff that depends on this ui, for example the ui-specific plugins. */
--- a/libpurple/glibcompat.h Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/glibcompat.h Fri Jun 30 15:03:16 2017 +0300 @@ -63,6 +63,11 @@ #endif /* __clang__ */ + +#if !GLIB_CHECK_VERSION(2, 44, 0) +#define G_IO_ERROR_CONNECTION_CLOSED G_IO_ERROR_BROKEN_PIPE +#endif + /****************************************************************************** * g_assert_* macros *****************************************************************************/
--- a/libpurple/marshallers.list Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -VOID:POINTER,POINTER,OBJECT -BOOLEAN:OBJECT,POINTER,STRING -VOID:STRING,STRING -VOID:STRING,STRING,DOUBLE -VOID:ENUM,STRING,STRING -VOID:ENUM,STRING,STRING,BOOLEAN -VOID:FLAGS,FLAGS -VOID:STRING,STRING,OBJECT,OBJECT -BOOLEAN:OBJECT -VOID:POINTER,POINTER,OBJECT,OBJECT
--- a/libpurple/media.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/media.c Fri Jun 30 15:03:16 2017 +0300 @@ -29,7 +29,6 @@ #ifdef USE_GSTREAMER #include "media/backend-fs2.h" -#include "marshallers.h" #include "media-gst.h" #endif /* USE_GSTREAMER */ @@ -224,41 +223,33 @@ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); purple_media_signals[S_ERROR] = g_signal_new("error", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); purple_media_signals[CANDIDATES_PREPARED] = g_signal_new("candidates-prepared", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__STRING_STRING, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); purple_media_signals[CODECS_CHANGED] = g_signal_new("codecs-changed", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); purple_media_signals[LEVEL] = g_signal_new("level", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__STRING_STRING_DOUBLE, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_DOUBLE); purple_media_signals[NEW_CANDIDATE] = g_signal_new("new-candidate", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__POINTER_POINTER_OBJECT, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_POINTER, PURPLE_TYPE_MEDIA_CANDIDATE); purple_media_signals[STATE_CHANGED] = g_signal_new("state-changed", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__ENUM_STRING_STRING, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 3, PURPLE_MEDIA_TYPE_STATE, G_TYPE_STRING, G_TYPE_STRING); purple_media_signals[STREAM_INFO] = g_signal_new("stream-info", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__ENUM_STRING_STRING_BOOLEAN, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 4, PURPLE_MEDIA_TYPE_INFO_TYPE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); purple_media_signals[CANDIDATE_PAIR_ESTABLISHED] = g_signal_new("candidate-pair-established", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__POINTER_POINTER_OBJECT_OBJECT, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 4, G_TYPE_POINTER, G_TYPE_POINTER, PURPLE_TYPE_MEDIA_CANDIDATE, PURPLE_TYPE_MEDIA_CANDIDATE); g_type_class_add_private(klass, sizeof(PurpleMediaPrivate));
--- a/libpurple/media/backend-iface.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/media/backend-iface.c Fri Jun 30 15:03:16 2017 +0300 @@ -23,8 +23,6 @@ #include "backend-iface.h" -#include "marshallers.h" - enum { S_ERROR, CANDIDATES_PREPARED, @@ -67,34 +65,29 @@ G_PARAM_STATIC_STRINGS)); purple_media_backend_signals[S_ERROR] = g_signal_new("error", G_TYPE_FROM_CLASS(iface), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); purple_media_backend_signals[CANDIDATES_PREPARED] = g_signal_new("candidates-prepared", G_TYPE_FROM_CLASS(iface), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__STRING_STRING, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); purple_media_backend_signals[CODECS_CHANGED] = g_signal_new("codecs-changed", G_TYPE_FROM_CLASS(iface), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); purple_media_backend_signals[NEW_CANDIDATE] = g_signal_new("new-candidate", G_TYPE_FROM_CLASS(iface), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__POINTER_POINTER_OBJECT, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_POINTER, PURPLE_TYPE_MEDIA_CANDIDATE); purple_media_backend_signals[ACTIVE_CANDIDATE_PAIR] = g_signal_new("active-candidate-pair", G_TYPE_FROM_CLASS(iface), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - purple_smarshal_VOID__STRING_STRING_OBJECT_OBJECT, + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, PURPLE_TYPE_MEDIA_CANDIDATE, PURPLE_TYPE_MEDIA_CANDIDATE);
--- a/libpurple/mediamanager.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/mediamanager.c Fri Jun 30 15:03:16 2017 +0300 @@ -27,7 +27,6 @@ #include "mediamanager.h" #ifdef USE_GSTREAMER -#include "marshallers.h" #include "media-gst.h" #include <media/backend-fs2.h> #endif /* USE_GSTREAMER */ @@ -172,8 +171,7 @@ purple_media_manager_signals[INIT_MEDIA] = g_signal_new ("init-media", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - purple_smarshal_BOOLEAN__OBJECT_POINTER_STRING, + 0, NULL, NULL, NULL, G_TYPE_BOOLEAN, 3, PURPLE_TYPE_MEDIA, G_TYPE_POINTER, G_TYPE_STRING); @@ -181,16 +179,14 @@ g_signal_new ("init-private-media", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - purple_smarshal_BOOLEAN__OBJECT_POINTER_STRING, + 0, NULL, NULL, NULL, G_TYPE_BOOLEAN, 3, PURPLE_TYPE_MEDIA, G_TYPE_POINTER, G_TYPE_STRING); purple_media_manager_signals[UI_CAPS_CHANGED] = g_signal_new ("ui-caps-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - purple_smarshal_VOID__FLAGS_FLAGS, + 0, NULL, NULL, NULL, G_TYPE_NONE, 2, PURPLE_MEDIA_TYPE_CAPS, PURPLE_MEDIA_TYPE_CAPS); @@ -198,8 +194,7 @@ g_signal_new("elements-changed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, + 0, NULL, NULL, NULL, G_TYPE_NONE, 0); g_type_class_add_private(klass, sizeof(PurpleMediaManagerPrivate));
--- a/libpurple/plugins/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/plugins/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -11,8 +11,6 @@ autoaccept_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ buddynote_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ -caesarcipher_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ -caesarcipher_consumer_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ codeinline_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ debug_example_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ helloworld_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ @@ -44,8 +42,6 @@ statenotify.la noinst_LTLIBRARIES = \ - caesarcipher.la \ - caesarcipher_consumer.la \ codeinline.la \ debug_example.la \ helloworld.la \ @@ -58,8 +54,6 @@ autoaccept_la_SOURCES = autoaccept.c buddynote_la_SOURCES = buddynote.c -caesarcipher_la_SOURCES = caesarcipher.c caesarcipher.h -caesarcipher_consumer_la_SOURCES = caesarcipher_consumer.c codeinline_la_SOURCES = codeinline.c debug_example_la_SOURCES = debug_example.c helloworld_la_SOURCES = helloworld.c @@ -77,8 +71,6 @@ autoaccept_la_LIBADD = @PURPLE_LIBS@ buddynote_la_LIBADD = @PURPLE_LIBS@ -caesarcipher_la_LIBADD = @PURPLE_LIBS@ -caesarcipher_consumer_la_LIBADD = @PURPLE_LIBS@ codeinline_la_LIBADD = @PURPLE_LIBS@ idle_la_LIBADD = @PURPLE_LIBS@ joinpart_la_LIBADD = @PURPLE_LIBS@ @@ -128,11 +120,9 @@ $(GLIB_CFLAGS) \ $(GPLUGIN_CFLAGS) \ $(PLUGIN_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(NSS_CFLAGS) + $(DBUS_CFLAGS) -PLUGIN_LIBS = \ - $(NSS_LIBS) +PLUGIN_LIBS = # # This part allows people to build their own plugins in here.
--- a/libpurple/plugins/caesarcipher.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -/* - * An example plugin that demonstrates exporting of a cipher object - * type to be used in another plugin. - * - * This plugin only provides the CaesarCipher type. See caesarcipher_consumer - * plugin for its use. - * - * Copyright (C) 2013, Ankit Vani <a@nevitus.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02111-1301, USA. - */ - -/* When writing a third-party plugin, do not include libpurple's internal.h - * included below. This file is for internal libpurple use only. We're including - * it here for our own convenience. */ -#include "internal.h" - -/* This file defines PURPLE_PLUGINS and includes all the libpurple headers */ -#include <purple.h> - -#include "caesarcipher.h" - -#define CAESAR_CIPHER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), CAESAR_TYPE_CIPHER, CaesarCipherPrivate)) - -typedef struct { - gint8 offset; -} CaesarCipherPrivate; - -enum { - PROP_NONE, - PROP_OFFSET, - PROP_LAST, -}; - -/****************************************************************************** - * Cipher stuff - *****************************************************************************/ -static void -caesar_shift(const guchar input[], size_t in_len, guchar output[], gint8 offset) -{ - size_t i; - - for (i = 0; i < in_len; ++i) { - if (input[i] >= 'a' && input[i] <= 'z') - output[i] = (((input[i] - 'a') + offset + 26) % 26) + 'a'; - else if (input[i] >= 'A' && input[i] <= 'Z') - output[i] = (((input[i] - 'A') + offset + 26) % 26) + 'A'; - else - output[i] = input[i]; - } - - output[i] = '\0'; -} - -static void -caesar_cipher_set_offset(PurpleCipher *cipher, gint8 offset) -{ - CaesarCipherPrivate *priv = CAESAR_CIPHER_GET_PRIVATE(cipher); - - priv->offset = offset % 26; -} - -static ssize_t -caesar_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - CaesarCipherPrivate *priv = CAESAR_CIPHER_GET_PRIVATE(cipher); - - g_return_val_if_fail(out_size > in_len, -1); - - caesar_shift(input, in_len, output, priv->offset); - - return in_len; -} - -static ssize_t -caesar_cipher_decrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - CaesarCipherPrivate *priv = CAESAR_CIPHER_GET_PRIVATE(cipher); - - g_return_val_if_fail(out_size > in_len, -1); - - caesar_shift(input, in_len, output, -priv->offset); - - return in_len; -} - -static void -caesar_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) -{ - caesar_cipher_set_offset(cipher, len); -} - -/****************************************************************************** - * Object stuff - *****************************************************************************/ -static void -caesar_cipher_set_property(GObject *obj, guint param_id, const GValue *value, - GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - - switch(param_id) { - case PROP_OFFSET: - caesar_cipher_set_offset(cipher, g_value_get_schar(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -/* initialize the cipher object. used in PURPLE_DEFINE_TYPE. */ -static void -caesar_cipher_init(CaesarCipher *cipher) -{ - /* classic caesar cipher uses a shift of 3 */ - CAESAR_CIPHER_GET_PRIVATE(cipher)->offset = 3; -} - -/* initialize the cipher class. used in PURPLE_DEFINE_TYPE. */ -static void -caesar_cipher_class_init(PurpleCipherClass *klass) -{ - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - - obj_class->set_property = caesar_cipher_set_property; - g_type_class_add_private(obj_class, sizeof(CaesarCipherPrivate)); - - klass->encrypt = caesar_cipher_encrypt; - klass->decrypt = caesar_cipher_decrypt; - klass->set_key = caesar_cipher_set_key; - - g_object_class_install_property(obj_class, PROP_OFFSET, - g_param_spec_char("offset", "offset", - "The offset by which to shift alphabets", - -25, 25, 3, - G_PARAM_WRITABLE) - ); -} - -/* - * define the CaesarCipher type. this function defines - * caesar_cipher_get_type() and caesar_cipher_register_type(). - */ -PURPLE_DEFINE_TYPE(CaesarCipher, caesar_cipher, PURPLE_TYPE_CIPHER); - -G_MODULE_EXPORT PurpleCipher * -caesar_cipher_new(void) -{ - return g_object_new(CAESAR_TYPE_CIPHER, NULL); -} - -/****************************************************************************** - * Plugin stuff - *****************************************************************************/ -static PurplePluginInfo * -plugin_query(GError **error) -{ - const gchar * const authors[] = { - "Ankit Vani <a@nevitus.org>", - NULL - }; - - return purple_plugin_info_new( - "id", "core-caesarcipher", - "name", N_("Caesar Cipher Provider Example"), - "version", DISPLAY_VERSION, - "category", N_("Example"), - "summary", N_("An example plugin that demonstrates exporting of a " - "cipher type."), - "description", N_("An example plugin that demonstrates exporting of " - "a cipher object type to be used in another " - "plugin."), - "authors", authors, - "website", PURPLE_WEBSITE, - "abi-version", PURPLE_ABI_VERSION, - NULL - ); -} - -static gboolean -plugin_load(PurplePlugin *plugin, GError **error) -{ - /* register the CaesarCipher type in the type system */ - caesar_cipher_register_type(plugin); - - return TRUE; -} - -static gboolean -plugin_unload(PurplePlugin *plugin, GError **error) -{ - return TRUE; -} - -PURPLE_PLUGIN_INIT(caesarcipher, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/caesarcipher.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * An example plugin that demonstrates exporting of a cipher object - * type to be used in another plugin. - * - * Copyright (C) 2013, Ankit Vani <a@nevitus.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02111-1301, USA. - */ - -#ifndef _CAESAR_CIPHER_H_ -#define _CAESAR_CIPHER_H_ - -#include "cipher.h" - -#define CAESAR_TYPE_CIPHER (caesar_cipher_get_type()) -#define CAESAR_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), CAESAR_TYPE_CIPHER, CaesarCipher)) -#define CAESAR_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CAESAR_TYPE_CIPHER, CaesarCipherClass)) -#define CAESAR_IS_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), CAESAR_TYPE_CIPHER)) -#define CAESAR_IS_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), CAESAR_TYPE_CIPHER)) -#define CAESAR_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), CAESAR_TYPE_CIPHER, CaesarCipherClass)) - -typedef struct _CaesarCipher CaesarCipher; -typedef struct _CaesarCipherClass CaesarCipherClass; - -/* - * A caesar cipher object. - * - * The Caesar cipher is one of the simplest and most widely known encryption - * techniques. It is a type of substitution cipher in which each letter in the - * plaintext is replaced by a letter some fixed number of positions down the - * alphabet. - */ -struct _CaesarCipher -{ - PurpleCipher gparent; -}; - -/* The base class for all CaesarCipher's. */ -struct _CaesarCipherClass -{ - PurpleCipherClass gparent; -}; - -/* - * Returns the GType for the CaesarCipher object. - */ -G_MODULE_EXPORT GType caesar_cipher_get_type(void); - -/* - * Creates a new CaesarCipher instance and returns it. - */ -G_MODULE_EXPORT PurpleCipher *caesar_cipher_new(void); - -#endif /* _CAESAR_CIPHER_H_ */
--- a/libpurple/plugins/caesarcipher_consumer.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * An example plugin that demonstrates usage of a cipher object type - * registered in another plugin. - * - * This plugin requires the caesarcipher plugin to be loaded to use the - * CaesarCipher type. - * - * Copyright (C) 2013, Ankit Vani <a@nevitus.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02111-1301, USA. - */ - -/* When writing a third-party plugin, do not include libpurple's internal.h - * included below. This file is for internal libpurple use only. We're including - * it here for our own convenience. */ -#include "internal.h" - -/* This file defines PURPLE_PLUGINS and includes all the libpurple headers */ -#include <purple.h> - -#include "caesarcipher.h" - -static void -debug_cipher(PurpleCipher *cipher, const gchar *input) -{ - gchar ciphertext[512], plaintext[512]; - - purple_debug_info("caesarcipher_consumer", "Encrypting..."); - - purple_debug_info("caesarcipher_consumer", "INPUT: %s\n", input); - purple_cipher_encrypt(cipher, (const guchar *)input, strlen(input), - (guchar *)ciphertext, 512); - purple_debug_info("caesarcipher_consumer", "OUTPUT: %s\n", ciphertext); - - purple_debug_info("caesarcipher_consumer", "Decrypting..."); - - purple_debug_info("caesarcipher_consumer", "INPUT: %s\n", ciphertext); - purple_cipher_decrypt(cipher, (const guchar *)ciphertext, - strlen(ciphertext), (guchar *)plaintext, 512); - purple_debug_info("caesarcipher_consumer", "OUTPUT: %s\n", plaintext); -} - -static PurplePluginInfo * -plugin_query(GError **error) -{ - const gchar * const authors[] = { - "Ankit Vani <a@nevitus.org>", - NULL - }; - - /* we need to ensure the object provider is loaded for its type to be - * registered in the type system. */ - const gchar * const dependencies[] = { - "core-caesarcipher", - NULL - }; - - return purple_plugin_info_new( - "id", "core-caesarcipher_consumer", - "name", N_("Caesar Cipher Consumer Example"), - "version", DISPLAY_VERSION, - "category", N_("Example"), - "summary", N_("An example plugin that demonstrates usage of a " - "loaded cipher type."), - "description", N_("An example plugin that demonstrates usage of " - "a cipher object type registered in another " - "plugin."), - "authors", authors, - "website", PURPLE_WEBSITE, - "abi-version", PURPLE_ABI_VERSION, - "dependencies", dependencies, - - NULL - ); -} - -static gboolean -plugin_load(PurplePlugin *plugin, GError **error) -{ - PurpleCipher *cipher = caesar_cipher_new(); - purple_debug_info("caesarcipher_consumer", "Created caesar cipher " - "object.\n"); - - debug_cipher(cipher, "Input string for cipher!"); - - purple_cipher_set_key(cipher, NULL, 13); - purple_debug_info("caesarcipher_consumer", "Offset set to 13.\n"); - - debug_cipher(cipher, "An0ther input 4 cipher.."); - - g_object_unref(cipher); - purple_debug_info("caesarcipher_consumer", "Destroyed caesar cipher " - "object.\n"); - - return TRUE; -} - -static gboolean -plugin_unload(PurplePlugin *plugin, GError **error) -{ - return TRUE; -} - -PURPLE_PLUGIN_INIT(caesarcipher_consumer, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/keyrings/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/plugins/keyrings/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -5,10 +5,14 @@ plugindir = @PURPLE_PLUGINDIR@ -internalkeyring_la_CFLAGS = $(AM_CPPFLAGS) +if ENABLE_NETTLE + +internalkeyring_la_CFLAGS = $(AM_CPPFLAGS) $(NETTLE_CFLAGS) internalkeyring_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ internalkeyring_la_SOURCES = internalkeyring.c -internalkeyring_la_LIBADD = @PURPLE_LIBS@ +internalkeyring_la_LIBADD = @PURPLE_LIBS@ $(NETTLE_LIBS) + +endif if ENABLE_SECRETSERVICE @@ -56,8 +60,12 @@ if PLUGINS -plugin_LTLIBRARIES = \ +plugin_LTLIBRARIES = + +if ENABLE_NETTLE +plugin_LTLIBRARIES += \ internalkeyring.la +endif if ENABLE_SECRETSERVICE plugin_LTLIBRARIES += \
--- a/libpurple/plugins/keyrings/internalkeyring.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/plugins/keyrings/internalkeyring.c Fri Jun 30 15:03:16 2017 +0300 @@ -31,8 +31,9 @@ #include "plugins.h" #include "version.h" -#include "ciphers/aescipher.h" -#include "ciphers/pbkdf2cipher.h" +#include <nettle/aes.h> +#include <nettle/cbc.h> +#include <nettle/pbkdf2.h> #define INTKEYRING_NAME N_("Internal keyring") #define INTKEYRING_DESCRIPTION N_("This plugin provides the default password " \ @@ -45,7 +46,7 @@ #define INTKEYRING_PBKDF2_ITERATIONS 10000 #define INTKEYRING_PBKDF2_ITERATIONS_MIN 1000 #define INTKEYRING_PBKDF2_ITERATIONS_MAX 1000000000 -#define INTKEYRING_KEY_LEN (256/8) +#define INTKEYRING_KEY_LEN AES256_KEY_SIZE #define INTKEYRING_ENCRYPT_BUFF_LEN 1000 #define INTKEYRING_ENCRYPTED_MIN_LEN 50 #define INTKEYRING_ENCRYPTION_METHOD "pbkdf2-sha256-aes256" @@ -150,33 +151,16 @@ static intkeyring_buff_t * intkeyring_derive_key(const gchar *passphrase, intkeyring_buff_t *salt) { - PurpleCipher *cipher; - gboolean succ; intkeyring_buff_t *ret; g_return_val_if_fail(passphrase != NULL, NULL); - cipher = purple_pbkdf2_cipher_new(G_CHECKSUM_SHA256); - - g_object_set(G_OBJECT(cipher), "iter_count", - GUINT_TO_POINTER(purple_prefs_get_int(INTKEYRING_PREFS - "pbkdf2_iterations")), NULL); - g_object_set(G_OBJECT(cipher), "out_len", GUINT_TO_POINTER( - INTKEYRING_KEY_LEN), NULL); - purple_cipher_set_salt(cipher, salt->data, salt->len); - purple_cipher_set_key(cipher, (const guchar*)passphrase, - strlen(passphrase)); - ret = intkeyring_buff_new(g_new(guchar, INTKEYRING_KEY_LEN), INTKEYRING_KEY_LEN); - succ = purple_cipher_digest(cipher, ret->data, ret->len); - g_object_unref(cipher); - - if (!succ) { - intkeyring_buff_free(ret); - return NULL; - } + pbkdf2_hmac_sha256(strlen(passphrase), (const uint8_t *)passphrase, + purple_prefs_get_int(INTKEYRING_PREFS"pbkdf2_iterations"), + salt->len, salt->data, ret->len, ret->data); return ret; } @@ -230,10 +214,11 @@ static gchar * intkeyring_encrypt(intkeyring_buff_t *key, const gchar *str) { - PurpleCipher *cipher; + struct CBC_CTX(struct aes256_ctx, AES_BLOCK_SIZE) ctx; intkeyring_buff_t *iv; guchar plaintext[INTKEYRING_ENCRYPT_BUFF_LEN]; size_t plaintext_len, text_len, verify_len; + int padding_len; guchar encrypted_raw[INTKEYRING_ENCRYPT_BUFF_LEN]; ssize_t encrypted_size; @@ -249,31 +234,38 @@ g_return_val_if_fail(plaintext_len + verify_len <= sizeof(plaintext), NULL); - cipher = purple_aes_cipher_new(); - g_return_val_if_fail(cipher != NULL, NULL); - memset(plaintext, 0, plaintext_len); memcpy(plaintext, str, text_len); memcpy(plaintext + plaintext_len, INTKEYRING_VERIFY_STR, verify_len); plaintext_len += verify_len; - iv = intkeyring_gen_salt(purple_cipher_get_block_size(cipher)); + /* Pad PKCS7 */ + padding_len = AES_BLOCK_SIZE - (plaintext_len % AES_BLOCK_SIZE); + + if (plaintext_len + padding_len > INTKEYRING_ENCRYPT_BUFF_LEN) { + purple_debug_error("keyring-internal", + "Internal keyring encrypt buffer too small"); + return NULL; + } + + memset(plaintext + plaintext_len, padding_len, padding_len); + plaintext_len += padding_len; + + /* Encrypt */ + iv = intkeyring_gen_salt(AES_BLOCK_SIZE); g_return_val_if_fail(iv != NULL, NULL); - purple_cipher_set_iv(cipher, iv->data, iv->len); - purple_cipher_set_key(cipher, key->data, key->len); - purple_cipher_set_batch_mode(cipher, - PURPLE_CIPHER_BATCH_MODE_CBC); + aes256_set_encrypt_key(&ctx.ctx, key->data); + CBC_SET_IV(&ctx, iv->data); memcpy(encrypted_raw, iv->data, iv->len); - encrypted_size = purple_cipher_encrypt(cipher, - plaintext, plaintext_len, encrypted_raw + iv->len, - sizeof(encrypted_raw) - iv->len); + CBC_ENCRYPT(&ctx, aes256_encrypt, plaintext_len, + encrypted_raw + iv->len, plaintext); + encrypted_size = plaintext_len; encrypted_size += iv->len; memset(plaintext, 0, plaintext_len); intkeyring_buff_free(iv); - g_object_unref(cipher); if (encrypted_size < 0) return NULL; @@ -285,42 +277,63 @@ static gchar * intkeyring_decrypt(intkeyring_buff_t *key, const gchar *str) { - PurpleCipher *cipher; + struct CBC_CTX(struct aes256_ctx, AES_BLOCK_SIZE) ctx; guchar *encrypted_raw; gsize encrypted_size; size_t iv_len, verify_len, text_len; guchar plaintext[INTKEYRING_ENCRYPT_BUFF_LEN]; const gchar *verify_str = NULL; - ssize_t plaintext_len; + size_t plaintext_len; + guint padding_len; + guint i; gchar *ret; g_return_val_if_fail(key != NULL, NULL); g_return_val_if_fail(str != NULL, NULL); - cipher = purple_aes_cipher_new(); - g_return_val_if_fail(cipher != NULL, NULL); - encrypted_raw = g_base64_decode(str, &encrypted_size); g_return_val_if_fail(encrypted_raw != NULL, NULL); - iv_len = purple_cipher_get_block_size(cipher); + iv_len = AES_BLOCK_SIZE; if (encrypted_size < iv_len) { g_free(encrypted_raw); return NULL; } - purple_cipher_set_iv(cipher, encrypted_raw, iv_len); - purple_cipher_set_key(cipher, key->data, key->len); - purple_cipher_set_batch_mode(cipher, - PURPLE_CIPHER_BATCH_MODE_CBC); + /* Decrypt */ + aes256_set_decrypt_key(&ctx.ctx, key->data); + CBC_SET_IV(&ctx, encrypted_raw); + CBC_DECRYPT(&ctx, aes256_decrypt, encrypted_size - iv_len, + plaintext, encrypted_raw + iv_len); + plaintext_len = encrypted_size - iv_len; + g_free(encrypted_raw); - plaintext_len = purple_cipher_decrypt(cipher, - encrypted_raw + iv_len, encrypted_size - iv_len, - plaintext, sizeof(plaintext)); + /* Unpad PKCS7 */ + padding_len = plaintext[plaintext_len - 1]; + if (padding_len == 0 || padding_len > AES_BLOCK_SIZE || + padding_len > plaintext_len) { + purple_debug_warning("internal-keyring", + "Invalid padding length: %d (total %" G_GSIZE_FORMAT + ") - most probably, the key was invalid\n", + padding_len, plaintext_len); + return NULL; + } - g_free(encrypted_raw); - g_object_unref(cipher); + plaintext_len -= padding_len; + for (i = 0; i < padding_len; ++i) { + if (plaintext[plaintext_len + i] != padding_len) { + purple_debug_warning("internal-keyring", + "Padding doesn't match at pos %d (found %02x, " + "expected %02x) - " + "most probably, the key was invalid\n", + i, plaintext[plaintext_len + i], padding_len); + return NULL; + } + } + memset(plaintext + plaintext_len, 0, padding_len); + + /* Verify */ verify_len = strlen(INTKEYRING_VERIFY_STR); /* Don't remove the len > 0 check! */ if (plaintext_len > 0 && (gsize)plaintext_len > verify_len &&
--- a/libpurple/protocols/facebook/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/facebook/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -1,12 +1,9 @@ EXTRA_DIST = \ - Makefile.mingw \ - marshaller.list + Makefile.mingw pkgdir = @PURPLE_PLUGINDIR@ FACEBOOKSOURCES = \ - marshal.c \ - marshal.h \ api.c \ api.h \ data.c \ @@ -25,17 +22,6 @@ util.c \ util.h -CLEANFILES = \ - marshal.c \ - marshal.h - -marshal.c: $(srcdir)/marshaller.list marshal.h - $(AM_V_GEN)echo "#include \"marshal.h\"" > $@ - $(AM_V_at)$(GLIB_GENMARSHAL) --prefix=fb_marshal --body $(srcdir)/marshaller.list >> $@ - -marshal.h: $(srcdir)/marshaller.list - $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=fb_marshal --header $(srcdir)/marshaller.list > $@ - AM_CFLAGS = $(st) libfacebook_la_LDFLAGS = -module @PLUGIN_LDFLAGS@
--- a/libpurple/protocols/facebook/Makefile.mingw Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/facebook/Makefile.mingw Fri Jun 30 15:03:16 2017 +0300 @@ -42,7 +42,6 @@ ## SOURCES, OBJECTS ## C_SRC = \ - marshal.c \ api.c \ data.c \ facebook.c \ @@ -85,18 +84,11 @@ $(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll -marshal.c: marshaller.list marshal.h - @echo "#include \"marshal.h\"" > $@ - @$(GLIB_GENMARSHAL) --prefix=fb_marshal --body marshaller.list >> $@ - -marshal.h: marshaller.list - @$(GLIB_GENMARSHAL) --prefix=fb_marshal --header marshaller.list > $@ - ## ## CLEAN RULES ## clean: - rm -f $(OBJECTS) marshal.c marshal.h + rm -f $(OBJECTS) rm -f $(TARGET).dll include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/protocols/facebook/api.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/facebook/api.c Fri Jun 30 15:03:16 2017 +0300 @@ -28,7 +28,6 @@ #include "api.h" #include "http.h" #include "json.h" -#include "marshal.h" #include "thrift.h" #include "util.h" @@ -68,6 +67,7 @@ gboolean invisible; guint unread; FbId lastmid; + gchar *contacts_delta; }; struct _FbApiData @@ -88,6 +88,9 @@ static void fb_api_sticker(FbApi *api, FbId sid, FbApiMessage *msg); +void +fb_api_contacts_delta(FbApi *api, const gchar *delta_cursor); + G_DEFINE_TYPE(FbApi, fb_api, G_TYPE_OBJECT); static void @@ -185,6 +188,7 @@ g_free(priv->did); g_free(priv->stoken); g_free(priv->token); + g_free(priv->contacts_delta); } static void @@ -287,8 +291,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -303,8 +306,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -320,8 +322,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); @@ -341,12 +342,27 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__POINTER_BOOLEAN, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN); /** + * FbApi::contacts-delta: + * @api: The #FbApi. + * @added: The #GSList of added #FbApiUser's. + * @removed: The #GSList of strings with removed user ids. + * + * Like 'contacts', but only the deltas. + */ + g_signal_new("contacts-delta", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_ACTION, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, + 2, G_TYPE_POINTER, G_TYPE_POINTER); + + /** * FbApi::error: * @api: The #FbApi. * @error: The #GError. @@ -358,10 +374,9 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__OBJECT, + NULL, NULL, NULL, G_TYPE_NONE, - 1, G_TYPE_ERROR); + 1, G_TYPE_POINTER); /** * FbApi::events: @@ -374,8 +389,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); @@ -390,8 +404,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); @@ -406,8 +419,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); @@ -423,8 +435,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); @@ -441,12 +452,27 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__INT64, + NULL, NULL, NULL, G_TYPE_NONE, 1, FB_TYPE_ID); /** + * FbApi::thread-kicked: + * @api: The #FbApi. + * @thrd: The #FbApiThread. + * + * Emitted upon the reply of a thread request when the user is no longer + * part of that thread. This is emitted as a result of #fb_api_thread(). + */ + g_signal_new("thread-kicked", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_ACTION, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, + 1, G_TYPE_POINTER); + + /** * FbApi::threads: * @api: The #FbApi. * @thrds: The #GSList of #FbApiThread's. @@ -458,8 +484,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); @@ -474,8 +499,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); } @@ -762,6 +786,9 @@ g_free(data); } + purple_http_request_header_set(req, "User-Agent", FB_API_AGENT); + purple_http_request_header_set(req, "Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); + data = fb_http_params_close(params, NULL); purple_http_request_set_contents(req, data, -1); ret = purple_http_request(priv->gc, req, callback, api); @@ -794,12 +821,16 @@ case FB_API_QUERY_CONTACTS_AFTER: name = "FetchContactsFullWithAfterQuery"; break; + case FB_API_QUERY_CONTACTS_DELTA: + name = "FetchContactsDeltaQuery"; + break; case FB_API_QUERY_STICKER: name = "FetchStickersWithPreviewsQuery"; break; case FB_API_QUERY_THREAD: name = "ThreadQuery"; break; + case FB_API_QUERY_SEQ_ID: case FB_API_QUERY_THREADS: name = "ThreadListQuery"; break; @@ -883,7 +914,7 @@ /* Write the information string */ fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 2, 1); - fb_thrift_write_str(thft, ""); + fb_thrift_write_str(thft, FB_API_MQTT_AGENT); /* Write the UNKNOWN ("cp"?) */ fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 3, 2); @@ -1029,7 +1060,7 @@ } values = fb_json_values_new(root); - fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, + fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.viewer.message_threads.sync_sequence_id"); fb_json_values_add(values, FB_JSON_TYPE_INT, TRUE, "$.viewer.message_threads.unread_count"); @@ -1045,7 +1076,13 @@ priv->sid = g_ascii_strtoll(str, NULL, 10); priv->unread = fb_json_values_next_int(values, 0); - fb_api_connect_queue(api); + if (priv->sid == 0) { + fb_api_error(api, FB_API_ERROR_GENERAL, + _("Failed to get sync_sequence_id")); + } else { + fb_api_connect_queue(api); + } + g_object_unref(values); json_node_free(root); } @@ -1087,7 +1124,7 @@ if (priv->sid == 0) { bldr = fb_json_bldr_new(JSON_NODE_OBJECT); fb_json_bldr_add_str(bldr, "1", "0"); - fb_api_http_query(api, FB_API_QUERY_THREADS, bldr, + fb_api_http_query(api, FB_API_QUERY_SEQ_ID, bldr, fb_api_cb_seqid); } else { fb_api_connect_queue(api); @@ -1363,7 +1400,11 @@ if (purple_strequal(str, "ExternalUrl")) { params = fb_http_params_new_parse(url, TRUE); - text = fb_http_params_dup_str(params, "u", NULL); + if (g_str_has_prefix(url, FB_API_FBRPC_PREFIX)) { + text = fb_http_params_dup_str(params, "target_url", NULL); + } else { + text = fb_http_params_dup_str(params, "u", NULL); + } fb_http_params_free(params); } else { text = g_strdup(url); @@ -1396,8 +1437,7 @@ values = fb_json_values_new(root); fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.xmaGraphQL"); fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, "$.fbid"); - fb_json_values_set_array(values, FALSE, "$.deltaNewMessage" - ".attachments"); + fb_json_values_set_array(values, FALSE, "$.attachments"); while (fb_json_values_update(values, &err)) { str = fb_json_values_next_str(values, NULL); @@ -1439,25 +1479,40 @@ return msgs; } + +static GSList * +fb_api_cb_publish_ms_new_message(FbApi *api, JsonNode *root, GSList *msgs, GError **error); + +static GSList * +fb_api_cb_publish_ms_event(FbApi *api, JsonNode *root, GSList *events, FbApiEventType type, GError **error); + static void fb_api_cb_publish_ms(FbApi *api, GByteArray *pload) { - const gchar *body; const gchar *data; - const gchar *str; - FbApiMessage *dmsg; - FbApiMessage msg; FbApiPrivate *priv = api->priv; - FbId id; - FbId oid; FbJsonValues *values; FbThrift *thft; gchar *stoken; GError *err = NULL; + GList *elms, *l; GSList *msgs = NULL; + GSList *events = NULL; guint size; JsonNode *root; JsonNode *node; + JsonArray *arr; + + static const struct { + const gchar *member; + FbApiEventType type; + gboolean is_message; + } event_types[] = { + {"deltaNewMessage", 0, 1}, + {"deltaThreadName", FB_API_EVENT_TYPE_THREAD_TOPIC, 0}, + {"deltaParticipantsAddedToGroupThread", FB_API_EVENT_TYPE_THREAD_USER_ADDED, 0}, + {"deltaParticipantLeftGroupThread", FB_API_EVENT_TYPE_THREAD_USER_REMOVED, 0}, + }; /* Read identifier string (for Facebook employees) */ thft = fb_thrift_new(pload, 0); @@ -1497,39 +1552,100 @@ return; } + arr = fb_json_node_get_arr(root, "$.deltas", NULL); + elms = json_array_get_elements(arr); + + for (l = elms; l != NULL; l = l->next) { + guint i = 0; + JsonObject *o = json_node_get_object(l->data); + + for (i = 0; i < G_N_ELEMENTS(event_types); i++) { + if ((node = json_object_get_member(o, event_types[i].member))) { + if (event_types[i].is_message) { + msgs = fb_api_cb_publish_ms_new_message( + api, node, msgs, &err + ); + } else { + events = fb_api_cb_publish_ms_event( + api, node, events, event_types[i].type, &err + ); + } + } + } + + if (G_UNLIKELY(err != NULL)) { + break; + } + } + + g_list_free(elms); + json_array_unref(arr); + + if (G_LIKELY(err == NULL)) { + if (msgs) { + msgs = g_slist_reverse(msgs); + g_signal_emit_by_name(api, "messages", msgs); + } + + if (events) { + events = g_slist_reverse(events); + g_signal_emit_by_name(api, "events", events); + } + } else { + fb_api_error_emit(api, err); + } + + g_slist_free_full(msgs, (GDestroyNotify) fb_api_message_free); + g_slist_free_full(events, (GDestroyNotify) fb_api_event_free); + json_node_free(root); +} + +static GSList * +fb_api_cb_publish_ms_new_message(FbApi *api, JsonNode *root, GSList *msgs, GError **error) +{ + const gchar *body; + const gchar *str; + GError *err = NULL; + FbApiPrivate *priv = api->priv; + FbApiMessage *dmsg; + FbApiMessage msg; + FbId id; + FbId oid; + FbJsonValues *values; + JsonNode *node; + values = fb_json_values_new(root); fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, - "$.deltaNewMessage.messageMetadata.offlineThreadingId"); + "$.messageMetadata.offlineThreadingId"); fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, - "$.deltaNewMessage.messageMetadata.actorFbId"); + "$.messageMetadata.actorFbId"); fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, - "$.deltaNewMessage.messageMetadata" + "$.messageMetadata" ".threadKey.otherUserFbId"); fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, - "$.deltaNewMessage.messageMetadata" + "$.messageMetadata" ".threadKey.threadFbId"); fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, - "$.deltaNewMessage.messageMetadata.timestamp"); + "$.messageMetadata.timestamp"); fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, - "$.deltaNewMessage.body"); + "$.body"); fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, - "$.deltaNewMessage.stickerId"); + "$.stickerId"); fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, - "$.deltaNewMessage.messageMetadata.messageId"); - fb_json_values_set_array(values, TRUE, "$.deltas"); - - while (fb_json_values_update(values, &err)) { + "$.messageMetadata.messageId"); + + if (fb_json_values_update(values, &err)) { id = fb_json_values_next_int(values, 0); /* Ignore everything but new messages */ if (id == 0) { - continue; + goto beach; } /* Ignore sequential duplicates */ if (id == priv->lastmid) { fb_util_debug_info("Ignoring duplicate %" FB_ID_FORMAT, id); - continue; + goto beach; } priv->lastmid = id; @@ -1565,7 +1681,7 @@ str = fb_json_values_next_str(values, NULL); if (str == NULL) { - continue; + goto beach; } node = fb_json_values_get_root(values); @@ -1573,20 +1689,97 @@ node, &err); if (G_UNLIKELY(err != NULL)) { - break; + g_propagate_error(error, err); + goto beach; } } - if (G_LIKELY(err == NULL)) { - msgs = g_slist_reverse(msgs); - g_signal_emit_by_name(api, "messages", msgs); - } else { - fb_api_error_emit(api, err); +beach: + g_object_unref(values); + return msgs; +} + +static GSList * +fb_api_cb_publish_ms_event(FbApi *api, JsonNode *root, GSList *events, FbApiEventType type, GError **error) +{ + FbApiEvent *event; + FbJsonValues *values = NULL; + FbJsonValues *values_inner = NULL; + GError *err = NULL; + + values = fb_json_values_new(root); + fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, + "$.messageMetadata.threadKey.threadFbId"); + fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, + "$.messageMetadata.actorFbId"); + + switch (type) { + case FB_API_EVENT_TYPE_THREAD_TOPIC: + fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, + "$.name"); + break; + + case FB_API_EVENT_TYPE_THREAD_USER_ADDED: + values_inner = fb_json_values_new(root); + + fb_json_values_add(values_inner, FB_JSON_TYPE_INT, FALSE, + "$.userFbId"); + + /* use the text field for the full name */ + fb_json_values_add(values_inner, FB_JSON_TYPE_STR, FALSE, + "$.fullName"); + + fb_json_values_set_array(values_inner, FALSE, + "$.addedParticipants"); + break; + + case FB_API_EVENT_TYPE_THREAD_USER_REMOVED: + fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, + "$.leftParticipantFbId"); + + /* use the text field for the kick message */ + fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, + "$.messageMetadata.adminText"); + break; } - g_slist_free_full(msgs, (GDestroyNotify) fb_api_message_free); + fb_json_values_update(values, &err); + + event = fb_api_event_dup(NULL, FALSE); + event->type = type; + event->tid = fb_json_values_next_int(values, 0); + event->uid = fb_json_values_next_int(values, 0); + + if (type == FB_API_EVENT_TYPE_THREAD_TOPIC) { + event->text = fb_json_values_next_str_dup(values, NULL); + } else if (type == FB_API_EVENT_TYPE_THREAD_USER_REMOVED) { + /* overwrite actor with subject */ + event->uid = fb_json_values_next_int(values, 0); + event->text = fb_json_values_next_str_dup(values, NULL); + } else if (type == FB_API_EVENT_TYPE_THREAD_USER_ADDED) { + + while (fb_json_values_update(values_inner, &err)) { + FbApiEvent *devent = fb_api_event_dup(event, FALSE); + + devent->uid = fb_json_values_next_int(values_inner, 0); + devent->text = fb_json_values_next_str_dup(values_inner, NULL); + + events = g_slist_prepend(events, devent); + } + fb_api_event_free(event); + event = NULL; + g_object_unref(values_inner); + } + g_object_unref(values); - json_node_free(root); + + if (G_UNLIKELY(err != NULL)) { + g_propagate_error(error, err); + } else if (event) { + events = g_slist_prepend(events, event); + } + + return events; } static void @@ -2043,25 +2236,16 @@ fb_api_http_query(api, FB_API_QUERY_CONTACT, bldr, fb_api_cb_contact); } -static void -fb_api_cb_contacts(PurpleHttpConnection *con, PurpleHttpResponse *res, - gpointer data) +static GSList * +fb_api_cb_contacts_nodes(FbApi *api, JsonNode *root, GSList *users) { - const gchar *cursor; const gchar *str; - FbApi *api = data; FbApiPrivate *priv = api->priv; FbApiUser *user; FbId uid; FbJsonValues *values; - gboolean complete; + gboolean is_array; GError *err = NULL; - GSList *users = NULL; - JsonNode *root; - - if (!fb_api_http_chk(api, con, res, &root)) { - return; - } values = fb_json_values_new(root); fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, @@ -2072,8 +2256,12 @@ "$.structured_name.text"); fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.hugePictureUrl.uri"); - fb_json_values_set_array(values, FALSE, "$.viewer.messenger_contacts" - ".nodes"); + + is_array = (JSON_NODE_TYPE(root) == JSON_NODE_ARRAY); + + if (is_array) { + fb_json_values_set_array(values, FALSE, "$"); + } while (fb_json_values_update(values, &err)) { str = fb_json_values_next_str(values, "0"); @@ -2083,6 +2271,9 @@ if ((!purple_strequal(str, "ARE_FRIENDS") && (uid != priv->uid)) || (uid == 0)) { + if (!is_array) { + break; + } continue; } @@ -2094,20 +2285,123 @@ user->csum = fb_api_user_icon_checksum(user->icon); users = g_slist_prepend(users, user); + + if (!is_array) { + break; + } } g_object_unref(values); - values = fb_json_values_new(root); + return users; +} + +/* base64(contact:<our id>:<their id>:<whatever>) */ +static GSList * +fb_api_cb_contacts_parse_removed(FbApi *api, JsonNode *node, GSList *users) +{ + gsize len; + char **split; + char *decoded = (char *) g_base64_decode(json_node_get_string(node), &len); + + g_return_val_if_fail(decoded[len] == '\0', users); + g_return_val_if_fail(len == strlen(decoded), users); + g_return_val_if_fail(g_str_has_prefix(decoded, "contact:"), users); + + split = g_strsplit_set(decoded, ":", 4); + + g_return_val_if_fail(g_strv_length(split) == 4, users); + + users = g_slist_prepend(users, g_strdup(split[2])); + + g_strfreev(split); + g_free(decoded); + + return users; +} + +static void +fb_api_cb_contacts(PurpleHttpConnection *con, PurpleHttpResponse *res, + gpointer data) +{ + const gchar *cursor; + const gchar *delta_cursor; + FbApi *api = data; + FbApiPrivate *priv = api->priv; + FbJsonValues *values; + gboolean complete; + gboolean is_delta; + GError *err = NULL; + GList *l; + GSList *users = NULL; + JsonNode *root; + JsonNode *croot; + JsonNode *node; + + if (!fb_api_http_chk(api, con, res, &root)) { + return; + } + + croot = fb_json_node_get(root, "$.viewer.messenger_contacts.deltas", NULL); + is_delta = (croot != NULL); + + if (!is_delta) { + croot = fb_json_node_get(root, "$.viewer.messenger_contacts", NULL); + node = fb_json_node_get(croot, "$.nodes", NULL); + users = fb_api_cb_contacts_nodes(api, node, users); + json_node_free(node); + + } else { + GSList *added = NULL; + GSList *removed = NULL; + JsonArray *arr = fb_json_node_get_arr(croot, "$.nodes", NULL); + GList *elms = json_array_get_elements(arr); + + for (l = elms; l != NULL; l = l->next) { + if ((node = fb_json_node_get(l->data, "$.added", NULL))) { + added = fb_api_cb_contacts_nodes(api, node, added); + json_node_free(node); + } + + if ((node = fb_json_node_get(l->data, "$.removed", NULL))) { + removed = fb_api_cb_contacts_parse_removed(api, node, removed); + json_node_free(node); + } + } + + g_signal_emit_by_name(api, "contacts-delta", added, removed); + + g_slist_free_full(added, (GDestroyNotify) fb_api_user_free); + g_slist_free_full(removed, (GDestroyNotify) g_free); + + g_list_free(elms); + json_array_unref(arr); + } + + values = fb_json_values_new(croot); + fb_json_values_add(values, FB_JSON_TYPE_BOOL, FALSE, + "$.page_info.has_next_page"); fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, - "$.viewer.messenger_contacts.page_info.end_cursor"); + "$.page_info.delta_cursor"); + fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, + "$.page_info.end_cursor"); fb_json_values_update(values, NULL); + complete = !fb_json_values_next_bool(values, FALSE); + + delta_cursor = fb_json_values_next_str(values, NULL); + cursor = fb_json_values_next_str(values, NULL); if (G_UNLIKELY(err == NULL)) { - complete = (cursor == NULL); - g_signal_emit_by_name(api, "contacts", users, complete); + if (is_delta || complete) { + g_free(priv->contacts_delta); + priv->contacts_delta = g_strdup(is_delta ? cursor : delta_cursor); + } + + if (users) { + g_signal_emit_by_name(api, "contacts", users, complete); + } if (!complete) { fb_api_contacts_after(api, cursor); @@ -2118,14 +2412,25 @@ g_slist_free_full(users, (GDestroyNotify) fb_api_user_free); g_object_unref(values); + + json_node_free(croot); json_node_free(root); } void fb_api_contacts(FbApi *api) { + FbApiPrivate *priv; JsonBuilder *bldr; + g_return_if_fail(FB_IS_API(api)); + priv = api->priv; + + if (priv->contacts_delta) { + fb_api_contacts_delta(api, priv->contacts_delta); + return; + } + bldr = fb_json_bldr_new(JSON_NODE_OBJECT); fb_json_bldr_arr_begin(bldr, "0"); fb_json_bldr_add_str(bldr, NULL, "user"); @@ -2153,6 +2458,24 @@ } void +fb_api_contacts_delta(FbApi *api, const gchar *delta_cursor) +{ + JsonBuilder *bldr; + + bldr = fb_json_bldr_new(JSON_NODE_OBJECT); + + fb_json_bldr_add_str(bldr, "0", delta_cursor); + + fb_json_bldr_arr_begin(bldr, "1"); + fb_json_bldr_add_str(bldr, NULL, "user"); + fb_json_bldr_arr_end(bldr); + + fb_json_bldr_add_str(bldr, "2", G_STRINGIFY(FB_API_CONTACTS_COUNT)); + fb_api_http_query(api, FB_API_QUERY_CONTACTS_DELTA, bldr, + fb_api_cb_contacts); +} + +void fb_api_connect(FbApi *api, gboolean invisible) { FbApiPrivate *priv; @@ -2603,6 +2926,7 @@ FbId uid; FbJsonValues *values; gboolean haself = FALSE; + guint num_users = 0; GError *err = NULL; values = fb_json_values_new(root); @@ -2638,6 +2962,7 @@ while (fb_json_values_update(values, &err)) { str = fb_json_values_next_str(values, "0"); uid = FB_ID_FROM_STR(str); + num_users++; if (uid != priv->uid) { user = fb_api_user_dup(NULL, FALSE); @@ -2656,8 +2981,7 @@ return FALSE; } - if ((g_slist_length(thrd->users) < 2) || !haself) { - fb_api_thread_reset(thrd, TRUE); + if (num_users < 2 || !haself) { g_object_unref(values); return FALSE; } @@ -2693,8 +3017,12 @@ if (!fb_api_thread_parse(api, &thrd, node, &err)) { if (G_LIKELY(err == NULL)) { - fb_api_error(api, FB_API_ERROR_GENERAL, - _("Failed to parse thread information")); + if (thrd.tid) { + g_signal_emit_by_name(api, "thread-kicked", &thrd); + } else { + fb_api_error(api, FB_API_ERROR_GENERAL, + _("Failed to parse thread information")); + } } else { fb_api_error_emit(api, err); } @@ -2738,7 +3066,7 @@ } values = fb_json_values_new(root); - fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.thread_fbid"); + fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.id"); fb_json_values_update(values, &err); FB_API_ERROR_EMIT(api, err, @@ -2785,8 +3113,8 @@ json = fb_json_bldr_close(bldr, JSON_NODE_ARRAY, NULL); prms = fb_http_params_new(); - fb_http_params_set_str(prms, "to", json); - fb_api_http_req(api, FB_API_URL_THREADS, "createThread", "POST", + fb_http_params_set_str(prms, "recipients", json); + fb_api_http_req(api, FB_API_URL_THREADS, "createGroup", "POST", prms, fb_api_cb_thread_create); g_free(json); } @@ -2807,7 +3135,7 @@ prms = fb_http_params_new(); fb_http_params_set_str(prms, "to", json); - fb_http_params_set_strf(prms, "id", "t_id.%" FB_ID_FORMAT, tid); + fb_http_params_set_strf(prms, "id", "t_%" FB_ID_FORMAT, tid); fb_api_http_req(api, FB_API_URL_PARTS, "addMembers", "POST", prms, fb_api_cb_http_bool); g_free(json); @@ -2825,7 +3153,7 @@ priv = api->priv; prms = fb_http_params_new(); - fb_http_params_set_strf(prms, "id", "t_id.%" FB_ID_FORMAT, tid); + fb_http_params_set_strf(prms, "id", "t_%" FB_ID_FORMAT, tid); if (uid == 0) { uid = priv->uid; @@ -2850,7 +3178,7 @@ prms = fb_http_params_new(); fb_http_params_set_str(prms, "name", topic); - fb_http_params_set_strf(prms, "tid", "t_id.%" FB_ID_FORMAT, tid); + fb_http_params_set_int(prms, "tid", tid); fb_api_http_req(api, FB_API_URL_TOPIC, "setThreadName", "messaging.setthreadname", prms, fb_api_cb_http_bool);
--- a/libpurple/protocols/facebook/api.h Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/facebook/api.h Fri Jun 30 15:03:16 2017 +0300 @@ -77,6 +77,13 @@ #define FB_API_WHOST "https://www.facebook.com" /** + * FB_API_FBRPC_PREFIX + * + * The fbrpc URL prefix used in links shared from the mobile app. + */ +#define FB_API_FBRPC_PREFIX "fbrpc://facebook/nativethirdparty" + +/** * FB_API_KEY: * * The Facebook API key. @@ -91,6 +98,30 @@ #define FB_API_SECRET "374e60f8b9bb6b8cbb30f78030438895" /** + * FB_ORCA_AGENT + * + * The part of the user agent that looks like the official client, since the + * server started checking this. + */ + +#define FB_ORCA_AGENT "[FBAN/Orca-Android;FBAV/109.0.0.17.70;FBPN/com.facebook.orca;FBLC/en_US;FBBV/52182662]" + +/** + * FB_API_AGENT: + * + * The HTTP User-Agent header. + */ +#define FB_API_AGENT "Facebook plugin / Purple / 0.9.5 " FB_ORCA_AGENT + +/** + * FB_API_MQTT_AGENT + * + * The client information string sent in the MQTT CONNECT message + */ + +#define FB_API_MQTT_AGENT FB_API_AGENT + +/** * FB_API_URL_ATTACH: * * The URL for attachment URL requests. @@ -131,7 +162,7 @@ * * The URL for thread management requests. */ -#define FB_API_URL_THREADS FB_API_GHOST "/me/threads" +#define FB_API_URL_THREADS FB_API_GHOST "/me/group_threads" /** * FB_API_URL_TOPIC: @@ -165,10 +196,8 @@ * 2: big_img_size * 3: huge_img_size * 4: small_img_size - * 5: low_res_cover_size - * 6: media_type */ -#define FB_API_QUERY_CONTACTS 10153856456271729 +#define FB_API_QUERY_CONTACTS 10154444360806729 /** * FB_API_QUERY_CONTACTS_AFTER: @@ -182,10 +211,24 @@ * 3: big_img_size * 4: huge_img_size * 5: small_img_size - * 6: low_res_cover_size - * 7: media_type */ -#define FB_API_QUERY_CONTACTS_AFTER 10153856456281729 +#define FB_API_QUERY_CONTACTS_AFTER 10154444360816729 + + +/** + * FB_API_QUERY_CONTACTS_DELTA: + * + * The query hash for the `FetchContactsDeltaQuery`. + * + * Key mapping: + * 0: after + * 1: profile_types + * 2: limit + * 3: big_img_size + * 4: huge_img_size + * 5: small_img_size + */ +#define FB_API_QUERY_CONTACTS_DELTA 10154444360801729 /** * FB_API_QUERY_STICKER: @@ -256,6 +299,16 @@ #define FB_API_QUERY_THREADS 10153919752026729 /** + * FB_API_QUERY_SEQ_ID: + * + * A variant of ThreadListQuery with sequence ID + * + * TODO: parameters. + */ + +#define FB_API_QUERY_SEQ_ID 10155268192741729 + +/** * FB_API_QUERY_XMA: * * The query hash for the `XMAQuery`.
--- a/libpurple/protocols/facebook/data.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/facebook/data.c Fri Jun 30 15:03:16 2017 +0300 @@ -243,6 +243,10 @@ g_object_get_property(G_OBJECT(priv->api), fb_props_strs[i], &val); str = g_value_get_string(&val); + + if (purple_strequal(fb_props_strs[i], "token") && !purple_account_get_remember_password(acct)) { + str = ""; + } purple_account_set_string(acct, fb_props_strs[i], str); g_value_unset(&val); }
--- a/libpurple/protocols/facebook/facebook.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/facebook/facebook.c Fri Jun 30 15:03:16 2017 +0300 @@ -68,15 +68,18 @@ PurpleBlistNode *n; PurpleBlistNode *node; PurpleGroup *grp; + const gchar *title; if (friend) { - return purple_blist_get_default_group(); + title = _("Facebook Friends"); + } else { + title = _("Facebook Non-Friends"); } - grp = purple_blist_find_group(_("Facebook Non-Friends")); + grp = purple_blist_find_group(title); if (G_UNLIKELY(grp == NULL)) { - grp = purple_group_new(_("Facebook Non-Friends")); + grp = purple_group_new(title); node = NULL; for (n = purple_blist_get_root(); n != NULL; n = n->next) { @@ -86,9 +89,10 @@ /* Append to the end of the buddy list */ purple_blist_add_group(grp, node); - node = PURPLE_BLIST_NODE(grp); - purple_blist_node_set_transient(node, TRUE); - purple_blist_node_set_bool(node, "collapsed", TRUE); + if (!friend) { + node = PURPLE_BLIST_NODE(grp); + purple_blist_node_set_bool(node, "collapsed", TRUE); + } } return grp; @@ -98,16 +102,13 @@ fb_buddy_add_nonfriend(PurpleAccount *acct, FbApiUser *user) { gchar uid[FB_ID_STRMAX]; - PurpleBlistNode *node; PurpleBuddy *bdy; PurpleGroup *grp; FB_ID_TO_STR(user->uid, uid); - bdy = purple_buddy_new(acct, uid, NULL); + bdy = purple_buddy_new(acct, uid, user->name); grp = fb_get_group(FALSE); - node = PURPLE_BLIST_NODE(bdy); - purple_blist_node_set_transient(node, TRUE); purple_buddy_set_server_alias(bdy, user->name); purple_blist_add_buddy(bdy, NULL, grp, NULL); } @@ -212,6 +213,28 @@ } static void +fb_sync_contacts_add_timeout(FbData *fata) +{ + gint sync; + PurpleConnection *gc; + PurpleAccount *acct; + + gc = fb_data_get_connection(fata); + acct = purple_connection_get_account(gc); + + sync = purple_account_get_int(acct, "sync-interval", 5); + + if (sync < 1) { + purple_account_set_int(acct, "sync-interval", 1); + sync = 1; + } + + sync *= 60 * 1000; + fb_data_add_timeout(fata, "sync-contacts", sync, fb_cb_sync_contacts, + fata); +} + +static void fb_cb_api_contacts(FbApi *api, GSList *users, gboolean complete, gpointer data) { const gchar *alias; @@ -220,9 +243,6 @@ FbData *fata = data; FbId muid; gchar uid[FB_ID_STRMAX]; - gint sync; - gpointer bata; - GSList *buddies; GSList *l; GValue val = G_VALUE_INIT; PurpleAccount *acct; @@ -272,7 +292,6 @@ purple_blist_add_buddy(bdy, NULL, grp, NULL); } - purple_buddy_set_protocol_data(bdy, GINT_TO_POINTER(TRUE)); purple_buddy_set_server_alias(bdy, user->name); csum = purple_buddy_icons_get_checksum_for_user(bdy); @@ -288,20 +307,6 @@ return; } - buddies = purple_blist_find_buddies(acct, NULL); - - while (buddies != NULL) { - bdy = buddies->data; - bata = purple_buddy_get_protocol_data(bdy); - buddies = g_slist_delete_link(buddies, buddies); - - if (GPOINTER_TO_INT(bata)) { - purple_buddy_set_protocol_data(bdy, NULL); - } else if (purple_buddy_get_group(bdy) != grpn) { - purple_blist_remove_buddy(bdy); - } - } - if (state != PURPLE_CONNECTION_CONNECTED) { status = purple_account_get_active_status(acct); type = purple_status_get_status_type(status); @@ -311,16 +316,52 @@ fb_api_connect(api, pstat == PURPLE_STATUS_INVISIBLE); } - sync = purple_account_get_int(acct, "sync-interval", 30); + fb_sync_contacts_add_timeout(fata); +} + +static void +fb_cb_api_contacts_delta(FbApi *api, GSList *added, GSList *removed, gpointer data) +{ + FbApiUser *user; + FbData *fata = data; + gchar uid[FB_ID_STRMAX]; + GSList *l; + PurpleAccount *acct; + PurpleBuddy *bdy; + PurpleConnection *gc; + PurpleGroup *grp; + PurpleGroup *grpn; - if (sync < 5) { - purple_account_set_int(acct, "sync-interval", 5); - sync = 5; + gc = fb_data_get_connection(fata); + acct = purple_connection_get_account(gc); + grp = fb_get_group(TRUE); + grpn = fb_get_group(FALSE); + + for (l = added; l != NULL; l = l->next) { + user = l->data; + FB_ID_TO_STR(user->uid, uid); + + bdy = purple_blist_find_buddy(acct, uid); + + if ((bdy != NULL) && (purple_buddy_get_group(bdy) == grpn)) { + purple_blist_remove_buddy(bdy); + } + + bdy = purple_buddy_new(acct, uid, NULL); + purple_blist_add_buddy(bdy, NULL, grp, NULL); + + purple_buddy_set_server_alias(bdy, user->name); } - sync *= 60 * 1000; - fb_data_add_timeout(fata, "sync-contacts", sync, fb_cb_sync_contacts, - fata); + for (l = removed; l != NULL; l = l->next) { + bdy = purple_blist_find_buddy(acct, l->data); + + if (bdy != NULL) { + purple_blist_remove_buddy(bdy); + } + } + + fb_sync_contacts_add_timeout(fata); } static void @@ -397,8 +438,18 @@ case FB_API_EVENT_TYPE_THREAD_USER_ADDED: if (purple_blist_find_buddy(acct, uid) == NULL) { - g_hash_table_insert(fetch, &event->tid, event); - break; + if (event->text) { + FbApiUser *user = fb_api_user_dup(NULL, FALSE); + user->uid = event->uid; + user->name = g_strdup(event->text); + + fb_buddy_add_nonfriend(acct, user); + + fb_api_user_free(user); + } else { + g_hash_table_insert(fetch, &event->tid, event); + break; + } } purple_chat_conversation_add_user(chat, uid, NULL, 0, @@ -406,7 +457,7 @@ break; case FB_API_EVENT_TYPE_THREAD_USER_REMOVED: - purple_chat_conversation_remove_user(chat, uid, NULL); + purple_chat_conversation_remove_user(chat, uid, event->text); break; } } @@ -664,6 +715,39 @@ } static void +fb_cb_api_thread_kicked(FbApi *api, FbApiThread *thrd, gpointer data) +{ + FbData *fata = data; + gchar tid[FB_ID_STRMAX]; + PurpleAccount *acct; + PurpleConnection *gc; + PurpleChatConversation *chat; + + FB_ID_TO_STR(thrd->tid, tid); + + gc = fb_data_get_connection(fata); + acct = purple_connection_get_account(gc); + chat = purple_conversations_find_chat_with_account(tid, acct); + + if (chat == NULL) { + PurpleRequestCommonParameters *cpar; + + cpar = purple_request_cpar_from_connection(gc); + purple_notify_error(gc, + _("Join a Chat"), + _("Failed to Join Chat"), + _("You have been removed from this chat"), + cpar); + return; + } + + purple_conversation_write_system_message(PURPLE_CONVERSATION(chat), + _("You have been removed from this chat"), 0); + + purple_serv_got_chat_left(gc, purple_chat_conversation_get_id(chat)); +} + +static void fb_cb_api_threads(FbApi *api, GSList *thrds, gpointer data) { const gchar *alias; @@ -743,11 +827,32 @@ } } +static void +fb_mark_read(FbData *fata, FbId id, gboolean thread) +{ + FbApi *api; + PurpleAccount *acct; + PurpleConnection *gc; + + gc = fb_data_get_connection(fata); + acct = purple_connection_get_account(gc); + api = fb_data_get_api(fata); + + if (!fb_data_get_unread(fata, id) || + (purple_account_get_bool(acct, "mark-read-available", FALSE) && + fb_api_is_invisible(api))) + { + return; + } + + fb_data_set_unread(fata, id, FALSE); + fb_api_read(api, id, thread); +} + static gboolean fb_cb_conv_read(gpointer data) { const gchar *name; - FbApi *api; FbData *fata; FbId id; gchar *tname; @@ -763,15 +868,9 @@ fb_data_clear_timeout(fata, tname, FALSE); g_free(tname); - if (!purple_conversation_has_focus(conv) || - !fb_data_get_unread(fata, id)) - { - return FALSE; + if (purple_conversation_has_focus(conv)) { + fb_mark_read(fata, id, PURPLE_IS_CHAT_CONVERSATION(conv)); } - - api = fb_data_get_api(fata); - fb_data_set_unread(fata, id, FALSE); - fb_api_read(api, id, PURPLE_IS_CHAT_CONVERSATION(conv)); return FALSE; } @@ -918,6 +1017,10 @@ G_CALLBACK(fb_cb_api_contacts), fata); g_signal_connect(api, + "contacts-delta", + G_CALLBACK(fb_cb_api_contacts_delta), + fata); + g_signal_connect(api, "error", G_CALLBACK(fb_cb_api_error), fata); @@ -942,6 +1045,10 @@ G_CALLBACK(fb_cb_api_thread_create), fata); g_signal_connect(api, + "thread-kicked", + G_CALLBACK(fb_cb_api_thread_kicked), + fata); + g_signal_connect(api, "threads", G_CALLBACK(fb_cb_api_threads), fata); @@ -961,7 +1068,7 @@ G_CALLBACK(fb_cb_conv_deleting), fata); - if (!fb_data_load(fata)) { + if (!fb_data_load(fata) || !purple_account_get_remember_password(acct)) { user = purple_account_get_username(acct); pass = purple_connection_get_password(gc); purple_connection_update_progress(gc, _("Authenticating"), @@ -1437,13 +1544,17 @@ protocol->options = OPT_PROTO_CHAT_TOPIC; opt = purple_account_option_int_new(_("Buddy list sync interval"), - "sync-interval", 30); + "sync-interval", 5); opts = g_list_prepend(opts, opt); - opt = purple_account_option_bool_new(_("Mark messages as read"), + opt = purple_account_option_bool_new(_("Mark messages as read on focus"), "mark-read", TRUE); opts = g_list_prepend(opts, opt); + opt = purple_account_option_bool_new(_("Mark messages as read only when available"), + "mark-read-available", FALSE); + opts = g_list_prepend(opts, opt); + opt = purple_account_option_bool_new(_("Show self messages"), "show-self", TRUE); opts = g_list_prepend(opts, opt);
--- a/libpurple/protocols/facebook/marshaller.list Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -VOID:INT64 -VOID:OBJECT -VOID:POINTER -VOID:POINTER,BOOLEAN -VOID:STRING,BOXED -VOID:VOID
--- a/libpurple/protocols/facebook/mqtt.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/facebook/mqtt.c Fri Jun 30 15:03:16 2017 +0300 @@ -31,7 +31,6 @@ #include "purple-gio.h" #include "queuedoutputstream.h" -#include "marshal.h" #include "mqtt.h" #include "util.h" @@ -97,8 +96,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -114,8 +112,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__OBJECT, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_ERROR); @@ -131,8 +128,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -148,8 +144,7 @@ G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, - NULL, NULL, - fb_marshal_VOID__STRING_BOXED, + NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BYTE_ARRAY); } @@ -440,8 +435,10 @@ do { if (pos >= count) { /* Not enough data yet, try again later */ - size = 0; - break; + g_buffered_input_stream_fill_async(priv->input, -1, + G_PRIORITY_DEFAULT, priv->cancellable, + fb_mqtt_cb_fill, mqtt); + return; } byte = *(buf + pos++); @@ -450,28 +447,22 @@ mult *= 128; } while ((byte & 128) != 0); - if (size > 0) { - /* Add header to size */ - size += pos; + /* Add header to size */ + size += pos; - g_byte_array_set_size(priv->rbuf, size); - priv->remz = size; + g_byte_array_set_size(priv->rbuf, size); + priv->remz = size; - /* TODO: Use g_input_stream_read_all_async() when available. */ - /* TODO: Alternately, it would be nice to let the - * FbMqttMessage directly use the GBufferedInputStream - * buffer instead of copying it, provided it's consumed - * before the next read. - */ - g_input_stream_read_async(G_INPUT_STREAM(priv->input), - priv->rbuf->data, priv->rbuf->len, - G_PRIORITY_DEFAULT, priv->cancellable, - fb_mqtt_cb_read_packet, mqtt); - } else { - g_buffered_input_stream_fill_async(priv->input, -1, - G_PRIORITY_DEFAULT, priv->cancellable, - fb_mqtt_cb_fill, mqtt); - } + /* TODO: Use g_input_stream_read_all_async() when available. */ + /* TODO: Alternately, it would be nice to let the + * FbMqttMessage directly use the GBufferedInputStream + * buffer instead of copying it, provided it's consumed + * before the next read. + */ + g_input_stream_read_async(G_INPUT_STREAM(priv->input), + priv->rbuf->data, priv->rbuf->len, + G_PRIORITY_DEFAULT, priv->cancellable, + fb_mqtt_cb_read_packet, mqtt); } void
--- a/libpurple/protocols/jabber/tests/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/jabber/tests/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -33,5 +33,4 @@ $(GPLUGIN_CFLAGS) \ $(PLUGIN_CFLAGS) \ $(DBUS_CFLAGS) \ - $(LIBXML_CFLAGS) \ - $(NSS_CFLAGS) + $(LIBXML_CFLAGS)
--- a/libpurple/protocols/oscar/tests/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/oscar/tests/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -19,5 +19,4 @@ $(GLIB_CFLAGS) \ $(GPLUGIN_CFLAGS) \ $(PLUGIN_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(NSS_CFLAGS) + $(DBUS_CFLAGS)
--- a/libpurple/protocols/simple/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/simple/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -14,6 +14,7 @@ AM_CFLAGS = $(st) libsimple_la_LDFLAGS = -module @PLUGIN_LDFLAGS@ +libsimple_la_LIBADD = $(NETTLE_LIBS) if STATIC_SIMPLE @@ -27,7 +28,7 @@ st = pkg_LTLIBRARIES = libsimple.la libsimple_la_SOURCES = $(SIMPLESOURCES) -libsimple_la_LIBADD = @PURPLE_LIBS@ +libsimple_la_LIBADD += @PURPLE_LIBS@ endif @@ -36,4 +37,5 @@ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ $(GPLUGIN_CFLAGS) \ - $(DEBUG_CFLAGS) + $(DEBUG_CFLAGS) \ + $(NETTLE_CFLAGS)
--- a/libpurple/protocols/simple/ntlm.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/simple/ntlm.c Fri Jun 30 15:03:16 2017 +0300 @@ -26,8 +26,10 @@ #include "ntlm.h" #include "debug.h" -#include "ciphers/descipher.h" -#include "ciphers/md4hash.h" +#ifdef HAVE_NETTLE +#include <nettle/des.h> +#include <nettle/md4.h> +#endif #include <string.h> @@ -112,6 +114,7 @@ return nonce; } +#ifdef HAVE_NETTLE /* * Create a 64bit DES key by taking a 56bit key and adding * a parity bit after every 7th bit. @@ -130,19 +133,15 @@ } /* - * helper function for purple cipher.c + * helper function for des encryption */ static void des_ecb_encrypt(const guint8 *plaintext, guint8 *result, const guint8 *key) { - PurpleCipher *cipher; - gssize encsiz; + struct des_ctx ctx; - cipher = purple_des_cipher_new(); - purple_cipher_set_key(cipher, key, 8); - encsiz = purple_cipher_encrypt(cipher, plaintext, 8, result, 8); - g_warn_if_fail(encsiz == 8); - g_object_unref(cipher); + des_set_key(&ctx, key); + des_encrypt(&ctx, DES_BLOCK_SIZE, result, plaintext); } /* @@ -201,10 +200,12 @@ buffer[i] = (char)(g_random_int() & 0xff); } } +#endif /* HAVE_NETTLE */ gchar * purple_ntlm_gen_type3(const gchar *username, const gchar *passw, const gchar *hostname, const gchar *domain, const guint8 *nonce, guint32 *flags) { +#ifdef HAVE_NETTLE char lm_pw[14]; unsigned char lm_hpw[21]; char sesskey[16]; @@ -219,7 +220,7 @@ unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; unsigned char nt_hpw[21]; char nt_pw[128]; - PurpleHash *hash; + struct md4_ctx ctx; char *tmp; int idx; gchar *ucs2le; @@ -320,10 +321,9 @@ nt_pw[2 * idx + 1] = 0; } - hash = purple_md4_hash_new(); - purple_hash_append(hash, (guint8 *)nt_pw, 2 * lennt); - purple_hash_digest(hash, nt_hpw, sizeof(nt_hpw)); - g_object_unref(hash); + md4_init(&ctx); + md4_update(&ctx, 2 * lennt, (uint8_t *)nt_pw); + md4_digest(&ctx, MD4_DIGEST_SIZE, nt_hpw); memset(nt_hpw + 16, 0, 5); calc_resp(nt_hpw, nonce, nt_resp); @@ -344,4 +344,8 @@ g_free(tmsg); return tmp; +#else + /* Used without support enabled */ + g_return_val_if_reached(NULL); +#endif /* HAVE_NETTLE */ }
--- a/libpurple/protocols/simple/simple.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/simple/simple.c Fri Jun 30 15:03:16 2017 +0300 @@ -265,11 +265,8 @@ gchar noncecount[9]; gchar *response; gchar *ret; - gchar *tmp; - const char *authdomain; const char *authuser; - authdomain = purple_account_get_string(sip->account, "authdomain", ""); authuser = purple_account_get_string(sip->account, "authuser", sip->username); if(!authuser || strlen(authuser) < 1) { @@ -287,6 +284,13 @@ g_free(response); return ret; } else if(auth->type == 2) { /* NTLM */ +#ifdef HAVE_NETTLE + const gchar *authdomain; + gchar *tmp; + + authdomain = purple_account_get_string(sip->account, + "authdomain", ""); + if(auth->nc == 3 && auth->nonce) { /* TODO: Don't hardcode "purple" as the hostname */ ret = purple_ntlm_gen_type3(authuser, sip->password, "purple", authdomain, (const guint8 *)auth->nonce, &auth->flags); @@ -296,6 +300,10 @@ } tmp = g_strdup_printf("NTLM qop=\"auth\", realm=\"%s\", targetname=\"%s\", gssapi-data=\"\"", auth->realm, auth->target); return tmp; +#else + /* Used without support enabled */ + g_return_val_if_reached(NULL); +#endif /* HAVE_NETTLE */ } sprintf(noncecount, "%08d", auth->nc++); @@ -350,6 +358,7 @@ } if(!g_ascii_strncasecmp(hdr, "NTLM", 4)) { +#ifdef HAVE_NETTLE purple_debug_info("simple", "found NTLM\n"); auth->type = 2; parts = g_strsplit(hdr+5, "\",", 0); @@ -382,6 +391,11 @@ } return; +#else + purple_debug_error("simple", "NTLM auth unsupported without " + "libnettle support. Please rebuild with " + "libnettle support for this feature.\n"); +#endif /* HAVE_NETTLE */ } else if(!g_ascii_strncasecmp(hdr, "DIGEST", 6)) { purple_debug_info("simple", "found DIGEST\n");
--- a/libpurple/protocols/simple/simple.h Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/protocols/simple/simple.h Fri Jun 30 15:03:16 2017 +0300 @@ -28,7 +28,6 @@ #include <gio/gio.h> #include <time.h> -#include "cipher.h" #include "circularbuffer.h" #include "network.h" #include "proxy.h"
--- a/libpurple/purple.h.in Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/purple.h.in Fri Jun 30 15:03:16 2017 +0300 @@ -53,7 +53,6 @@ #include <accountopt.h> #include <buddylist.h> #include <buddyicon.h> -#include <cipher.h> #include <circularbuffer.h> #include <cmds.h> #include <connection.h>
--- a/libpurple/smiley-list.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/smiley-list.c Fri Jun 30 15:03:16 2017 +0300 @@ -26,6 +26,8 @@ #include "smiley-parser.h" #include "trie.h" +#include <string.h> + #define PURPLE_SMILEY_LIST_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SMILEY_LIST, \ PurpleSmileyListPrivate))
--- a/libpurple/stun.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/stun.c Fri Jun 30 15:03:16 2017 +0300 @@ -254,7 +254,7 @@ ifc.ifc_req = buffer_ifr; ioctl(source, SIOCGIFCONF, &ifc); - it = buffer; + it = (guchar *)buffer_ifr; it_end = it + ifc.ifc_len; while (it < it_end) { ifr = (struct ifreq*)(gpointer)it;
--- a/libpurple/tests/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/tests/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -6,28 +6,16 @@ $(GPLUGIN_LIBS) test_programs=\ - test_des \ - test_des3 \ test_image \ - test_md4 \ test_smiley \ test_smiley_list \ test_trie \ test_util \ test_xmlnode -test_des_SOURCES=test_des.c -test_des_LDADD=$(COMMON_LIBS) - -test_des3_SOURCES=test_des3.c -test_des3_LDADD=$(COMMON_LIBS) - test_image_SOURCES=test_image.c test_image_LDADD=$(COMMON_LIBS) -test_md4_SOURCES=test_md4.c -test_md4_LDADD=$(COMMON_LIBS) - test_smiley_SOURCES=test_smiley.c test_smiley_LDADD=$(COMMON_LIBS) @@ -51,8 +39,7 @@ $(GLIB_CFLAGS) \ $(GPLUGIN_CFLAGS) \ $(PLUGIN_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(NSS_CFLAGS) + $(DBUS_CFLAGS) EXTRA_DIST += \ data/test-image.png
--- a/libpurple/tests/test_des.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - */ -#include <glib.h> - -#include <purple.h> - -#include "ciphers/descipher.h" - -static void -test_des_cipher(const gchar *in, const gchar *key, const gchar *out, size_t len) { - PurpleCipher *cipher = NULL; - guchar *decrypt = NULL, *encrypt = NULL, *answer = NULL; - size_t ret = 0; - - decrypt = g_memdup(in, len + 1); - encrypt = g_memdup(out, len + 1); - - cipher = purple_des_cipher_new(); - - purple_cipher_set_key(cipher, (const guchar *)key, 8); - - answer = g_new0(guchar, len + 1); - ret = purple_cipher_encrypt(cipher, decrypt, len, answer, len); - g_assert(ret == len); - g_assert_cmpmem(encrypt, len, answer, len); - g_free(answer); - - answer = g_new0(guchar, len + 1); - ret = purple_cipher_decrypt(cipher, encrypt, len, answer, len); - g_assert(ret == len); - g_assert_cmpmem(decrypt, len, answer, len); - g_free(answer); - - g_free(encrypt); - g_free(decrypt); - - g_object_unref(G_OBJECT(cipher)); -} - -static void -test_des_cipher_12345678(void) { - test_des_cipher( - "12345678", - "\x3b\x38\x98\x37\x15\x20\xf7\x5e", - "\x06\x22\x05\xac\x6a\x0d\x55\xdd", - 8 - ); -} - -static void -test_des_cipher_abcdefgh(void) { - test_des_cipher( - "abcdefgh", - "\x3b\x38\x98\x37\x15\x20\xf7\x5e", - "\x62\xe0\xc6\x8c\x48\xe4\x75\xed", - 8 - ); -} - -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/cipher/des/12345678", - test_des_cipher_12345678); - - g_test_add_func("/cipher/des/abcdefgh", - test_des_cipher_abcdefgh); - - return g_test_run(); -}
--- a/libpurple/tests/test_des3.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - */ -#include <glib.h> - -#include <purple.h> - -#include "ciphers/des3cipher.h" - -/****************************************************************************** - * DES3 Tests - * See http://csrc.nist.gov/groups/ST/toolkit/examples.html - * and some NULL things I made up - *****************************************************************************/ -static void -test_des3_cipher(const gchar *in, const gchar *key, const gchar *iv, - const gchar *out, size_t len, PurpleCipherBatchMode mode) -{ - PurpleCipher *cipher = NULL; - guchar *decrypt = NULL, *encrypt = NULL, *answer = NULL; - size_t ret = 0; - - decrypt = g_memdup(in, len + 1); - encrypt = g_memdup(out, len + 1); - - cipher = purple_des3_cipher_new(); - - purple_cipher_set_key(cipher, (const guchar *)key, 24); - purple_cipher_set_batch_mode(cipher, mode); - purple_cipher_set_iv(cipher, (guchar *)iv, 8); - - answer = g_new0(guchar, len + 1); - ret = purple_cipher_encrypt(cipher, decrypt, len, answer, len); - g_assert(ret == len); - g_assert_cmpmem(encrypt, len, answer, len); - g_free(answer); - - answer = g_new0(guchar, len + 1); - ret = purple_cipher_decrypt(cipher, encrypt, len, answer, len); - g_assert(ret == len); - g_assert_cmpmem(decrypt, len, answer, len); - g_free(answer); - - g_free(encrypt); - g_free(decrypt); - - g_object_unref(G_OBJECT(cipher)); -} - -static void -test_des3_cipher_ecb_nist1(void) { - test_des3_cipher( - "\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A" - "\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51", - "\x01\x23\x45\x67\x89\xAB\xCD\xEF" - "\x23\x45\x67\x89\xAB\xCD\xEF\x01" - "\x45\x67\x89\xAB\xCD\xEF\x01\x23", - "00000000", /* ignored */ - "\x71\x47\x72\xF3\x39\x84\x1D\x34\x26\x7F\xCC\x4B\xD2\x94\x9C\xC3" - "\xEE\x11\xC2\x2A\x57\x6A\x30\x38\x76\x18\x3F\x99\xC0\xB6\xDE\x87", - 32, - PURPLE_CIPHER_BATCH_MODE_ECB - ); -} - -static void -test_des3_cipher_ecb_nist2(void) { - test_des3_cipher( - "\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A" - "\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51", - "\x01\x23\x45\x67\x89\xAB\xCD\xEF" - "\x23\x45\x67\x89\xAB\xCD\xEF\x01" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF", - "00000000", /* ignored */ - "\x06\xED\xE3\xD8\x28\x84\x09\x0A\xFF\x32\x2C\x19\xF0\x51\x84\x86" - "\x73\x05\x76\x97\x2A\x66\x6E\x58\xB6\xC8\x8C\xF1\x07\x34\x0D\x3D", - 32, - PURPLE_CIPHER_BATCH_MODE_ECB - ); -} - -static void -test_des3_cipher_ecb_null_key(void) { - test_des3_cipher( - "\x16\xf4\xb3\x77\xfd\x4b\x9e\xca", - "\x38\x00\x88\x6a\xef\xcb\x00\xad" - "\x5d\xe5\x29\x00\x7d\x98\x64\x4c" - "\x86\x00\x7b\xd3\xc7\x00\x7b\x32", - "00000000", /* ignored */ - "\xc0\x60\x30\xa1\xb7\x25\x42\x44", - 8, - PURPLE_CIPHER_BATCH_MODE_ECB - ); -} - -static void -test_des3_cipher_ecb_null_text(void) { - test_des3_cipher( - "\x65\x73\x34\xc1\x19\x00\x79\x65", - "\x32\x64\xda\x10\x13\x6a\xfe\x1e" - "\x37\x54\xd1\x2c\x41\x04\x10\x40" - "\xaf\x1c\x75\x2b\x51\x3a\x03\xf5", - "00000000", /* ignored */ - "\xe5\x80\xf6\x12\xf8\x4e\xd9\x6c", - 8, - PURPLE_CIPHER_BATCH_MODE_ECB - ); -} - -static void -test_des3_cipher_ecb_null_key_and_text(void) { - test_des3_cipher( - "\xdf\x7f\x00\x92\xe7\xc1\x49\xd2", - "\x0e\x41\x00\xc4\x8b\xf0\x6e\xa1" - "\x66\x49\x42\x63\x22\x00\xf0\x99" - "\x6b\x22\xc1\x37\x9c\x00\xe4\x8f", - "00000000", /* ignored */ - "\x73\xd8\x1f\x1f\x50\x01\xe4\x79", - 8, - PURPLE_CIPHER_BATCH_MODE_ECB - ); -} - -static void -test_des3_cipher_cbc_nist1(void) { - test_des3_cipher( - "\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A" - "\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51", - "\x01\x23\x45\x67\x89\xAB\xCD\xEF" - "\x23\x45\x67\x89\xAB\xCD\xEF\x01" - "\x45\x67\x89\xAB\xCD\xEF\x01\x23", - "\xF6\x9F\x24\x45\xDF\x4F\x9B\x17", - "\x20\x79\xC3\xD5\x3A\xA7\x63\xE1\x93\xB7\x9E\x25\x69\xAB\x52\x62" - "\x51\x65\x70\x48\x1F\x25\xB5\x0F\x73\xC0\xBD\xA8\x5C\x8E\x0D\xA7", - 32, - PURPLE_CIPHER_BATCH_MODE_CBC - ); -} - -static void -test_des3_cipher_cbc_nist2(void) { - test_des3_cipher( - "\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A" - "\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51", - "\x01\x23\x45\x67\x89\xAB\xCD\xEF" - "\x23\x45\x67\x89\xAB\xCD\xEF\x01" - "\x01\x23\x45\x67\x89\xAB\xCD\xEF", - "\xF6\x9F\x24\x45\xDF\x4F\x9B\x17", - "\x74\x01\xCE\x1E\xAB\x6D\x00\x3C\xAF\xF8\x4B\xF4\x7B\x36\xCC\x21" - "\x54\xF0\x23\x8F\x9F\xFE\xCD\x8F\x6A\xCF\x11\x83\x92\xB4\x55\x81", - 32, - PURPLE_CIPHER_BATCH_MODE_CBC - ); -} - -static void -test_des3_cipher_cbc_null_key(void) { - test_des3_cipher( - "\x16\xf4\xb3\x77\xfd\x4b\x9e\xca", - "\x38\x00\x88\x6a\xef\xcb\x00\xad" - "\x5d\xe5\x29\x00\x7d\x98\x64\x4c" - "\x86\x00\x7b\xd3\xc7\x00\x7b\x32", - "\x31\x32\x33\x34\x35\x36\x37\x38", - "\x52\xe7\xde\x96\x39\x87\x87\xdb", - 8, - PURPLE_CIPHER_BATCH_MODE_CBC - ); -} - -static void -test_des3_cipher_cbc_null_text(void) { - test_des3_cipher( - "\x65\x73\x34\xc1\x19\x00\x79\x65", - "\x32\x64\xda\x10\x13\x6a\xfe\x1e" - "\x37\x54\xd1\x2c\x41\x04\x10\x40" - "\xaf\x1c\x75\x2b\x51\x3a\x03\xf5", - "\x7C\xAF\x0D\x57\x1E\x57\x10\xDA", - "\x40\x12\x0e\x00\x85\xff\x6c\xc2", - 8, - PURPLE_CIPHER_BATCH_MODE_CBC - ); -} - -static void -test_des3_cipher_cbc_null_key_and_text(void) { - test_des3_cipher( - "\xdf\x7f\x00\x92\xe7\xc1\x49\xd2", - "\x0e\x41\x00\xc4\x8b\xf0\x6e\xa1" - "\x66\x49\x42\x63\x22\x00\xf0\x99" - "\x6b\x22\xc1\x37\x9c\x00\xe4\x8f", - "\x01\x19\x0D\x2c\x40\x67\x89\x67", - "\xa7\xc1\x10\xbe\x9b\xd5\x8a\x67", - 8, - PURPLE_CIPHER_BATCH_MODE_CBC - ); -} - - -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/cipher/des3/ecb nist1", - test_des3_cipher_ecb_nist1); - g_test_add_func("/cipher/des3/ecb nist2", - test_des3_cipher_ecb_nist2); - g_test_add_func("/cipher/des3/ecb null key", - test_des3_cipher_ecb_null_key); - g_test_add_func("/cipher/des3/ecb null text", - test_des3_cipher_ecb_null_text); - g_test_add_func("/cipher/des3/ebc null key and text", - test_des3_cipher_ecb_null_key_and_text); - - g_test_add_func("/cipher/des3/cbc nist1", - test_des3_cipher_cbc_nist1); - g_test_add_func("/cipher/des3/cbc nist2", - test_des3_cipher_cbc_nist2); - g_test_add_func("/cipher/des3/cbc null key", - test_des3_cipher_cbc_null_key); - g_test_add_func("/cipher/des3/cbc null text", - test_des3_cipher_cbc_null_text); - g_test_add_func("/cipher/des3/cbc null key and text", - test_des3_cipher_cbc_null_key_and_text); - - return g_test_run(); -}
--- a/libpurple/tests/test_image.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/tests/test_image.c Fri Jun 30 15:03:16 2017 +0300 @@ -21,6 +21,7 @@ */ #include <glib.h> +#include <string.h> #include <purple.h>
--- a/libpurple/tests/test_md4.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - */ -#include <glib.h> - -#include <purple.h> - -#include "ciphers/md4hash.h" - -static void -test_md4hash(gchar *data, gchar *digest) { - PurpleHash *hash = NULL; - gchar cdigest[33]; - gboolean ret = FALSE; - - hash = purple_md4_hash_new(); - - purple_hash_append(hash, (guchar *)data, strlen(data)); - - ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); - - g_assert(ret); - g_assert_cmpstr(digest, ==, cdigest); -} - -static void -test_md4hash_empty_string(void) { - test_md4hash("", - "31d6cfe0d16ae931b73c59d7e0c089c0"); -} - -static void -test_md4hash_a(void) { - test_md4hash("a", - "bde52cb31de33e46245e05fbdbd6fb24"); -} - -static void -test_md4hash_abc(void) { - test_md4hash("abc", - "a448017aaf21d8525fc10ae87aa6729d"); -} - -static void -test_md4hash_message_digest(void) { - test_md4hash("message digest", - "d9130a8164549fe818874806e1c7014b"); -} - -static void -test_md4hash_a_to_z(void) { - test_md4hash("abcdefghijklmnopqrstuvwxyz", - "d79e1c308aa5bbcdeea8ed63df412da9"); -} - -static void -test_md4hash_A_to_Z_a_to_z_0_to_9(void) { - test_md4hash("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "043f8582f241db351ce627e153e7f0e4"); -} - -static void -test_md4hash_1_to_0_eight_times(void) { - test_md4hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890", - "e33b4ddc9c38f2199c3e7b164fcc0536"); -} - -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/hash/md4/empty-string", - test_md4hash_empty_string); - g_test_add_func("/hash/md4/a", - test_md4hash_a); - g_test_add_func("/hash/md4/abc", - test_md4hash_abc); - g_test_add_func("/hash/md4/message digest", - test_md4hash_message_digest); - g_test_add_func("/hash/md4/a to z", - test_md4hash_a_to_z); - g_test_add_func("/hash/md4/A to Z, a to z, 0 to 9" , - test_md4hash_A_to_Z_a_to_z_0_to_9); - g_test_add_func("/hash/md4/1 to 0 eight times", - test_md4hash_1_to_0_eight_times); - - return g_test_run(); -}
--- a/libpurple/tests/test_smiley.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/tests/test_smiley.c Fri Jun 30 15:03:16 2017 +0300 @@ -21,6 +21,7 @@ */ #include <glib.h> +#include <string.h> #include <purple.h>
--- a/libpurple/xfer.c Thu Jun 15 10:48:26 2017 +0300 +++ b/libpurple/xfer.c Fri Jun 30 15:03:16 2017 +0300 @@ -1920,12 +1920,14 @@ gsize size, const gchar *mimetype) { PurpleXferPrivate *priv = PURPLE_XFER_GET_PRIVATE(xfer); + gpointer old_thumbnail_data; + gchar *old_mimetype; g_return_if_fail(priv != NULL); /* Hold onto these in case they are equal to passed-in pointers */ - gpointer *old_thumbnail_data = priv->thumbnail_data; - const gchar *old_mimetype = priv->thumbnail_mimetype; + old_thumbnail_data = priv->thumbnail_data; + old_mimetype = priv->thumbnail_mimetype; if (thumbnail && size > 0) { priv->thumbnail_data = g_memdup(thumbnail, size);
--- a/pidgin/Makefile.am Thu Jun 15 10:48:26 2017 +0300 +++ b/pidgin/Makefile.am Fri Jun 30 15:03:16 2017 +0300 @@ -4,6 +4,7 @@ getopt1.c \ gtk3compat.h \ gtkdebug.html \ + pidgin.gresource.xml \ Makefile.mingw \ data/pidgin.appdata.xml.in \ data/pidgin.desktop.in \ @@ -55,7 +56,6 @@ gtkdialogs.c \ gtkdnd-hints.c \ gtkdocklet.c \ - gtkeventloop.c \ gtkicon-theme.c \ gtkicon-theme-loader.c \ gtkidle.c \ @@ -72,7 +72,6 @@ gtkroomlist.c \ gtksavedstatuses.c \ gtkscrollbook.c \ - gtksession.c \ gtksmiley-manager.c \ gtksmiley-theme.c \ gtksound.c \ @@ -85,6 +84,7 @@ gtkxfer.c \ libpidgin.c \ minidialog.c \ + pidgin.gresource.c \ pidgintooltip.c libpidgin_la_headers = \ @@ -103,7 +103,6 @@ gtkdialogs.h \ gtkdnd-hints.h \ gtkdocklet.h \ - gtkeventloop.h \ gtkicon-theme.h \ gtkicon-theme-loader.h \ gtkidle.h \ @@ -121,7 +120,6 @@ gtkroomlist.h \ gtksavedstatuses.h \ gtkscrollbook.h \ - gtksession.h \ gtksmiley-manager.h \ gtksmiley-theme.h \ gtksound.h \ @@ -172,18 +170,22 @@ libpidgininclude_HEADERS = \ $(libpidgin_la_headers) -libpidgin_la_builtheaders = gtkdebug.html.h +libpidgin_la_builtheaders = pidgin.gresource.h +libpidgin_la_builtsources = pidgin.gresource.c -BUILT_SOURCES = $(libpidgin_la_builtheaders) +BUILT_SOURCES = $(libpidgin_la_builtheaders) $(libpidgin_la_builtsources) -CLEANFILES = gtkdebug.html.h +CLEANFILES = pidgin.gresource.h pidgin.gresource.c -%.html.h: %.html - $(AM_V_GEN)echo "static const char $*_html[] = {" > $@ - $(AM_V_at)$(sedpath) -e 's/^[ ]\+//g' -e 's/[ ]\+/ /g' $< | $(xxdpath) -i | sed -e 's/\(0x[0-9a-f][0-9a-f]\)$$/\1, 0x00/' >> $@ - $(AM_V_at)echo "};" >> $@ +%.gresource.h: %.gresource.xml + $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --generate-header --target $@ --c-name $* --sourcedir $(srcdir) $< -gtkdebug.c: gtkdebug.html.h +%.gresource.c: %.gresource.xml + $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --generate-source --target $@ --c-name $* --sourcedir $(srcdir) $< + +pidgin.gresource.c: gtkdebug.html +pidgin.gresource.h: gtkdebug.html +gtkdebug.c: pidgin.gresource.h libpidgin_la_DEPENDENCIES = @LIBOBJS@ $(LIBPIDGIN_WIN32RES) libpidgin_la_LDFLAGS = -export-dynamic -no-undefined \ @@ -199,7 +201,6 @@ $(GSTVIDEO_LIBS) \ $(GSTINTERFACES_LIBS) \ $(XSS_LIBS) \ - $(SM_LIBS) \ $(INTLLIBS) \ $(LIBXML_LIBS) \ $(WEBKIT_LIBS) \
--- a/pidgin/Makefile.mingw Thu Jun 15 10:48:26 2017 +0300 +++ b/pidgin/Makefile.mingw Fri Jun 30 15:03:16 2017 +0300 @@ -71,7 +71,6 @@ gtkdialogs.c \ gtkdnd-hints.c \ gtkdocklet.c \ - gtkeventloop.c \ gtkicon-theme-loader.c \ gtkicon-theme.c \ gtkidle.c \
--- a/pidgin/gtkdebug.c Thu Jun 15 10:48:26 2017 +0300 +++ b/pidgin/gtkdebug.c Fri Jun 30 15:03:16 2017 +0300 @@ -40,7 +40,7 @@ #include "gtk3compat.h" -#include "gtkdebug.html.h" +#include "pidgin.gresource.h" typedef struct { @@ -409,7 +409,10 @@ static DebugWindow * debug_window_new(void) { + GError *error; DebugWindow *win; + GResource *resource; + GBytes *resource_bytes; GtkWidget *vbox; GtkWidget *toolbar; GtkWidget *frame; @@ -586,7 +589,25 @@ frame = pidgin_create_webview(FALSE, &win->text, NULL); pidgin_webview_set_format_functions(PIDGIN_WEBVIEW(win->text), PIDGIN_WEBVIEW_ALL ^ PIDGIN_WEBVIEW_SMILEY ^ PIDGIN_WEBVIEW_IMAGE); - pidgin_webview_load_html_string(PIDGIN_WEBVIEW(win->text), gtkdebug_html); + resource = pidgin_get_resource(); + error = NULL; + resource_bytes = g_resource_lookup_data(resource, + "/im/pidgin/Pidgin/gtkdebug.html", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + if (G_UNLIKELY(resource_bytes == NULL || error != NULL)) { + gchar *msg = g_strdup_printf("Unable to load debug window HTML: %s\n", + error ? error->message : "Unknown error"); + g_clear_error(&error); + pidgin_webview_load_html_string(PIDGIN_WEBVIEW(win->text), msg); + g_free(msg); + } else { + gconstpointer gtkdebug_html; + gtkdebug_html = g_bytes_get_data(resource_bytes, NULL); + pidgin_webview_load_html_string(PIDGIN_WEBVIEW(win->text), + gtkdebug_html); + } + g_bytes_unref(resource_bytes); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_widget_show(frame);
--- a/pidgin/gtkdialogs.c Thu Jun 15 10:48:26 2017 +0300 +++ b/pidgin/gtkdialogs.c Fri Jun 30 15:03:16 2017 +0300 @@ -696,12 +696,6 @@ #endif #ifndef _WIN32 -#ifdef USE_SM - g_string_append(str, "<dt>X Session Management:</dt><dd>Enabled</dd>"); -#else - g_string_append(str, "<dt>X Session Management:</dt><dd>Disabled</dd>"); -#endif - #ifdef USE_SCREENSAVER g_string_append(str, "<dt>XScreenSaver:</dt><dd>Enabled</dd>"); #else
--- a/pidgin/gtkeventloop.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/* pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include <glib.h> -#include "gtkeventloop.h" -#include "eventloop.h" -#include "internal.h" - -#define PIDGIN_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) -#define PIDGIN_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) - -typedef struct _PidginIOClosure { - PurpleInputFunction function; - guint result; - gpointer data; - -} PidginIOClosure; - -static gboolean pidgin_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) -{ - PidginIOClosure *closure = data; - PurpleInputCondition purple_cond = 0; - - if (condition & PIDGIN_READ_COND) - purple_cond |= PURPLE_INPUT_READ; - if (condition & PIDGIN_WRITE_COND) - purple_cond |= PURPLE_INPUT_WRITE; - -#if 0 - purple_debug_misc("gtk_eventloop", - "CLOSURE: callback for %d, fd is %d\n", - closure->result, g_io_channel_unix_get_fd(source)); -#endif - -#ifdef _WIN32 - if(! purple_cond) { -#if 0 - purple_debug_misc("gtk_eventloop", - "CLOSURE received GIOCondition of 0x%x, which does not" - " match 0x%x (READ) or 0x%x (WRITE)\n", - condition, PIDGIN_READ_COND, PIDGIN_WRITE_COND); -#endif /* DEBUG */ - - return TRUE; - } -#endif /* _WIN32 */ - - closure->function(closure->data, g_io_channel_unix_get_fd(source), - purple_cond); - - return TRUE; -} - -static guint pidgin_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function, - gpointer data) -{ - PidginIOClosure *closure = g_new0(PidginIOClosure, 1); - GIOChannel *channel; - GIOCondition cond = 0; - - closure->function = function; - closure->data = data; - - if (condition & PURPLE_INPUT_READ) - cond |= PIDGIN_READ_COND; - if (condition & PURPLE_INPUT_WRITE) - cond |= PIDGIN_WRITE_COND; - -#ifdef _WIN32 - channel = g_io_channel_win32_new_socket(fd); -#else - channel = g_io_channel_unix_new(fd); -#endif - - closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, - pidgin_io_invoke, closure, g_free); - -#if 0 - purple_debug_misc("gtk_eventloop", - "CLOSURE: adding input watcher %d for fd %d\n", - closure->result, fd); -#endif - - g_io_channel_unref(channel); - return closure->result; -} - -static PurpleEventLoopUiOps eventloop_ops = -{ - g_timeout_add, - g_source_remove, - pidgin_input_add, - g_source_remove, - NULL, /* input_get_error */ - g_timeout_add_seconds, - NULL, - NULL, - NULL, - NULL -}; - -PurpleEventLoopUiOps * -pidgin_eventloop_get_ui_ops(void) -{ - return &eventloop_ops; -}
--- a/pidgin/gtkeventloop.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _PIDGINEVENTLOOP_H_ -#define _PIDGINEVENTLOOP_H_ -/** - * SECTION:gtkeventloop - * @section_id: pidgin-gtkeventloop - * @short_description: <filename>gtkeventloop.h</filename> - * @title: Event Loop Implementation - */ - -#include "eventloop.h" - -G_BEGIN_DECLS - -/** - * pidgin_eventloop_get_ui_ops: - * - * Returns the GTK+ event loop UI operations structure. - * - * Returns: The GTK+ event loop UI operations structure. - */ -PurpleEventLoopUiOps *pidgin_eventloop_get_ui_ops(void); - -G_END_DECLS - -#endif /* _PIDGINEVENTLOOP_H_ */
--- a/pidgin/gtksession.c Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ -/* Pidgin is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - */ -#include "internal.h" - -#include "core.h" -#include "debug.h" -#include "eventloop.h" -#include "gtksession.h" - -#ifdef USE_SM - -#include <X11/ICE/ICElib.h> -#include <X11/SM/SMlib.h> -#include <gdk/gdkx.h> -#include <unistd.h> -#include <fcntl.h> -#include <gdk/gdk.h> -#include <gtk/gtk.h> - -#include "gtk3compat.h" - -#define ERROR_LENGTH 512 - -static IceIOErrorHandler ice_installed_io_error_handler; -static SmcConn session = NULL; -static gchar *myself = NULL; -static gboolean had_first_save = FALSE; -static gboolean session_managed = FALSE; - -/* ICE belt'n'braces stuff */ - -struct ice_connection_info { - IceConn connection; - guint input_id; -}; - -static void ice_process_messages(gpointer data, gint fd, - PurpleInputCondition condition) { - struct ice_connection_info *conninfo = (struct ice_connection_info*) data; - IceProcessMessagesStatus status; - - /* please don't block... please! */ - status = IceProcessMessages(conninfo->connection, NULL, NULL); - - if (status == IceProcessMessagesIOError) { - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "ICE IO error, closing connection... "); - - /* IO error, please disconnect */ - IceSetShutdownNegotiation(conninfo->connection, False); - IceCloseConnection(conninfo->connection); - - if (purple_debug_is_verbose()) { - purple_debug_misc("Session Management", - "Connection closed."); - } - - /* cancel the handler */ - purple_input_remove(conninfo->input_id); - } -} - -static void ice_connection_watch(IceConn connection, IcePointer client_data, - Bool opening, IcePointer *watch_data) { - struct ice_connection_info *conninfo = NULL; - - if (opening) { - purple_debug_misc("Session Management", - "Handling new ICE connection..."); - - /* ensure ICE connection is not passed to child processes */ - if (fcntl(IceConnectionNumber(connection), F_SETFD, FD_CLOEXEC) != 0) - purple_debug_warning("gtksession", "couldn't set FD_CLOEXEC\n"); - - conninfo = g_new(struct ice_connection_info, 1); - conninfo->connection = connection; - - /* watch the connection */ - conninfo->input_id = purple_input_add(IceConnectionNumber(connection), PURPLE_INPUT_READ, - ice_process_messages, conninfo); - *watch_data = conninfo; - } else { - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Handling closed ICE connection... \n"); - - /* get the input ID back and stop watching it */ - conninfo = (struct ice_connection_info*) *watch_data; - purple_input_remove(conninfo->input_id); - g_free(conninfo); - } - - if (purple_debug_is_verbose()) { - purple_debug_misc("Session Management", - "ICE connection handled."); - } -} - -/* We call any handler installed before (or after) ice_init but - * avoid calling the default libICE handler which does an exit(). - * - * This means we do nothing by default, which is probably correct, - * the connection will get closed by libICE - */ - -static void ice_io_error_handler(IceConn connection) { - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Handling ICE IO error... "); - - if (ice_installed_io_error_handler) - (*ice_installed_io_error_handler)(connection); - - if (purple_debug_is_verbose()) { - purple_debug_misc("Session Management", - "ICE IO error handled."); - } -} - -static void ice_init(void) { - IceIOErrorHandler default_handler; - - ice_installed_io_error_handler = IceSetIOErrorHandler(NULL); - default_handler = IceSetIOErrorHandler(ice_io_error_handler); - - if (ice_installed_io_error_handler == default_handler) - ice_installed_io_error_handler = NULL; - - IceAddConnectionWatch(ice_connection_watch, NULL); - - if (purple_debug_is_verbose()) { - purple_debug_misc("Session Management", "ICE initialized."); - } -} - -/* my magic utility function */ - -static gchar **session_make_command(gchar *client_id, gchar *config_dir) { - gint i = 4; - gint j = 0; - gchar **ret; - - if (client_id) i += 2; - if (config_dir) i += 2; /* we will specify purple's user dir */ - - ret = g_new(gchar *, i); - ret[j++] = g_strdup(myself); - - if (client_id) { - ret[j++] = g_strdup("--session"); - ret[j++] = g_strdup(client_id); - } - - if (config_dir) { - ret[j++] = g_strdup("--config"); - ret[j++] = g_strdup(config_dir); - } - - ret[j++] = g_strdup("--display"); - ret[j++] = g_strdup((gchar *)gdk_display_get_name(gdk_display_get_default())); - - ret[j] = NULL; - - return ret; -} - -/* SM callback handlers */ - -static void session_save_yourself(SmcConn conn, SmPointer data, int save_type, - Bool shutdown, int interact_style, Bool fast) { - if (had_first_save == FALSE && save_type == SmSaveLocal && - interact_style == SmInteractStyleNone && !shutdown && - !fast) { - /* this is just a dry run, spit it back */ - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Received first save_yourself\n"); - SmcSaveYourselfDone(conn, True); - had_first_save = TRUE; - return; - } - - /* tum ti tum... don't add anything else here without * - * reading SMlib.PS from an X.org ftp server near you */ - - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Received save_yourself\n"); - - if (save_type == SmSaveGlobal || save_type == SmSaveBoth) { - /* may as well do something ... */ - /* or not -- save_prefs(); */ - } - - SmcSaveYourselfDone(conn, True); -} - -static void session_die(SmcConn conn, SmPointer data) { - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Received die\n"); - purple_core_quit(); -} - -static void session_save_complete(SmcConn conn, SmPointer data) { - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Received save_complete\n"); -} - -static void session_shutdown_cancelled(SmcConn conn, SmPointer data) { - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Received shutdown_cancelled\n"); -} - -/* utility functions stolen from Gnome-client */ - -static void session_set_value(SmcConn conn, gchar *name, char *type, - int num_vals, SmPropValue *vals) { - SmProp *proplist[1]; - SmProp prop; - - g_return_if_fail(conn); - - prop.name = name; - prop.type = type; - prop.num_vals = num_vals; - prop.vals = vals; - - proplist[0] = ∝ - SmcSetProperties(conn, 1, proplist); -} - -static void session_set_string(SmcConn conn, gchar *name, gchar *value) { - SmPropValue val; - - g_return_if_fail(name); - - val.length = strlen (value)+1; - val.value = value; - - session_set_value(conn, name, SmARRAY8, 1, &val); -} - -static void session_set_gchar(SmcConn conn, gchar *name, gchar value) { - SmPropValue val; - - g_return_if_fail(name); - - val.length = 1; - val.value = &value; - - session_set_value(conn, name, SmCARD8, 1, &val); -} - -static void session_set_array(SmcConn conn, gchar *name, gchar *array[]) { - gint argc; - gchar **ptr; - gint i; - - SmPropValue *vals; - - g_return_if_fail (name); - - /* We count the number of elements in our array. */ - for (ptr = array, argc = 0; *ptr ; ptr++, argc++) /* LOOP */; - - /* Now initialize the 'vals' array. */ - vals = g_new (SmPropValue, argc); - for (ptr = array, i = 0 ; i < argc ; ptr++, i++) { - vals[i].length = strlen (*ptr); - vals[i].value = *ptr; - } - - session_set_value(conn, name, SmLISTofARRAY8, argc, vals); - - g_free (vals); -} - -#endif /* USE_SM */ - -/* setup functions */ - -void -pidgin_session_init(gchar *argv0, gchar *previous_id, gchar *config_dir) -{ -#ifdef USE_SM - SmcCallbacks callbacks; - gchar *client_id = NULL; - gchar error[ERROR_LENGTH] = ""; - gchar *tmp = NULL; - gchar **cmd = NULL; - - if (session != NULL) { - /* session is already established, what the hell is going on? */ - purple_debug(PURPLE_DEBUG_WARNING, "Session Management", - "Duplicated call to pidgin_session_init!\n"); - return; - } - - if (g_getenv("SESSION_MANAGER") == NULL) { - purple_debug(PURPLE_DEBUG_ERROR, "Session Management", - "No SESSION_MANAGER found, aborting.\n"); - return; - } - - ice_init(); - - callbacks.save_yourself.callback = session_save_yourself; - callbacks.die.callback = session_die; - callbacks.save_complete.callback = session_save_complete; - callbacks.shutdown_cancelled.callback = session_shutdown_cancelled; - - callbacks.save_yourself.client_data = NULL; - callbacks.die.client_data = NULL; - callbacks.save_complete.client_data = NULL; - callbacks.shutdown_cancelled.client_data = NULL; - - if (previous_id) { - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Connecting with previous ID %s\n", previous_id); - } else { - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Connecting with no previous ID\n"); - } - - session = SmcOpenConnection(NULL, "session", SmProtoMajor, SmProtoMinor, SmcSaveYourselfProcMask | - SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, - &callbacks, previous_id, &client_id, ERROR_LENGTH, error); - - if (session == NULL) { - if (error[0] != '\0') { - purple_debug(PURPLE_DEBUG_ERROR, "Session Management", - "Connection failed with error: %s\n", error); - } else { - purple_debug(PURPLE_DEBUG_ERROR, "Session Management", - "Connetion failed with unknown error.\n"); - } - return; - } - - tmp = SmcVendor(session); - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Connected to manager (%s) with client ID %s\n", - tmp, client_id); - free(tmp); - - session_managed = TRUE; - gdk_x11_set_sm_client_id(client_id); - - tmp = g_get_current_dir(); - session_set_string(session, SmCurrentDirectory, tmp); - g_free(tmp); - - tmp = g_strdup_printf("%d", (int) getpid()); - session_set_string(session, SmProcessID, tmp); - g_free(tmp); - - tmp = g_strdup(g_get_user_name()); - session_set_string(session, SmUserID, tmp); - g_free(tmp); - - session_set_gchar(session, SmRestartStyleHint, (gchar) SmRestartIfRunning); - session_set_string(session, SmProgram, (gchar *) g_get_prgname()); - - myself = g_strdup(argv0); - purple_debug(PURPLE_DEBUG_MISC, "Session Management", - "Using %s as command\n", myself); - - cmd = session_make_command(NULL, config_dir); - session_set_array(session, SmCloneCommand, cmd); - g_strfreev(cmd); - - /* this is currently useless, but gnome-session warns 'the following applications will not - save their current status' bla bla if we don't have it and the user checks 'Save Session' - when they log out */ - cmd = g_new(gchar *, 2); - cmd[0] = g_strdup("/bin/true"); - cmd[1] = NULL; - session_set_array(session, SmDiscardCommand, cmd); - g_strfreev(cmd); - - cmd = session_make_command(client_id, config_dir); - session_set_array(session, SmRestartCommand, cmd); - g_strfreev(cmd); - - g_free(client_id); -#endif /* USE_SM */ -} - -void -pidgin_session_end() -{ -#ifdef USE_SM - if (session == NULL) /* no session to close */ - return; - - SmcCloseConnection(session, 0, NULL); - - purple_debug(PURPLE_DEBUG_INFO, "Session Management", - "Connection closed.\n"); -#endif /* USE_SM */ -}
--- a/pidgin/gtksession.h Thu Jun 15 10:48:26 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _PIDGINSESSION_H_ -#define _PIDGINSESSION_H_ -/** - * SECTION:gtksession - * @section_id: pidgin-gtksession - * @short_description: <filename>gtksession.h</filename> - * @title: X Windows Session Management - */ - -G_BEGIN_DECLS - -/**************************************************************************/ -/* X Windows session subsystem */ -/**************************************************************************/ - -/** - * pidgin_session_init: - * @argv0: The first argument passed into the program. This - * will be the name of the executable, e.g. 'purple' - * @previous_id: An optional session ID to use. This can be NULL. - * @config_dir: The path to the configuration directory used by - * this instance of this program, e.g. '/home/user/.purple' - * - * Register this instance of Pidgin with the user's current session - * manager. - */ -void pidgin_session_init(gchar *argv0, gchar *previous_id, gchar *config_dir); - -/** - * pidgin_session_end: - * - * Unregister this instance of Pidgin with the user's current session - * manager. - */ -void pidgin_session_end(void); - -G_END_DECLS - -#endif /* _PIDGINSESSION_H_ */
--- a/pidgin/gtkwebview.c Thu Jun 15 10:48:26 2017 +0300 +++ b/pidgin/gtkwebview.c Fri Jun 30 15:03:16 2017 +0300 @@ -24,7 +24,6 @@ #include "debug.h" #include "glibcompat.h" #include "image-store.h" -#include "marshallers.h" #include "pidgin.h" #include "pidginstock.h" @@ -1344,45 +1343,44 @@ G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(PidginWebViewClass, buttons_update), - NULL, 0, g_cclosure_marshal_VOID__INT, + NULL, 0, NULL, G_TYPE_NONE, 1, G_TYPE_INT); signals[TOGGLE_FORMAT] = g_signal_new("format-toggled", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(PidginWebViewClass, toggle_format), - NULL, 0, g_cclosure_marshal_VOID__INT, + NULL, 0, NULL, G_TYPE_NONE, 1, G_TYPE_INT); signals[CLEAR_FORMAT] = g_signal_new("format-cleared", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(PidginWebViewClass, clear_format), - NULL, 0, g_cclosure_marshal_VOID__VOID, + NULL, 0, NULL, G_TYPE_NONE, 0); signals[UPDATE_FORMAT] = g_signal_new("format-updated", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(PidginWebViewClass, update_format), - NULL, 0, g_cclosure_marshal_VOID__VOID, + NULL, 0, NULL, G_TYPE_NONE, 0); signals[CHANGED] = g_signal_new("changed", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(PidginWebViewClass, changed), - NULL, NULL, g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); signals[HTML_APPENDED] = g_signal_new("html-appended", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(PidginWebViewClass, html_appended), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + NULL, NULL, NULL, G_TYPE_NONE, 1, WEBKIT_TYPE_DOM_RANGE, NULL); signals[INSERT_IMAGE] = g_signal_new("insert-image", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(PidginWebViewClass, insert_image), - pidgin_webview_insert_image_accu, NULL, - purple_smarshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, + pidgin_webview_insert_image_accu, NULL, NULL, + G_TYPE_BOOLEAN, 1, PURPLE_TYPE_IMAGE); /* Class Methods */
--- a/pidgin/libpidgin.c Thu Jun 15 10:48:26 2017 +0300 +++ b/pidgin/libpidgin.c Fri Jun 30 15:03:16 2017 +0300 @@ -29,7 +29,6 @@ #include "core.h" #include "dbus-maybe.h" #include "debug.h" -#include "eventloop.h" #include "glibcompat.h" #include "log.h" #include "network.h" @@ -50,7 +49,6 @@ #include "gtkdebug.h" #include "gtkdialogs.h" #include "gtkdocklet.h" -#include "gtkeventloop.h" #include "gtkxfer.h" #include "gtkidle.h" #include "gtklog.h" @@ -63,7 +61,6 @@ #include "gtkrequest.h" #include "gtkroomlist.h" #include "gtksavedstatuses.h" -#include "gtksession.h" #include "gtksmiley-theme.h" #include "gtksound.h" #include "gtkutils.h" @@ -294,11 +291,6 @@ static void pidgin_quit(void) { -#ifdef USE_SM - /* unplug */ - pidgin_session_end(); -#endif - /* Uninit */ pidgin_utils_uninit(); pidgin_notify_uninit(); @@ -317,7 +309,7 @@ g_hash_table_destroy(ui_info); /* and end it all... */ - gtk_main_quit(); + g_application_quit(g_application_get_default()); } static GHashTable *pidgin_ui_get_info(void) @@ -378,6 +370,12 @@ } static void +pidgin_activate_cb(GApplication *application, gpointer user_data) +{ + purple_blist_set_visible(TRUE); +} + +static void show_usage(const char *name, gboolean terse) { char *text; @@ -422,6 +420,7 @@ int pidgin_start(int argc, char *argv[]) { + GApplication *app; gboolean opt_force_online = FALSE; gboolean opt_help = FALSE; gboolean opt_login = FALSE; @@ -452,6 +451,7 @@ GList *active_accounts; GStatBuf st; GError *error; + int ret; struct option long_options[] = { {"config", required_argument, NULL, 'c'}, @@ -689,6 +689,9 @@ purple_debug_set_enabled(debug_enabled); purple_debug_set_colored(debug_colored); + /* Call this here as GtkApplication calls gtk_init() in + * g_application_register() and we don't necessarily want to exit(). + */ gui_check = gtk_init_check(&argc, &argv); if (!gui_check) { const char *display = gdk_display_get_name(gdk_display_get_default()); @@ -703,6 +706,26 @@ return 1; } + app = G_APPLICATION(gtk_application_new("im.pidgin.Pidgin", + G_APPLICATION_NON_UNIQUE)); + + g_object_set(app, "register-session", TRUE, NULL); + + g_signal_connect(app, "activate", + G_CALLBACK(pidgin_activate_cb), NULL); + + if (!g_application_register(app, NULL, &error)) { + purple_debug_error("gtk", + "Unable to register GApplication: %s\n", + error->message); + g_clear_error(&error); + g_object_unref(app); +#ifndef _WIN32 + g_free(segfault_message); +#endif + return 1; + } + search_path = g_build_filename(purple_user_dir(), "gtk-3.0.css", NULL); error = NULL; @@ -726,7 +749,6 @@ #endif purple_core_set_ui_ops(pidgin_core_get_ui_ops()); - purple_eventloop_set_ui_ops(pidgin_eventloop_get_ui_ops()); if (!purple_core_init(PIDGIN_UI)) { fprintf(stderr, @@ -771,9 +793,6 @@ ui_main(); -#ifdef USE_SM - pidgin_session_init(argv[0], opt_session_arg, opt_config_dir_arg); -#endif g_free(opt_session_arg); opt_session_arg = NULL; g_free(opt_config_dir_arg); @@ -845,7 +864,23 @@ winpidgin_post_init(); #endif - gtk_main(); + /* TODO: Use GtkApplicationWindow or add a window instead */ + g_application_hold(app); + + ret = g_application_run(app, 0, NULL); + + /* Make sure purple has quit in case something in GApplication + * has caused g_application_run() to finish on its own. This can + * happen, for example, if the desktop session is ending. + */ + if (purple_get_core() != NULL) { + purple_core_quit(); + } + + /* Now that we're sure purple_core_quit() has been called, + * this can be freed. + */ + g_object_unref(app); #ifndef _WIN32 g_free(segfault_message); @@ -858,5 +893,5 @@ winpidgin_cleanup(); #endif - return 0; + return ret; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pidgin.gresource.xml Fri Jun 30 15:03:16 2017 +0300 @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/im/pidgin/Pidgin"> + <file compressed="true">gtkdebug.html</file> + </gresource> +</gresources>
--- a/po/POTFILES.in Thu Jun 15 10:48:26 2017 +0300 +++ b/po/POTFILES.in Fri Jun 30 15:03:16 2017 +0300 @@ -57,8 +57,6 @@ libpurple/plugins.c libpurple/plugins/autoaccept.c libpurple/plugins/buddynote.c -libpurple/plugins/caesarcipher.c -libpurple/plugins/caesarcipher_consumer.c libpurple/plugins/dbus-example.c libpurple/plugins/filectl.c libpurple/plugins/idle.c