diff --git a/CHANGELOG.md b/CHANGELOG.md index 46eb724..9d9aec5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ Changelog --------- + +##### Version 1.1.0 (Beta 2) + + - update to libtgl 2 + - support two-factor authentication + - improve sticker support + - add option to control message read recipes + - many bugfixes + + ##### Version 1.0.0 (Beta 1) - Move state files into .purple/telegram-purple directory diff --git a/Makefile.in b/Makefile.in index 7baf55a..d537109 100644 --- a/Makefile.in +++ b/Makefile.in @@ -35,7 +35,7 @@ include ${srcdir}/Makefile.tl-parser include ${srcdir}/Makefile.tgl create_dirs: ${DIR_LIST} -create_dirs_and_headers: ${DIR_LIST} ${AUTO}/auto.c ${AUTO}/auto-header.h ${AUTO}/constants.h +create_dirs_and_headers: ${DIR_LIST} ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-types.h ${DIR_LIST}: @test -d $@ || mkdir -p $@ diff --git a/Makefile.tgl b/Makefile.tgl index 307171a..fc31c03 100644 --- a/Makefile.tgl +++ b/Makefile.tgl @@ -1,27 +1,32 @@ TGL_OBJECTS=${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/tgl.o ${OBJ}/updates.o ${OBJ}/tg-mime-types.o ${OBJ}/mtproto-utils.o + +TGL_OBJECTS_AUTO=${OBJ}/auto/auto-skip.o ${OBJ}/auto/auto-fetch.o ${OBJ}/auto/auto-store.o ${OBJ}/auto/auto-autocomplete.o ${OBJ}/auto/auto-types.o ${OBJ}/auto/auto-fetch-ds.o ${OBJ}/auto/auto-free-ds.o ${OBJ}/auto/auto-store-ds.o ${OBJ}/auto/auto-print-ds.o + + TLD_OBJECTS=${OBJ}/dump-tl-file.o GENERATE_OBJECTS=${OBJ}/generate.o TGL_COMMON_OBJECTS=${OBJ}/tools.o TGL_OBJ_C=${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS} -ALL_OBJS+=${TGL_OBJ_C} - .SUFFIXES: .SUFFIXES: .c .h .o dump-tl: ${EXE}/dump-tl-file -${OBJ}/auto/auto.o ${TGL_OBJECTS}: ${AUTO}/constants.h ${AUTO}/auto-header.h +${TGL_OBJECTS}: ${AUTO}/constants.h ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h ${AUTO}/auto-fetch-ds.h ${AUTO}/auto-free-ds.h ${AUTO}/auto-store-ds.h ${AUTO}/auto-print-ds.h ${TGL_OBJ_C}: ${OBJ}/%.o: ${srcdir}/tgl/%.c | create_dirs ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< -${OBJ}/auto/auto.o: ${AUTO}/auto.c - ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/auto/auto.d -MQ ${OBJ}/auto/auto.o -o $@ $< +${TGL_OBJECTS_AUTO}: ${OBJ}/auto/%.o: ${AUTO}/%.c | create_dirs + ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< -${LIB}/libtgl.a: ${TGL_OBJECTS} ${TGL_COMMON_OBJECTS} ${OBJ}/auto/auto.o - ar ruv $@ $^ +#${OBJ}/auto/auto.o: ${AUTO}/auto.c +# ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/auto/auto.d -MQ ${OBJ}/auto/auto.o -o $@ $< + +${LIB}/libtgl.a: ${TGL_OBJECTS} ${TGL_COMMON_OBJECTS} ${TGL_OBJECTS_AUTO} + rm -f $@ && ar ruv $@ $^ ${EXE}/generate: ${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${CC} ${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${LINK_FLAGS} -o $@ @@ -35,11 +40,11 @@ ${AUTO}/scheme.tl: ${srcdir}/tgl/scheme.tl ${srcdir}/tgl/encrypted_scheme.tl ${s ${AUTO}/scheme2.tl: ${AUTO}/scheme.tl ${EXE}/tl-parser ${EXE}/tl-parser -E ${AUTO}/scheme.tl 2> $@ || ( cat $@ && rm $@ && false ) -${AUTO}/auto.c: ${AUTO}/scheme.tlo ${EXE}/generate - ${EXE}/generate ${AUTO}/scheme.tlo > $@ +${AUTO}/auto-%.c: ${AUTO}/scheme.tlo ${EXE}/generate auto/constants.h ${AUTO}/auto-%.h | create_dirs_and_headers + ${EXE}/generate -g $(patsubst ${AUTO}/auto-%.c,%,$@) ${AUTO}/scheme.tlo > $@ || rm $@ -${AUTO}/auto-header.h: ${AUTO}/scheme.tlo ${EXE}/generate - ${EXE}/generate -H ${AUTO}/scheme.tlo > $@ +${AUTO}/auto-%.h: ${AUTO}/scheme.tlo ${EXE}/generate + ${EXE}/generate -g $(patsubst ${AUTO}/auto-%.h,%-header,$@) ${AUTO}/scheme.tlo > $@ || rm $@ ${AUTO}/constants.h: ${AUTO}/scheme2.tl ${srcdir}/tgl/gen_constants_h.awk awk -f ${srcdir}/tgl/gen_constants_h.awk < $< > $@ diff --git a/README.md b/README.md index 28ec4ae..ee10d0a 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,26 @@ Telegram-Purple (Beta) Telegram-purple is a Libpurple plugin that adds support for the Telegram messenger. -Beta 1 +Beta 2 ------ -If you migrate from an older version, the Telegram authentication files have been moved to .purple/telegram-purple. If you want to keep your old secret chats, please copy it manually from ~/.telegram-purple, otherwise you will just be prompted for a new SMS code. + - update to libtgl 2 + - support two-factor authentication + - improve sticker support + - add option to control message read recipes + - many bugfixes + + +If you migrate from an older version, the Telegram authentication files have been moved to .purple/telegram-purple. If you want to keep your old secret chats, please copy it manually from ~/.telegram-purple, otherwise you will be prompted for a new SMS code. Build ----- -Below, you will find instructions on how to build the libpurple protocol plugin. If you just want to use the plugin in Adium, [download precompiled packages here.](https://github.com/majn/telegram-purple/releases) +Below, you will find instructions on how to build the libpurple protocol plugin. If you just want to use the plugin in Adium, [download precompiled packages here.](https://github.com/majn/telegram-purple/releases). #### 1. Clone -This repository has submodules, so you need to clone recursively +This repository has submodules, so you need to clone recursively. git clone --recursive https://github.com/majn/telegram-purple @@ -27,21 +34,23 @@ This repository has submodules, so you need to clone recursively ##### Fedora - sudo yum install gcc openssl-devel glib2-devel libpurple-devel + sudo yum install gcc openssl-devel glib2-devel libpurple-devel libwebp-devel -###### Debian +###### Debian / Ubuntu - sudo apt-get install libssl-dev libglib2.0-dev libpurple-dev + sudo apt-get install libssl-dev libglib2.0-dev libpurple-dev libwebp-dev ###### OpenSUSE - sudo zypper install gcc glib glib-devel libpurple libpurple-devel zlib-devel openssl libopenssl-devel + sudo zypper install gcc glib glib-devel libpurple libpurple-devel zlib-devel openssl libopenssl-devel libwebp-devel #### 3. Compile and install +If libwebp is not available, you can disable sticker support by calling ./configure --disable-libweb instead. + ./configure make sudo make install diff --git a/config.h.in b/config.h.in index 29d9d95..341c321 100644 --- a/config.h.in +++ b/config.h.in @@ -15,6 +15,9 @@ /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT +/* Define to 1 if you have the `webp' library (-lwebp). */ +#undef HAVE_LIBWEBP + /* Define to 1 if you have `z' library (-lz) */ #undef HAVE_LIBZ diff --git a/configure b/configure index 42ff5d3..bcd0630 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for telegram-purple 1.0.0. +# Generated by GNU Autoconf 2.69 for telegram-purple 1.1.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='telegram-purple' PACKAGE_TARNAME='telegram-purple' -PACKAGE_VERSION='1.0.0' -PACKAGE_STRING='telegram-purple 1.0.0' +PACKAGE_VERSION='1.1.0' +PACKAGE_STRING='telegram-purple 1.1.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -686,6 +686,7 @@ ac_user_opts=' enable_option_checking with_openssl with_zlib +enable_libwebp ' ac_precious_vars='build_alias host_alias @@ -1241,7 +1242,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures telegram-purple 1.0.0 to adapt to many kinds of systems. +\`configure' configures telegram-purple 1.1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1302,10 +1303,17 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of telegram-purple 1.0.0:";; + short | recursive ) echo "Configuration of telegram-purple 1.1.0:";; esac cat <<\_ACEOF +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-libwebp Disable libwebp, stickers won't be displayed in the + chat + Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) @@ -1398,7 +1406,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -telegram-purple configure 1.0.0 +telegram-purple configure 1.1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1817,7 +1825,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by telegram-purple $as_me 1.0.0, which was +It was created by telegram-purple $as_me 1.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4210,6 +4218,67 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libwebp" >&5 +$as_echo_n "checking for libwebp... " >&6; } +# Check whether --enable-libwebp was given. +if test "${enable_libwebp+set}" = set; then : + enableval=$enable_libwebp; +fi + + if test "x$enable_libwebp" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 +$as_echo "enabled" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WebPDecodeRGBA in -lwebp" >&5 +$as_echo_n "checking for WebPDecodeRGBA in -lwebp... " >&6; } +if ${ac_cv_lib_webp_WebPDecodeRGBA+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lwebp $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char WebPDecodeRGBA (); +int +main () +{ +return WebPDecodeRGBA (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_webp_WebPDecodeRGBA=yes +else + ac_cv_lib_webp_WebPDecodeRGBA=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_webp_WebPDecodeRGBA" >&5 +$as_echo "$ac_cv_lib_webp_WebPDecodeRGBA" >&6; } +if test "x$ac_cv_lib_webp_WebPDecodeRGBA" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBWEBP 1 +_ACEOF + + LIBS="-lwebp $LIBS" + +else + as_fn_error $? "no libwebp found, try --disable-libwebp, but stickers won't be displayed in the chat" "$LINENO" 5 +fi + + fi # Checks for header files. @@ -4833,7 +4902,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by telegram-purple $as_me 1.0.0, which was +This file was extended by telegram-purple $as_me 1.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4895,7 +4964,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -telegram-purple config.status 1.0.0 +telegram-purple config.status 1.1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index b60b5ad..c21003f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([telegram-purple], [1.0.0]) +AC_INIT([telegram-purple], [1.1.0]) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADERS([config.h]) @@ -20,6 +20,14 @@ AX_CHECK_ZLIB(, [AC_MSG_ERROR([No zlib found])]) PKG_CHECK_MODULES([PURPLE], [purple], ) +AC_MSG_CHECKING([for libwebp]) +AC_ARG_ENABLE([libwebp], + AS_HELP_STRING([--disable-libwebp], [Disable libwebp, stickers won't be displayed in the chat])) + AS_IF([test "x$enable_libwebp" != "xno"], [ + AC_MSG_RESULT([enabled]) + AC_CHECK_LIB([webp], [WebPDecodeRGBA], [], [AC_MSG_ERROR([no libwebp found, try --disable-libwebp, but stickers won't be displayed in the chat])]) + ]) + # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h]) diff --git a/rpm/purple-telegram.spec b/rpm/purple-telegram.spec new file mode 100644 index 0000000..a120ec9 --- /dev/null +++ b/rpm/purple-telegram.spec @@ -0,0 +1,33 @@ +Name: purple-telegram +Version: 1.0.1 +Release: 1%{?dist} +Summary: Adds support for Telegram to Pidgin, Adium, Finch and other Libpurple based messengers +Group: Internet/Messaging +License: GPLv2+ +URL: https://github.com/majn/telegram-purple +Source0: https://codeload.github.com/majn/telegram-purple/tar.gz/v%{version}.tar.gz + +BuildRequires: openssl-devel,glib2-devel,libpurple-devel +Requires: openssl,glib2,libpurple + +%description + +%prep +%autosetup + +%build +%configure +make %{?_smp_mflags} + +%install +%make_install + +%files +%doc +%{_libdir}/purple-2/telegram-purple.so +%{_sysconfdir}/telegram-purple/* +%{_datadir}/pixmaps/pidgin/protocols/16/telegram.png +%{_datadir}/pixmaps/pidgin/protocols/22/telegram.png +%{_datadir}/pixmaps/pidgin/protocols/48/telegram.png + +%changelog diff --git a/telegram-adium/TelegramAccount.m b/telegram-adium/TelegramAccount.m index fe65d8f..747e3c0 100644 --- a/telegram-adium/TelegramAccount.m +++ b/telegram-adium/TelegramAccount.m @@ -51,6 +51,11 @@ { [super configurePurpleAccount]; + purple_account_set_string (account, TGP_KEY_PASSWORD_TWO_FACTOR, + [[self preferenceForKey:@"Telegram:"TGP_KEY_PASSWORD_TWO_FACTOR + group:GROUP_ACCOUNT_STATUS] + UTF8String]); + purple_account_set_string (account, TGP_KEY_ACCEPT_SECRET_CHATS, [[self preferenceForKey:@"Telegram:"TGP_KEY_ACCEPT_SECRET_CHATS group:GROUP_ACCOUNT_STATUS] @@ -61,6 +66,11 @@ group:GROUP_ACCOUNT_STATUS] boolValue]); + purple_account_set_bool (account, TGP_KEY_SEND_READ_NOTIFICATIONS, + [[self preferenceForKey:@"Telegram:"TGP_KEY_SEND_READ_NOTIFICATIONS + group:GROUP_ACCOUNT_STATUS] + boolValue]); + purple_account_set_bool (account, TGP_KEY_HISTORY_SYNC_ALL, [[self preferenceForKey:@"Telegram:"TGP_KEY_HISTORY_SYNC_ALL group:GROUP_ACCOUNT_STATUS] diff --git a/telegram-adium/TelegramAccountView.xib b/telegram-adium/TelegramAccountView.xib index 76845c1..e510fff 100644 --- a/telegram-adium/TelegramAccountView.xib +++ b/telegram-adium/TelegramAccountView.xib @@ -1,19 +1,21 @@ - + - + + + @@ -21,11 +23,11 @@ - + - + @@ -33,30 +35,57 @@ - + + + + + + + + + - - + + + + + + + + + + + + + + + + + + NSAllRomanInputSourcesLocaleIdentifier + + + - + - + - + @@ -64,7 +93,7 @@ - + @@ -72,7 +101,7 @@ - + @@ -81,7 +110,7 @@ - + @@ -107,7 +136,7 @@ - + @@ -115,29 +144,29 @@ - + - - + @@ -145,7 +174,7 @@ - + @@ -154,7 +183,7 @@ - + @@ -162,15 +191,22 @@ - + + - + diff --git a/telegram-adium/TelegramAccountViewController.h b/telegram-adium/TelegramAccountViewController.h index 92c571c..510c17b 100644 --- a/telegram-adium/TelegramAccountViewController.h +++ b/telegram-adium/TelegramAccountViewController.h @@ -1,17 +1,19 @@ -/* - * Adium is the legal property of its developers, whose names are listed in the copyright file included - * 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. +/** + * 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 + * + * Copyright Matthias Jentsch 2014-2015 */ #import @@ -20,10 +22,12 @@ @interface TelegramAccountViewController : PurpleAccountViewController { IBOutlet NSButton *checkbox_historySyncAll; IBOutlet NSButton *checkbox_displayReadNotifications; + IBOutlet NSButton *checkbox_sendReadNotifications; IBOutlet NSTextField *textField_maxMsgSplitCount; IBOutlet NSTextField *textField_inactiveDaysOffline; IBOutlet NSTextField *textField_historyRetrieveDays; + IBOutlet NSSecureTextField *textField_passwordTwoFactor; IBOutlet NSMatrix *radio_Encryption; } diff --git a/telegram-adium/TelegramAccountViewController.m b/telegram-adium/TelegramAccountViewController.m index a9c6508..4efb68e 100644 --- a/telegram-adium/TelegramAccountViewController.m +++ b/telegram-adium/TelegramAccountViewController.m @@ -1,17 +1,19 @@ -/* - * Adium is the legal property of its developers, whose names are listed in the copyright file included - * 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. +/** + * 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 + * + * Copyright Matthias Jentsch 2014-2015 */ #import "TelegramAccountViewController.h" @@ -20,7 +22,7 @@ #import #import #import -#import +#import DISPLAY #include "telegram-purple.h" @@ -46,11 +48,18 @@ } [radio_Encryption selectCellAtRow:row column:0]; + NSString *passwordTwoFactor = [account preferenceForKey:@"Telegram:"TGP_KEY_PASSWORD_TWO_FACTOR + group:GROUP_ACCOUNT_STATUS] ?: nil; + [textField_password setStringValue:passwordTwoFactor]; + id s = [account preferenceForKey:@"Telegram:"TGP_KEY_HISTORY_SYNC_ALL group:GROUP_ACCOUNT_STATUS]; [checkbox_historySyncAll setState:[s boolValue]]; - id s4 = [account preferenceForKey:@"Telegram:"TGP_KEY_DISPLAY_READ_NOTIFICATIONS group:GROUP_ACCOUNT_STATUS]; - [checkbox_displayReadNotifications setState:[s4 boolValue]]; + id read = [account preferenceForKey:@"Telegram:"TGP_KEY_DISPLAY_READ_NOTIFICATIONS group:GROUP_ACCOUNT_STATUS]; + [checkbox_displayReadNotifications setState:[read boolValue]]; + + id send = [account preferenceForKey:@"Telegram:"TGP_KEY_SEND_READ_NOTIFICATIONS group:GROUP_ACCOUNT_STATUS]; + [checkbox_sendReadNotifications setState:[send boolValue]]; NSString *inactiveDaysOffline = [account preferenceForKey:@"Telegram:"TGP_KEY_INACTIVE_DAYS_OFFLINE @@ -69,6 +78,10 @@ NSArray *selections = @[@"ask", @"always", @"never"]; + [account setPreference:[textField_password stringValue] + forKey:@"Telegram:"TGP_KEY_PASSWORD_TWO_FACTOR + group:GROUP_ACCOUNT_STATUS]; + [account setPreference:selections[[radio_Encryption selectedRow]] forKey:@"Telegram:"TGP_KEY_ACCEPT_SECRET_CHATS group:GROUP_ACCOUNT_STATUS]; @@ -81,6 +94,10 @@ forKey:@"Telegram:"TGP_KEY_DISPLAY_READ_NOTIFICATIONS group:GROUP_ACCOUNT_STATUS]; + [account setPreference:[NSNumber numberWithBool: [checkbox_sendReadNotifications state]] + forKey:@"Telegram:"TGP_KEY_SEND_READ_NOTIFICATIONS + group:GROUP_ACCOUNT_STATUS]; + [account setPreference:[textField_historyRetrieveDays stringValue] forKey:@"Telegram:"TGP_KEY_HISTORY_RETRIEVAL_THRESHOLD group:GROUP_ACCOUNT_STATUS]; diff --git a/telegram-adium/TelegramJoinChatViewController.h b/telegram-adium/TelegramJoinChatViewController.h index 308377b..9b0e388 100644 --- a/telegram-adium/TelegramJoinChatViewController.h +++ b/telegram-adium/TelegramJoinChatViewController.h @@ -1,17 +1,19 @@ -/* - * Adium is the legal property of its developers, whose names are listed in the copyright file included - * 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. +/** + * 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 + * + * Copyright Matthias Jentsch 2014-2015 */ #import @@ -19,7 +21,6 @@ @class AIAccount, AICompletingTextField; @interface TelegramJoinChatViewController : DCJoinChatViewController { - // IBOutlet NSTextField *textField_newChat; IBOutlet NSPopUpButton *popupButton_existingChat; } diff --git a/telegram-adium/TelegramJoinChatViewController.m b/telegram-adium/TelegramJoinChatViewController.m index d9e8db7..72baffc 100644 --- a/telegram-adium/TelegramJoinChatViewController.m +++ b/telegram-adium/TelegramJoinChatViewController.m @@ -1,17 +1,19 @@ -/* - * Adium is the legal property of its developers, whose names are listed in the copyright file included - * 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. +/** + * 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 + * + * Copyright Matthias Jentsch 2014-2015 */ #include diff --git a/telegram-adium/telegram-adium.xcodeproj/project.pbxproj b/telegram-adium/telegram-adium.xcodeproj/project.pbxproj index 966a677..8b81831 100644 --- a/telegram-adium/telegram-adium.xcodeproj/project.pbxproj +++ b/telegram-adium/telegram-adium.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ C438CE281A12BEAF00E1DA0F /* telegram16.png in Resources */ = {isa = PBXBuildFile; fileRef = C438CE241A12BEAF00E1DA0F /* telegram16.png */; }; C438CE291A12BEAF00E1DA0F /* telegram22.png in Resources */ = {isa = PBXBuildFile; fileRef = C438CE251A12BEAF00E1DA0F /* telegram22.png */; }; C438CE2A1A12BEAF00E1DA0F /* telegram48.png in Resources */ = {isa = PBXBuildFile; fileRef = C438CE261A12BEAF00E1DA0F /* telegram48.png */; }; - C438CE2C1A12BF3400E1DA0F /* libtgl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C438CE2B1A12BF3400E1DA0F /* libtgl.a */; }; C438CE321A12C07800E1DA0F /* msglog.c in Sources */ = {isa = PBXBuildFile; fileRef = C438CE2D1A12C07800E1DA0F /* msglog.c */; }; C438CE331A12C07800E1DA0F /* telegram-base.c in Sources */ = {isa = PBXBuildFile; fileRef = C438CE2E1A12C07800E1DA0F /* telegram-base.c */; }; C438CE341A12C07800E1DA0F /* telegram-purple.c in Sources */ = {isa = PBXBuildFile; fileRef = C438CE2F1A12C07800E1DA0F /* telegram-purple.c */; }; @@ -40,11 +39,23 @@ C4B4BE331AB4536F0064AC17 /* PurpleDefaultsTelegram.plist in Resources */ = {isa = PBXBuildFile; fileRef = C4B4BE321AB4536F0064AC17 /* PurpleDefaultsTelegram.plist */; }; C4B4BE371AB5FB5C0064AC17 /* TelegramJoinChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4B4BE351AB5FB5C0064AC17 /* TelegramJoinChatViewController.m */; }; C4B4BE391AB613950064AC17 /* TelegramJoinChatView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4B4BE381AB613950064AC17 /* TelegramJoinChatView.xib */; }; + C4B57BE71B10C652006997F4 /* libwebp.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C4B57BE61B10C652006997F4 /* libwebp.dylib */; }; + C4B57BF01B1598D4006997F4 /* libtgl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C4B57BEF1B1598D4006997F4 /* libtgl.a */; }; C4D819031A5C85FE0044CBA9 /* lodepng.c in Sources */ = {isa = PBXBuildFile; fileRef = C4D819011A5C85FE0044CBA9 /* lodepng.c */; }; C4D819061A5C862E0044CBA9 /* tgp-structs.c in Sources */ = {isa = PBXBuildFile; fileRef = C4D819041A5C862E0044CBA9 /* tgp-structs.c */; }; C4E528111A8A907200C4B915 /* tgp-ft.c in Sources */ = {isa = PBXBuildFile; fileRef = C4E5280F1A8A907200C4B915 /* tgp-ft.c */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + C4B57BF51B160EA6006997F4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C410947E19BB2D7D0083BF3F /* Project object */; + proxyType = 1; + remoteGlobalIDString = C4B57BF11B160950006997F4; + remoteInfo = "telegram-purple"; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ C40564861A7937C600A293B9 /* AdiumLibpurple.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdiumLibpurple.framework; path = Frameworks/Adium/AdiumLibpurple.framework; sourceTree = ""; }; C410948619BB2D7D0083BF3F /* telegram-adium.AdiumLibpurplePlugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "telegram-adium.AdiumLibpurplePlugin"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -90,6 +101,7 @@ C487A18F1A792EA50044F135 /* libglib.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libglib.framework; path = Frameworks/Adium/libglib.framework; sourceTree = ""; }; C487A1901A792EA50044F135 /* libpurple.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libpurple.framework; path = Frameworks/Adium/libpurple.framework; sourceTree = ""; }; C49A915719BBC5C5001B3DC0 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; + C4A71A911B18DD9300AE2E2B /* Makefile.tgl */ = {isa = PBXFileReference; lastKnownFileType = text; name = Makefile.tgl; path = ../Makefile.tgl; sourceTree = ""; }; C4B4BE2D1AB392F80064AC17 /* TelegramAccountView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TelegramAccountView.xib; sourceTree = ""; }; C4B4BE2F1AB393800064AC17 /* TelegramAccountViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TelegramAccountViewController.m; sourceTree = ""; }; C4B4BE301AB393800064AC17 /* TelegramAccountViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TelegramAccountViewController.h; sourceTree = ""; }; @@ -97,6 +109,13 @@ C4B4BE351AB5FB5C0064AC17 /* TelegramJoinChatViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TelegramJoinChatViewController.m; sourceTree = ""; }; C4B4BE361AB5FB5C0064AC17 /* TelegramJoinChatViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TelegramJoinChatViewController.h; sourceTree = ""; }; C4B4BE381AB613950064AC17 /* TelegramJoinChatView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TelegramJoinChatView.xib; sourceTree = ""; }; + C4B57BE51B109E6D006997F4 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; + C4B57BE61B10C652006997F4 /* libwebp.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libwebp.dylib; path = ../../../../../usr/local/lib/libwebp.dylib; sourceTree = ""; }; + C4B57BE81B10D814006997F4 /* configure.ac */ = {isa = PBXFileReference; lastKnownFileType = text; name = configure.ac; path = ../configure.ac; sourceTree = ""; }; + C4B57BE91B10D822006997F4 /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = Makefile.in; path = ../Makefile.in; sourceTree = ""; }; + C4B57BEC1B13B2C4006997F4 /* auto-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "auto-types.h"; path = "../auto/auto-types.h"; sourceTree = ""; }; + C4B57BED1B1598BE006997F4 /* telegram-purple */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "telegram-purple"; path = ..; sourceTree = ""; }; + C4B57BEF1B1598D4006997F4 /* libtgl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtgl.a; path = ../libs/libtgl.a; sourceTree = ""; }; C4D819011A5C85FE0044CBA9 /* lodepng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lodepng.c; sourceTree = ""; }; C4D819021A5C85FE0044CBA9 /* lodepng.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lodepng.h; sourceTree = ""; }; C4D819041A5C862E0044CBA9 /* tgp-structs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "tgp-structs.c"; path = "../tgp-structs.c"; sourceTree = ""; }; @@ -110,6 +129,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C4B57BF01B1598D4006997F4 /* libtgl.a in Frameworks */, C40564871A7937C600A293B9 /* AdiumLibpurple.framework in Frameworks */, C487A18C1A792E9B0044F135 /* Adium.framework in Frameworks */, C487A18E1A792E9B0044F135 /* AIUtilities.framework in Frameworks */, @@ -118,8 +138,8 @@ C487A17B1A792CF00044F135 /* libcrypto.dylib in Frameworks */, C466937819E703370036A108 /* AppKit.framework in Frameworks */, C49A915819BBC5C5001B3DC0 /* libz.dylib in Frameworks */, - C438CE2C1A12BF3400E1DA0F /* libtgl.a in Frameworks */, C410948A19BB2D7D0083BF3F /* CoreFoundation.framework in Frameworks */, + C4B57BE71B10C652006997F4 /* libwebp.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -166,6 +186,9 @@ C410948819BB2D7D0083BF3F /* Frameworks */ = { isa = PBXGroup; children = ( + C4B57BEF1B1598D4006997F4 /* libtgl.a */, + C4B57BED1B1598BE006997F4 /* telegram-purple */, + C4B57BE61B10C652006997F4 /* libwebp.dylib */, C40564861A7937C600A293B9 /* AdiumLibpurple.framework */, C487A18F1A792EA50044F135 /* libglib.framework */, C487A1901A792EA50044F135 /* libpurple.framework */, @@ -210,6 +233,10 @@ C4BF990319BB8B200038D507 /* telegram-purple */ = { isa = PBXGroup; children = ( + C4B57BE81B10D814006997F4 /* configure.ac */, + C4B57BE91B10D822006997F4 /* Makefile.in */, + C4B57BE51B109E6D006997F4 /* README.md */, + C4A71A911B18DD9300AE2E2B /* Makefile.tgl */, C425F9161A7069C300361AFC /* tgp-utils.c */, C425F9171A7069C300361AFC /* tgp-utils.h */, C4D819041A5C862E0044CBA9 /* tgp-structs.c */, @@ -231,6 +258,7 @@ C431EB7B1A76C737006521CB /* tgp-chat.c */, C431EB7C1A76C737006521CB /* tgp-chat.h */, C4E5280F1A8A907200C4B915 /* tgp-ft.c */, + C4B57BEC1B13B2C4006997F4 /* auto-types.h */, C4E528101A8A907200C4B915 /* tgp-ft.h */, ); name = "telegram-purple"; @@ -248,6 +276,23 @@ }; /* End PBXGroup section */ +/* Begin PBXLegacyTarget section */ + C4B57BF11B160950006997F4 /* telegram-purple */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = C4B57BF21B160951006997F4 /* Build configuration list for PBXLegacyTarget "telegram-purple" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/make; + buildWorkingDirectory = "$(PROJECT_DIR)/../"; + dependencies = ( + ); + name = "telegram-purple"; + passBuildSettingsInEnvironment = 0; + productName = "telegram-purple"; + }; +/* End PBXLegacyTarget section */ + /* Begin PBXNativeTarget section */ C410948519BB2D7D0083BF3F /* telegram-adium */ = { isa = PBXNativeTarget; @@ -260,6 +305,7 @@ buildRules = ( ); dependencies = ( + C4B57BF61B160EA6006997F4 /* PBXTargetDependency */, ); name = "telegram-adium"; productName = "telegram-adium"; @@ -274,6 +320,11 @@ attributes = { LastUpgradeCheck = 0510; ORGANIZATIONNAME = "Matthias Jentsch"; + TargetAttributes = { + C4B57BF11B160950006997F4 = { + CreatedOnToolsVersion = 6.3.2; + }; + }; }; buildConfigurationList = C410948119BB2D7D0083BF3F /* Build configuration list for PBXProject "telegram-adium" */; compatibilityVersion = "Xcode 3.2"; @@ -288,6 +339,7 @@ projectRoot = ""; targets = ( C410948519BB2D7D0083BF3F /* telegram-adium */, + C4B57BF11B160950006997F4 /* telegram-purple */, ); }; /* End PBXProject section */ @@ -338,6 +390,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + C4B57BF61B160EA6006997F4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C4B57BF11B160950006997F4 /* telegram-purple */; + targetProxy = C4B57BF51B160EA6006997F4 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ C410948E19BB2D7D0083BF3F /* InfoPlist.strings */ = { isa = PBXVariantGroup; @@ -374,6 +434,7 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( HAVE_CONFIG_H, + HAVE_LIBWEBP, DEBUG, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; @@ -412,7 +473,10 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = s; - GCC_PREPROCESSOR_DEFINITIONS = HAVE_CONFIG_H; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + HAVE_LIBWEBP, + ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -442,16 +506,19 @@ GCC_PREFIX_HEADER = "telegram-adium/telegram-adium-Prefix.pch"; HEADER_SEARCH_PATHS = ( "$(inherited)", + "$(PROJECT_DIR)/../auto", "$(PROJECT_DIR)/../tgl", "$(PROJECT_DIR)/Frameworks/Adium/libpurple.framework/Headers", "$(PROJECT_DIR)/Frameworks/Adium/libglib.framework/Headers", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + /usr/local/include, ); INFOPLIST_FILE = "telegram-adium/telegram-adium-Info.plist"; INSTALL_PATH = "$(HOME)/Library/Application Support/Adium 2.0/PlugIns/"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/../tgl/libs", + "$(PROJECT_DIR)/../libs", + /usr/local/lib, ); OTHER_CFLAGS = "-DPURPLE_STATIC_PRPL"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -477,16 +544,19 @@ GCC_PREFIX_HEADER = "telegram-adium/telegram-adium-Prefix.pch"; HEADER_SEARCH_PATHS = ( "$(inherited)", + "$(PROJECT_DIR)/../auto", "$(PROJECT_DIR)/../tgl", "$(PROJECT_DIR)/Frameworks/Adium/libpurple.framework/Headers", "$(PROJECT_DIR)/Frameworks/Adium/libglib.framework/Headers", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + /usr/local/include, ); INFOPLIST_FILE = "telegram-adium/telegram-adium-Info.plist"; INSTALL_PATH = "$(HOME)/Library/Application Support/Adium 2.0/PlugIns/"; LIBRARY_SEARCH_PATHS = ( "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../tgl/libs", + "$(PROJECT_DIR)/../libs", + /usr/local/lib, ); OTHER_CFLAGS = "-DPURPLE_STATIC_PRPL"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -495,6 +565,44 @@ }; name = Release; }; + C4B57BF31B160951006997F4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_UNREACHABLE_CODE = YES; + DEBUGGING_SYMBOLS = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + C4B57BF41B160951006997F4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_UNREACHABLE_CODE = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -516,6 +624,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + C4B57BF21B160951006997F4 /* Build configuration list for PBXLegacyTarget "telegram-purple" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C4B57BF31B160951006997F4 /* Debug */, + C4B57BF41B160951006997F4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; /* End XCConfigurationList section */ }; rootObject = C410947E19BB2D7D0083BF3F /* Project object */; diff --git a/telegram-adium/telegram-adium.xcodeproj/xcuserdata/matj.xcuserdatad/xcschemes/telegram-purple.xcscheme b/telegram-adium/telegram-adium.xcodeproj/xcuserdata/matj.xcuserdatad/xcschemes/telegram-purple.xcscheme new file mode 100644 index 0000000..08edabb --- /dev/null +++ b/telegram-adium/telegram-adium.xcodeproj/xcuserdata/matj.xcuserdatad/xcschemes/telegram-purple.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/telegram-adium/telegram-adium.xcodeproj/xcuserdata/matj.xcuserdatad/xcschemes/xcschememanagement.plist b/telegram-adium/telegram-adium.xcodeproj/xcuserdata/matj.xcuserdatad/xcschemes/xcschememanagement.plist index a3b948e..379ba26 100644 --- a/telegram-adium/telegram-adium.xcodeproj/xcuserdata/matj.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/telegram-adium/telegram-adium.xcodeproj/xcuserdata/matj.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,6 +9,11 @@ orderHint 0 + telegram-purple.xcscheme + + orderHint + 2 + telegrma-adium Release.xcscheme isShown @@ -24,6 +29,11 @@ primary + C4B57BF11B160950006997F4 + + primary + + diff --git a/telegram-base.c b/telegram-base.c index d897928..6cb26f1 100644 --- a/telegram-base.c +++ b/telegram-base.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -38,9 +39,9 @@ #include "msglog.h" #include "tgp-2prpl.h" #include "tgp-structs.h" +#include "tgp-utils.h" #include "lodepng/lodepng.h" - #define _(m) m #define DC_SERIALIZED_MAGIC 0x868aa81d #define STATE_FILE_MAGIC 0x28949a93 @@ -137,7 +138,7 @@ void write_dc (struct tgl_dc *DC, void *extra) { assert (write (auth_file_fd, &x, 4) == 4); } - assert (DC->has_auth); + assert (DC->flags & TGLDCF_LOGGED_IN); assert (write (auth_file_fd, &DC->port, 4) == 4); int l = strlen (DC->ip); @@ -181,8 +182,8 @@ void read_dc (struct tgl_state *TLS, int auth_file_fd, int id, unsigned ver) { assert (read (auth_file_fd, &auth_key_id, 8) == 8); assert (read (auth_file_fd, auth_key, 256) == 256); - bl_do_dc_option (TLS, id, 2, "DC", l, ip, port); - bl_do_set_auth_key_id (TLS, id, auth_key); + bl_do_dc_option (TLS, id, "DC", 2, ip, l, port); + bl_do_set_auth_key (TLS, id, auth_key); bl_do_dc_signed (TLS, id); } @@ -200,16 +201,16 @@ int error_if_val_false (struct tgl_state *TLS, int val, const char *cause, const void empty_auth_file (struct tgl_state *TLS) { if (TLS->test_mode) { - bl_do_dc_option (TLS, 1, 0, "", strlen (TG_SERVER_TEST_1), TG_SERVER_TEST_1, 443); - bl_do_dc_option (TLS, 2, 0, "", strlen (TG_SERVER_TEST_2), TG_SERVER_TEST_2, 443); - bl_do_dc_option (TLS, 3, 0, "", strlen (TG_SERVER_TEST_3), TG_SERVER_TEST_3, 443); + bl_do_dc_option (TLS, 1, "", 0, TG_SERVER_TEST_1, strlen (TG_SERVER_TEST_1), 443); + bl_do_dc_option (TLS, 2, "", 0, TG_SERVER_TEST_2, strlen (TG_SERVER_TEST_2), 443); + bl_do_dc_option (TLS, 3, "", 0, TG_SERVER_TEST_3, strlen (TG_SERVER_TEST_3), 443); bl_do_set_working_dc (TLS, TG_SERVER_TEST_DEFAULT); } else { - bl_do_dc_option (TLS, 1, 0, "", strlen (TG_SERVER_1), TG_SERVER_1, 443); - bl_do_dc_option (TLS, 2, 0, "", strlen (TG_SERVER_2), TG_SERVER_2, 443); - bl_do_dc_option (TLS, 3, 0, "", strlen (TG_SERVER_3), TG_SERVER_3, 443); - bl_do_dc_option (TLS, 4, 0, "", strlen (TG_SERVER_4), TG_SERVER_4, 443); - bl_do_dc_option (TLS, 5, 0, "", strlen (TG_SERVER_5), TG_SERVER_5, 443); + bl_do_dc_option (TLS, 1, "", 0, TG_SERVER_1, strlen (TG_SERVER_1), 443); + bl_do_dc_option (TLS, 2, "", 0, TG_SERVER_2, strlen (TG_SERVER_2), 443); + bl_do_dc_option (TLS, 3, "", 0, TG_SERVER_3, strlen (TG_SERVER_3), 443); + bl_do_dc_option (TLS, 4, "", 0, TG_SERVER_4, strlen (TG_SERVER_4), 443); + bl_do_dc_option (TLS, 5, "", 0, TG_SERVER_5, strlen (TG_SERVER_5), 443); bl_do_set_working_dc (TLS, TG_SERVER_DEFAULT); } } @@ -333,6 +334,8 @@ void read_secret_chat (struct tgl_state *TLS, int fd, int v) { assert (read (fd, &key, 256) == 256); if (v >= 2) { assert (read (fd, sha, 20) == 20); + } else { + SHA1 ((void *)key, 256, sha); } int in_seq_no = 0, out_seq_no = 0, last_in_seq_no = 0; if (v >= 1) { @@ -340,25 +343,13 @@ void read_secret_chat (struct tgl_state *TLS, int fd, int v) { assert (read (fd, &last_in_seq_no, 4) == 4); assert (read (fd, &out_seq_no, 4) == 4); } - - bl_do_encr_chat_create (TLS, id, user_id, admin_id, s, l); - struct tgl_secret_chat *P = (void *)tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (id)); - assert (P && (P->flags & FLAG_CREATED)); - bl_do_encr_chat_set_date (TLS, P, date); - bl_do_encr_chat_set_ttl (TLS, P, ttl); - bl_do_encr_chat_set_layer (TLS ,P, layer); - bl_do_encr_chat_set_state (TLS, P, state); - bl_do_encr_chat_set_key (TLS, P, key, key_fingerprint); - if (v >= 2) { - bl_do_encr_chat_set_sha (TLS, P, sha); - } else { - SHA1 ((void *)key, 256, sha); - bl_do_encr_chat_set_sha (TLS, P, sha); - } - if (v >= 1) { - bl_do_encr_chat_set_seq (TLS, P, in_seq_no, last_in_seq_no, out_seq_no); - } - bl_do_encr_chat_set_access_hash (TLS, P, access_hash); + + bl_do_encr_chat_new (TLS, id, + &access_hash, &date, &admin_id, &user_id, + key, NULL, sha, &state, &ttl, &layer, + &in_seq_no, &last_in_seq_no, &out_seq_no, + &key_fingerprint, TGLECF_CREATE | TGLECF_CREATED + ); } void read_secret_chat_file (struct tgl_state *TLS) { @@ -386,6 +377,41 @@ void read_secret_chat_file (struct tgl_state *TLS) { close (secret_chat_fd); } +gchar *get_config_dir (struct tgl_state *TLS, char const *username) { + gchar *dir = g_strconcat (purple_user_dir(), G_DIR_SEPARATOR_S, config_dir, + G_DIR_SEPARATOR_S, username, NULL); + + if (g_str_has_prefix (dir, g_get_tmp_dir())) { + // telepathy-haze will set purple user dir to a tmp path, + // but we need the files to be persistent + g_free (dir); + dir = g_strconcat (g_get_home_dir(), G_DIR_SEPARATOR_S, ".telegram-purple", + G_DIR_SEPARATOR_S, username, NULL); + } + g_mkdir_with_parents (dir, 0700); + return dir; +} + +gchar *get_download_dir (struct tgl_state *TLS) { + assert (TLS->base_path); + static gchar *dir; + if (dir) { + g_free (dir); + } + dir = g_strconcat (TLS->base_path, G_DIR_SEPARATOR_S, "downloads", NULL); + g_mkdir_with_parents (dir, 0700); + return dir; +} + +void assert_file_exists (PurpleConnection *gc, const char *filepath, const char *format) { + if (!g_file_test (filepath, G_FILE_TEST_EXISTS)) { + gchar *msg = g_strdup_printf (format, filepath); + purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR, msg); + g_free (msg); + return; + } +} + void telegram_export_authorization (struct tgl_state *TLS); void export_auth_callback (struct tgl_state *TLS, void *extra, int success) { if (!error_if_val_false(TLS, success, "Login Canceled", "Authentication export failed.")) { @@ -397,7 +423,7 @@ void telegram_export_authorization (struct tgl_state *TLS) { int i; for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i] && !tgl_signed_dc (TLS, TLS->DC_list[i])) { debug ("tgl_do_export_auth(%d)", i); - tgl_do_export_auth (TLS, i, export_auth_callback, (void*)(long)TLS->DC_list[i]); + tgl_do_export_auth (TLS, i, export_auth_callback, (void*)(long)TLS->DC_list[i]); return; } write_auth_file (TLS); @@ -428,7 +454,9 @@ void request_code_entered (gpointer data, const gchar *code) { struct tgl_state *TLS = data; connection_data *conn = TLS->ev_base; char const *username = purple_account_get_username(conn->pa); - tgl_do_send_code_result (TLS, username, conn->hash, code, code_receive_result, 0) ; + tgl_do_send_code_result (TLS, username, (int)strlen (username), conn->hash, + (int)strlen (conn->hash), code, (int)strlen (code), + code_receive_result, 0); } static void request_code_canceled (gpointer data) { @@ -439,22 +467,6 @@ static void request_code_canceled (gpointer data) { PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, "registration canceled"); } -static void request_name_code_entered (PurpleConnection* gc, PurpleRequestFields* fields) { - connection_data *conn = purple_connection_get_protocol_data(gc); - struct tgl_state *TLS = conn->TLS; - char const *username = purple_account_get_username(conn->pa); - - const char* first = purple_request_fields_get_string(fields, "first_name"); - const char* last = purple_request_fields_get_string(fields, "last_name"); - const char* code = purple_request_fields_get_string(fields, "code"); - if (!first || !last || !code) { - request_name_and_code (TLS); - return; - } - - tgl_do_send_code_result_auth (TLS, username, conn->hash, code, first, last, code_auth_receive_result, NULL); -} - static void request_code (struct tgl_state *TLS) { debug ("Client is not registered, registering..."); connection_data *conn = TLS->ev_base; @@ -476,6 +488,25 @@ static void request_code (struct tgl_state *TLS) { } } +static void request_name_code_entered (PurpleConnection* gc, PurpleRequestFields* fields) { + connection_data *conn = purple_connection_get_protocol_data(gc); + struct tgl_state *TLS = conn->TLS; + char const *username = purple_account_get_username(conn->pa); + + const char* first = purple_request_fields_get_string(fields, "first_name"); + const char* last = purple_request_fields_get_string(fields, "last_name"); + const char* code = purple_request_fields_get_string(fields, "code"); + if (!first || !last || !code) { + request_name_and_code (TLS); + return; + } + + tgl_do_send_code_result_auth(TLS, username, (int)strlen(username), conn->hash, + (int)strlen (conn->hash), code, (int)strlen (code), first, + (int)strlen (first), last, (int)strlen (last), + code_auth_receive_result, NULL); +} + static void request_name_and_code (struct tgl_state *TLS) { debug ("Phone is not registered, registering..."); @@ -505,6 +536,41 @@ static void request_name_and_code (struct tgl_state *TLS) { } } +static void request_password_entered (struct request_password_data *data, PurpleRequestFields* fields) { + const char* pass = purple_request_fields_get_string (fields, "password"); + data->callback (data->TLS, pass, data->arg); + free (data); +} + +void request_password (struct tgl_state *TLS, + void (*callback)(struct tgl_state *TLS, const char *string, void *arg), + void *arg) { + connection_data *conn = TLS->ev_base; + + struct request_password_data *data = malloc (sizeof(struct request_password_data)); + data->TLS = TLS; + data->arg = arg; + data->callback = callback; + + PurpleRequestFields* fields = purple_request_fields_new(); + PurpleRequestField* field = NULL; + + PurpleRequestFieldGroup* group = purple_request_field_group_new (""); + field = purple_request_field_string_new ("password", "Password", "", 0); + purple_request_field_string_set_masked (field, TRUE); + purple_request_field_group_add_field (group, field); + purple_request_fields_add_group (fields, group); + + if (!purple_request_fields (conn->gc, "Password needed", "Enter password for two factor authentication", + NULL, fields, "Ok", G_CALLBACK(request_password_entered), "Cancel", NULL, conn->pa, + NULL, NULL, data)) { + + const char *error = "No password for two factor authentication, enter it in extended settings."; + purple_connection_error_reason (conn->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, error); + purple_notify_error (_telegram_protocol, "Password invalid", "Password invalid", error); + } +} + void write_secret_chat_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_secret_chat *E) { if (!success) { return; } write_secret_chat_file (TLS); @@ -565,7 +631,7 @@ static void telegram_send_sms (struct tgl_state *TLS) { } connection_data *conn = TLS->ev_base; char const *username = purple_account_get_username(conn->pa); - tgl_do_send_code (TLS, username, sign_in_callback, 0); + tgl_do_send_code (TLS, username, (int) strlen(username), sign_in_callback, NULL); } static int all_authorized (struct tgl_state *TLS) { @@ -606,7 +672,7 @@ void telegram_login (struct tgl_state *TLS) { /** * This function generates a png image to visualize the sha1 key from an encrypted chat. */ -int generate_ident_icon (struct tgl_state *TLS, unsigned char* sha1_key) { +int tgp_visualize_key (struct tgl_state *TLS, unsigned char* sha1_key) { int colors[4] = { 0xffffff, 0xd5e6f3, diff --git a/telegram-base.h b/telegram-base.h index 10ced40..53155ef 100644 --- a/telegram-base.h +++ b/telegram-base.h @@ -22,6 +22,12 @@ #include "telegram-purple.h" +struct request_password_data { + struct tgl_state *TLS; + void (*callback)(struct tgl_state *TLS, const char *string, void *arg); + void *arg; +}; + void read_state_file (struct tgl_state *TLS); void read_auth_file (struct tgl_state *TLS); void write_auth_file (struct tgl_state *TLS); @@ -33,7 +39,14 @@ void write_secret_chat_gw (struct tgl_state *TLS, void *extra, int success, stru void telegram_login (struct tgl_state *TLS); void request_code_entered (gpointer data, const gchar *code); -int generate_ident_icon(struct tgl_state *TLS, unsigned char* sha1_key); +void request_password (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, const char *string, void *arg), void *arg); void request_accept_secret_chat (struct tgl_state *TLS, struct tgl_secret_chat *U); + +gchar *get_config_dir (struct tgl_state *TLS, char const *username); +gchar *get_download_dir (struct tgl_state *TLS); +void assert_file_exists (PurpleConnection *gc, const char *filepath, const char *format); + +int tgp_visualize_key(struct tgl_state *TLS, unsigned char* sha1_key); + #endif diff --git a/telegram-purple.c b/telegram-purple.c index 572aa54..8d7167e 100755 --- a/telegram-purple.c +++ b/telegram-purple.c @@ -59,6 +59,7 @@ #include #include #include +#include #include "tgp-structs.h" #include "tgp-2prpl.h" #include "tgp-net.h" @@ -71,6 +72,7 @@ #include "tgp-ft.h" #include "tgp-msg.h" +static void get_password (struct tgl_state *TLS, const char *prompt, int flags, void (*callback)(struct tgl_state *TLS, const char *string, void *arg), void *arg); static void update_message_received (struct tgl_state *TLS, struct tgl_message *M); static void update_user_handler (struct tgl_state *TLS, struct tgl_user *U, unsigned flags); static void update_user_status_handler (struct tgl_state *TLS, struct tgl_user *U); @@ -86,6 +88,7 @@ const char *pk_path = "/etc/telegram-purple/server.pub"; struct tgl_update_callback tgp_callback = { .logprintf = debug, + .get_string = get_password, .new_msg = update_message_received, .msg_receive = update_message_received, .user_update = update_user_handler, @@ -250,6 +253,19 @@ static char *format_print_name (struct tgl_state *TLS, tgl_peer_id_t id, const c return tgl_strdup (s); } +static void get_password (struct tgl_state *TLS, const char *prompt, int flags, + void (*callback)(struct tgl_state *TLS, const char *string, void *arg), void *arg) { + connection_data *conn = TLS->ev_base; + const char *P = purple_account_get_string (conn->pa, TGP_KEY_PASSWORD_TWO_FACTOR, NULL); + if (str_not_empty (P)) { + if (conn->password_retries++ < 1) { + callback (TLS, P, arg); + return; + } + } + request_password (TLS, callback, arg); +} + static void on_contact_added (struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_user *users[]) { PurpleBuddy *buddy = callback_extra; @@ -261,7 +277,7 @@ static void on_contact_added (struct tgl_state *TLS,void *callback_extra, int su } } -static void on_userpic_loaded (struct tgl_state *TLS, void *extra, int success, char *filename) { +static void on_userpic_loaded (struct tgl_state *TLS, void *extra, int success, const char *filename) { connection_data *conn = TLS->ev_base; struct download_desc *dld = extra; @@ -290,8 +306,7 @@ fin: free (dld); } -void on_user_get_info (struct tgl_state *TLS, void *info_data, int success, struct tgl_user *U) -{ +void on_user_get_info (struct tgl_state *TLS, void *info_data, int success, struct tgl_user *U) { get_user_info_data *user_info_data = (get_user_info_data *)info_data; tgl_peer_t *P = tgl_peer_get (TLS, user_info_data->peer); @@ -299,8 +314,8 @@ void on_user_get_info (struct tgl_state *TLS, void *info_data, int success, stru warning ("on_user_get_info not successfull, aborting..."); return; } - - if (U->photo.sizes_num == 0) { + + if (!U->photo || U->photo->sizes_num == 0) { // No profile pic to load, display it right away if (user_info_data->show_info) { PurpleNotifyUserInfo *info = p2tgl_notify_peer_info_new (TLS, P); @@ -312,7 +327,7 @@ void on_user_get_info (struct tgl_state *TLS, void *info_data, int success, stru struct download_desc *dld = malloc (sizeof(struct download_desc)); dld->data = U; dld->get_user_info_data = info_data; - tgl_do_load_photo (TLS, &U->photo, on_userpic_loaded, dld); + tgl_do_load_photo (TLS, U->photo, on_userpic_loaded, dld); } } @@ -342,11 +357,11 @@ void on_ready (struct tgl_state *TLS) { tggroup = purple_group_new ("Telegram"); purple_blist_add_group (tggroup, NULL); } - + debug ("seq = %d, pts = %d, date = %d", TLS->seq, TLS->pts, TLS->date); tgl_do_get_difference (TLS, purple_account_get_bool (conn->pa, "history-sync-all", FALSE), NULL, NULL); - tgl_do_get_dialog_list (TLS, 0, 0); + tgl_do_get_dialog_list (TLS, 0, 0, NULL, NULL); tgl_do_update_contact_list (TLS, 0, 0); } @@ -437,28 +452,17 @@ static void tgprpl_login (PurpleAccount * acct) { debug ("tgprpl_login()"); PurpleConnection *gc = purple_account_get_connection (acct); - char const *username = purple_account_get_username (acct); struct tgl_state *TLS = tgl_state_alloc (); connection_data *conn = connection_data_init (TLS, gc, acct); purple_connection_set_protocol_data (gc, conn); - TLS->base_path = g_strdup_printf ("%s/%s/%s", purple_user_dir(), config_dir, username); - char *ddir = g_strdup_printf ("%s/%s", TLS->base_path, "downloads"); - tgl_set_download_directory (TLS, ddir); - g_mkdir_with_parents (TLS->base_path, 0700); - g_mkdir_with_parents (ddir, 0700); - free (ddir); + TLS->base_path = get_config_dir(TLS, purple_account_get_username (acct)); + tgl_set_download_directory (TLS, get_download_dir(TLS)); + assert_file_exists (gc, pk_path, "Error, server public key not found at %s." + " Make sure that Telegram-Purple is installed properly."); debug ("base configuration path: '%s'", TLS->base_path); - if (!g_file_test(pk_path, G_FILE_TEST_EXISTS)) { - gchar *msg = g_strdup_printf ("Error, server public key not found at %s." - " Make sure that Telegram-Purple is installed properly.", pk_path); - purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR, msg); - g_free (msg); - return; - } - tgl_set_verbosity (TLS, 4); tgl_set_rsa_key (TLS, pk_path); @@ -558,7 +562,7 @@ static void tgprpl_set_status (PurpleAccount * acct, PurpleStatus * status) { if (!gc) { return; } connection_data *conn = purple_connection_get_protocol_data (gc); - if (p2tgl_status_is_present(status)) { + if (p2tgl_status_is_present (status) && p2tgl_send_notifications (acct)) { pending_reads_send_all (conn->pending_reads, conn->TLS); } } @@ -772,10 +776,14 @@ static void tgprpl_init (PurplePlugin *plugin) { // Login + opt = purple_account_option_string_new ("Password (two factor authentication)", + TGP_KEY_PASSWORD_TWO_FACTOR, NULL); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, opt); + opt = purple_account_option_bool_new("Fallback SMS Verification", "compat-verification", 0); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, opt); - + // Messaging GList *verification_values = NULL; @@ -803,12 +811,20 @@ static void tgprpl_init (PurplePlugin *plugin) { TGP_KEY_HISTORY_RETRIEVAL_THRESHOLD, TGP_DEFAULT_HISTORY_RETRIEVAL_THRESHOLD); prpl_info.protocol_options = g_list_append (prpl_info.protocol_options, opt); + + + // Read notifications opt = purple_account_option_bool_new ("Display read notifications", TGP_KEY_DISPLAY_READ_NOTIFICATIONS, TGP_DEFAULT_DISPLAY_READ_NOTIFICATIONS); prpl_info.protocol_options = g_list_append (prpl_info.protocol_options, opt); + opt = purple_account_option_bool_new ("Send read notifications when present.", + TGP_KEY_SEND_READ_NOTIFICATIONS, + TGP_DEFAULT_SEND_READ_NOTIFICATIONS); + prpl_info.protocol_options = g_list_append (prpl_info.protocol_options, opt); + _telegram_protocol = plugin; } diff --git a/telegram-purple.h b/telegram-purple.h index 3fc4992..942c8ba 100644 --- a/telegram-purple.h +++ b/telegram-purple.h @@ -25,7 +25,7 @@ #define PLUGIN_ID "prpl-telegram" #define TG_AUTHOR "Matthias Jentsch , Vitaly Valtman, Christopher Althaus , Markus Endres . Based on libtgl by Vitaly Valtman." #define TG_DESCRIPTION "Telegram protocol." -#define TG_BUILD "11" +#define TG_BUILD "12" #include #include @@ -39,21 +39,26 @@ #define TGP_MAX_MSG_SIZE 4096 #define TGP_DEFAULT_MAX_MSG_SPLIT_COUNT 4 +#define TGP_KEY_PASSWORD_TWO_FACTOR "password-two-factor" + #define TGP_DEFAULT_ACCEPT_SECRET_CHATS "ask" #define TGP_KEY_ACCEPT_SECRET_CHATS "accept-secret-chats" #define TGP_DEFAULT_INACTIVE_DAYS_OFFLINE 7 #define TGP_KEY_INACTIVE_DAYS_OFFLINE "inactive-days-offline" -#define TGP_DEFAULT_DISPLAY_READ_NOTIFICATIONS FALSE -#define TGP_KEY_DISPLAY_READ_NOTIFICATIONS "display-read-notifications" - #define TGP_DEFAULT_HISTORY_RETRIEVAL_THRESHOLD 14 #define TGP_KEY_HISTORY_RETRIEVAL_THRESHOLD "history-retrieve-days" #define TGP_KEY_HISTORY_SYNC_ALL "history-sync-all" #define TGP_DEFAULT_HISTORY_SYNC_ALL FALSE +#define TGP_DEFAULT_DISPLAY_READ_NOTIFICATIONS FALSE +#define TGP_KEY_DISPLAY_READ_NOTIFICATIONS "display-read-notifications" + +#define TGP_DEFAULT_SEND_READ_NOTIFICATIONS TRUE +#define TGP_KEY_SEND_READ_NOTIFICATIONS "send-read-notifications" + void on_chat_get_info (struct tgl_state *TLS, void *extra, int success, struct tgl_chat *C); void on_ready (struct tgl_state *TLS); extern const char *pk_path; diff --git a/tgl b/tgl index 5e36b2b..195b2bc 160000 --- a/tgl +++ b/tgl @@ -1 +1 @@ -Subproject commit 5e36b2bc84f47656eb82bb0039dadb4c5133c996 +Subproject commit 195b2bcccdefd63282654c4d827315a48b677f97 diff --git a/tgp-2prpl.c b/tgp-2prpl.c index 3af8380..27f979c 100644 --- a/tgp-2prpl.c +++ b/tgp-2prpl.c @@ -17,6 +17,11 @@ Copyright Matthias Jentsch 2014 */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "telegram-purple.h" #include "tgp-2prpl.h" #include "tgp-structs.h" @@ -45,12 +50,17 @@ gchar *p2tgl_strdup_alias (tgl_peer_t *user) { return g_strdup (user->print_name); } -int p2tgl_status_is_present (PurpleStatus *status) -{ +int p2tgl_status_is_present (PurpleStatus *status) { const char *name = purple_status_get_id (status); return !(strcmp (name, "unavailable") == 0 || strcmp (name, "away") == 0); } +int p2tgl_send_notifications (PurpleAccount *acct) { + int ret = purple_account_get_bool (acct, TGP_KEY_SEND_READ_NOTIFICATIONS, TGP_DEFAULT_SEND_READ_NOTIFICATIONS); + debug ("sending notifications: %d", ret); + return ret; +} + /* Disclaimer: I stole this function from davidgfnet's whatsapp plugin, all credit for it goes to him @@ -385,7 +395,7 @@ PurpleNotifyUserInfo *p2tgl_notify_encrypted_chat_info_new (struct tgl_state *TL } if (secret->first_key_sha[0]) { - int sha1key_store_id = generate_ident_icon (TLS, secret->first_key_sha); + int sha1key_store_id = tgp_visualize_key (TLS, secret->first_key_sha); if (sha1key_store_id != -1) { char *ident_icon = format_img_full (sha1key_store_id); purple_notify_user_info_add_pair (info, "Secret key", ident_icon); @@ -424,6 +434,21 @@ int p2tgl_imgstore_add_with_id (const char* filename) { return id; } +#ifdef HAVE_LIBWEBP +int p2tgl_imgstore_add_with_id_webp (const char *filename) { + size_t pngsize; + void *png = tgp_webp_load_png (filename, &pngsize); + if (!png) { return -1; } + + // will be owned by libpurple imgstore, which uses glib functions for managing memory + void *pngdub = g_memdup (png, (guint)pngsize); + free (png); + + int imgStoreId = purple_imgstore_add_with_id (pngdub, pngsize, NULL); + return imgStoreId; +} +#endif + void p2tgl_buddy_icons_set_for_user (PurpleAccount *pa, tgl_peer_id_t *id, const char* filename) { char *who = g_strdup_printf("%d", tgl_get_peer_id(*id)); diff --git a/tgp-2prpl.h b/tgp-2prpl.h index 2676c18..0efdad0 100644 --- a/tgp-2prpl.h +++ b/tgp-2prpl.h @@ -38,6 +38,7 @@ char *p2tgl_strdup_id (tgl_peer_id_t user); char *p2tgl_strdup_alias(tgl_peer_t *user); int p2tgl_status_is_present (PurpleStatus *status); +int p2tgl_send_notifications (PurpleAccount *acct); PurpleConversation *p2tgl_got_joined_chat (struct tgl_state *TLS, struct tgl_chat *chat); void p2tgl_got_chat_invite (PurpleConnection *gc, tgl_peer_t *chat, tgl_peer_id_t inviter, const char *message); @@ -78,5 +79,6 @@ PurpleNotifyUserInfo *p2tgl_notify_encrypted_chat_info_new (struct tgl_state *TL void p2tgl_blist_alias_buddy (PurpleBuddy *buddy, struct tgl_user *user); int p2tgl_imgstore_add_with_id (const char* filename); +int p2tgl_imgstore_add_with_id_webp (const char *filename); void p2tgl_buddy_icons_set_for_user (PurpleAccount *pa, tgl_peer_id_t *id, const char* filename); #endif diff --git a/tgp-chat.c b/tgp-chat.c index 41c36d9..21842cf 100644 --- a/tgp-chat.c +++ b/tgp-chat.c @@ -41,16 +41,17 @@ void chat_users_update (struct tgl_state *TLS, struct tgl_chat *chat) { PurpleConversation *chat_show (PurpleConnection *gc, int id) { connection_data *conn = purple_connection_get_protocol_data(gc); PurpleConversation *convo = purple_find_chat (gc, id); + PurpleConvChat *chat = purple_conversation_get_chat_data (convo); tgl_peer_t *P = tgl_peer_get (conn->TLS, TGL_MK_CHAT(id)); - if (! convo) { - if (! P) { - warning ("Chat %d not existing, not showing...", id); - return NULL; - } - convo = p2tgl_got_joined_chat (conn->TLS, &P->chat); - chat_users_update (conn->TLS, &P->chat); + if (! P) { + warning ("Chat %d not existing, not showing...", id); + return NULL; } + if (! convo || (chat && purple_conv_chat_has_left (chat))) { + convo = p2tgl_got_joined_chat (conn->TLS, &P->chat); + } + chat_users_update (conn->TLS, &P->chat); return convo; } diff --git a/tgp-ft.c b/tgp-ft.c index 85acdeb..13b8728 100644 --- a/tgp-ft.c +++ b/tgp-ft.c @@ -26,11 +26,37 @@ #include #include #include +#include "telegram-purple.h" static void tgprpl_xfer_free_data (struct tgp_xfer_send_data *data); +static char *tgp_strdup_determine_filename (const char *mime, const char *caption, + int flags, long long hash) { + if (caption) { + return g_strdup (caption); + } + + const char *type = NULL; + if (mime) { + type = tgp_mime_to_filetype (mime); + } + if (!type) { + if (flags & TGLDF_IMAGE) { + type = "png"; + } else if (flags & TGLDF_AUDIO) { + type = "ogg"; + } else if (flags & TGLDF_VIDEO) { + type = "mp4"; + } else if (flags & TGLDF_STICKER) { + type = "webp"; + } else { + type = "bin"; + } + } + return g_strdup_printf ("%lld.%s", ABS(hash), type); +} -static void tgprpl_xfer_recv_on_finished (struct tgl_state *TLS, void *_data, int success, char *filename) { +static void tgprpl_xfer_recv_on_finished (struct tgl_state *TLS, void *_data, int success, const char *filename) { debug ("tgprpl_xfer_recv_on_finished()"); struct tgp_xfer_send_data *data = _data; @@ -43,7 +69,7 @@ static void tgprpl_xfer_recv_on_finished (struct tgl_state *TLS, void *_data, in } g_unlink (purple_xfer_get_local_filename (data->xfer)); - g_rename (filename, purple_xfer_get_local_filename(data->xfer)); + g_rename (filename, purple_xfer_get_local_filename (data->xfer)); } else { failure ("ERROR xfer failed"); @@ -120,13 +146,9 @@ static gboolean tgprpl_xfer_upload_progress (gpointer _data) { static void tgprpl_xfer_recv_init (PurpleXfer *X) { debug ("tgprpl_xfer_recv_init"); struct tgp_xfer_send_data *data = X->data; - purple_xfer_start (X, -1, NULL, 0); - const char *who = purple_xfer_get_remote_user (X); - debug ("who: %s", who); tgl_peer_t *P = find_peer_by_name (data->conn->TLS, who); - if (P) { if (data->document) { tgl_do_load_document (data->conn->TLS, data->document, tgprpl_xfer_recv_on_finished, data); @@ -138,7 +160,6 @@ static void tgprpl_xfer_recv_init (PurpleXfer *X) { } else { warning ("User not found, not downloading..."); } - data->timer = purple_timeout_add (100, tgprpl_xfer_upload_progress, X); } @@ -154,7 +175,15 @@ static void tgprpl_xfer_send_init (PurpleXfer *X) { tgl_peer_t *P = find_peer_by_name (data->conn->TLS, who); if (P) { - tgl_do_send_document (data->conn->TLS, -2, P->id, (char*)localfile, tgprpl_xfer_on_finished, data); + if (tgl_get_peer_type (P->id) != TGL_PEER_ENCR_CHAT) { + tgl_do_send_document (data->conn->TLS, P->id, (char*) localfile, NULL, + 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, tgprpl_xfer_on_finished, data); + } + else { + purple_notify_message (_telegram_protocol, PURPLE_NOTIFY_MSG_ERROR, "Not supported", + "Sorry, sending documents to encrypted chats not yet supported.", + NULL, NULL, NULL); + } } data->timer = purple_timeout_add (100, tgprpl_xfer_upload_progress, X); @@ -218,8 +247,14 @@ static PurpleXfer *tgprpl_new_xfer_recv (PurpleConnection * gc, const char *who) void tgprpl_recv_file (PurpleConnection * gc, const char *who, struct tgl_document *D) { debug ("tgprpl_recv_file()"); PurpleXfer *X = tgprpl_new_xfer_recv (gc, who); + + char *filename = tgp_strdup_determine_filename (D->mime_type, D->caption, D->flags, + D->access_hash); + purple_xfer_set_filename (X, filename); + g_free (filename); + + purple_xfer_set_size (X, D->size); - purple_xfer_set_filename (X, D->caption ? D->caption : D->mime_type); tgprpl_xfer_init_data (X, purple_connection_get_protocol_data (gc), D, NULL); purple_xfer_request (X); } @@ -228,7 +263,13 @@ void tgprpl_recv_encr_file (PurpleConnection * gc, const char *who, struct tgl_e debug ("tgprpl_recv_encr_file()"); PurpleXfer *X = tgprpl_new_xfer_recv (gc, who); - purple_xfer_set_filename (X, D->caption ? D->caption : D->mime_type); + char *filename = tgp_strdup_determine_filename (D->mime_type, D->caption, D->flags, + D->access_hash); + purple_xfer_set_filename (X, filename); + g_free (filename); + + purple_xfer_set_size (X, D->size); + tgprpl_xfer_init_data (X, purple_connection_get_protocol_data (gc), NULL, D); purple_xfer_request (X); } diff --git a/tgp-msg.c b/tgp-msg.c index 04bec6e..ea3beb2 100644 --- a/tgp-msg.c +++ b/tgp-msg.c @@ -18,6 +18,10 @@ Copyright Matthias Jentsch 2014-2015 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -36,7 +40,7 @@ static void tgp_msg_err_out (struct tgl_state *TLS, const char *error, tgl_peer_id_t to); static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) { - assert (M && M->service); + assert (M && M->flags & TGLMF_SERVICE); char *txt_user = NULL; char *txt_action = NULL; char *txt = NULL; @@ -119,18 +123,8 @@ static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) { return txt; } -static char *format_document_desc (char *type, char *caption, gint64 size) { - char *s = tgp_g_format_size (size); - char *msg = g_strdup_printf ("[%s] %s %s", type, caption, s); - g_free (s); - return msg; -} - static char *format_message (struct tgl_message *M) { switch (M->media.type) { - case tgl_message_media_photo_encr: - return format_document_desc ("ENCRYPTED PHOTO", "(not yet supported)", M->media.encr_photo.size); - break; case tgl_message_media_contact: return g_strdup_printf ("%s %s
%s", M->media.first_name, M->media.last_name, M->media.phone); break; @@ -163,10 +157,12 @@ static gboolean tgp_msg_send_schedule_cb (gpointer data) { connection_data *conn = data; conn->out_timer = 0; struct tgp_msg_sending *D = NULL; - + while ((D = g_queue_peek_head (conn->out_messages))) { g_queue_pop_head (conn->out_messages); - tgl_do_send_message (D->TLS, D->to, D->msg, (int)strlen (D->msg), tgp_msg_send_done, NULL); + + // TODO: option for disable_msg_preview + tgl_do_send_message(D->TLS, D->to, D->msg, (int)strlen (D->msg), 0, tgp_msg_send_done, NULL); tgp_msg_sending_free (D); } return FALSE; @@ -222,6 +218,11 @@ int tgp_msg_send (struct tgl_state *TLS, const char *message, tgl_peer_id_t to) gchar *img = NULL; gchar *stripped = NULL; if ((img = g_strrstr (message, "message); g_error_free (err); + return 0; } } } - // send remaining text as additional plaintext message - stripped = purple_markup_strip_html (message); - int ret = tgp_msg_send_split (TLS, stripped, to); - g_free (stripped); - return ret; + // no image id found in image + return 0; } #ifndef __ADIUM_ @@ -280,46 +282,64 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) { struct tgl_message *M = C->msg; char *text = NULL; int flags = 0; - - // Filter message updates and deletes, are not created and - // all messages in general that were already displayed, or shouldn't be displayed - if ((M->flags & (FLAG_MESSAGE_EMPTY | FLAG_DELETED)) || - !(M->flags & FLAG_CREATED) || + + // only display new messages, ignore updates or deletions + if ((M->flags & (TGLMF_EMPTY | TGLMF_DELETED)) || + !(M->flags & TGLMF_CREATED) || !M->message || - our_msg (TLS, M) || + tgp_outgoing_msg (TLS, M) || !tgl_get_peer_type (M->to_id)) { return; } - - if (M->service) { + + if (M->flags & TGLMF_SERVICE) { text = format_service_msg (TLS, M); flags |= PURPLE_MESSAGE_SYSTEM; } + else if (M->media.type == tgl_message_media_document && M->media.document->flags & TGLDF_STICKER) { +#ifdef HAVE_LIBWEBP + char *filename = C->data; + int img = p2tgl_imgstore_add_with_id_webp (filename); + if (img <= 0) { failure ("Cannot display sticker, adding to imgstore failed"); return; } + used_images_add (conn, img); + text = format_img_full (img); + flags |= PURPLE_MESSAGE_IMAGES; + g_free (filename); +#else + char *txt_user = p2tgl_strdup_alias (tgl_peer_get (TLS, M->from_id)); + text = g_strdup_printf ("%s sent a sticker", txt_user); + flags |= PURPLE_MESSAGE_SYSTEM; + g_free (txt_user); +#endif + } + else if (M->media.type == tgl_message_media_photo || + (M->media.type == tgl_message_media_document_encr && M->media.encr_document->flags & TGLDF_IMAGE)) { + char *filename = C->data; + int img = p2tgl_imgstore_add_with_id (filename); + if (img <= 0) { + failure ("Cannot display picture message, adding to imgstore failed."); + return; + } + used_images_add (conn, img); + text = format_img_full (img); + flags |= PURPLE_MESSAGE_IMAGES; + g_free (filename); + } else if (M->media.type == tgl_message_media_document) { char *who = p2tgl_strdup_id (M->from_id); - if (! out_msg(TLS, M)) { - tgprpl_recv_file (conn->gc, who, &M->media.document); + if (! tgp_our_msg(TLS, M)) { + tgprpl_recv_file (conn->gc, who, M->media.document); } g_free (who); return; } else if (M->media.type == tgl_message_media_document_encr) { - char *who = p2tgl_strdup_id (M->from_id); - if (! out_msg(TLS, M)) { - tgprpl_recv_encr_file (conn->gc, who, &M->media.encr_document); + char *who = p2tgl_strdup_id (M->to_id); + if (! tgp_our_msg(TLS, M)) { + tgprpl_recv_encr_file (conn->gc, who, M->media.encr_document); } g_free (who); - } - else if (M->media.type == tgl_message_media_photo) { - char *filename = C->data; - int imgStoreId = p2tgl_imgstore_add_with_id (filename); - if (imgStoreId <= 0) { - failure ("Cannot display picture message, adding to imgstore failed."); - return; - } - used_images_add (conn, imgStoreId); - text = format_img_full (imgStoreId); - flags |= PURPLE_MESSAGE_IMAGES; + return; } else { text = format_message (M); @@ -344,7 +364,7 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) { break; } case TGL_PEER_USER: { - if (out_msg (TLS, M)) { + if (tgp_our_msg (TLS, M)) { flags |= PURPLE_MESSAGE_SEND; flags &= ~PURPLE_MESSAGE_RECV; p2tgl_got_im_combo (TLS, M->to_id, text, flags, M->date); @@ -356,7 +376,7 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) { } } - if (p2tgl_status_is_present (purple_account_get_active_status (conn->pa))) { + if (p2tgl_status_is_present (purple_account_get_active_status (conn->pa)) && p2tgl_send_notifications(conn->pa)) { pending_reads_send_all (conn->pending_reads, conn->TLS); } @@ -384,9 +404,9 @@ static void tgp_msg_process_in_ready (struct tgl_state *TLS) { } } -static void tgp_msg_on_loaded_photo (struct tgl_state *TLS, void *extra, int success, char *filename) { +static void tgp_msg_on_loaded_document (struct tgl_state *TLS, void *extra, int success, const char *filename) { struct tgp_msg_loading *C = extra; - C->data = filename; + C->data = (void *) g_strdup (filename); C->done = TRUE; tgp_msg_process_in_ready (TLS); } @@ -394,15 +414,28 @@ static void tgp_msg_on_loaded_photo (struct tgl_state *TLS, void *extra, int suc void tgp_msg_recv (struct tgl_state *TLS, struct tgl_message *M) { connection_data *conn = TLS->ev_base; struct tgp_msg_loading *C = tgp_msg_loading_init (TRUE, M); - + if (M->date != 0 && M->date < tgp_msg_oldest_relevant_ts (TLS)) { debug ("Message from %d on %d too old, ignored.", tgl_get_peer_id (M->from_id), M->date); return; } if (M->media.type == tgl_message_media_photo) { C->done = FALSE; - tgl_do_load_photo (TLS, &M->media.photo, tgp_msg_on_loaded_photo, C); + tgl_do_load_photo (TLS, M->media.photo, tgp_msg_on_loaded_document, C); } + if (M->media.type == tgl_message_media_document_encr && + M->media.encr_document->flags & TGLDF_IMAGE && + !(M->media.encr_document->flags & TGLDF_STICKER)) { + C->done = FALSE; + tgl_do_load_encr_document (TLS, M->media.encr_document, tgp_msg_on_loaded_document, C); + } + #ifdef HAVE_LIBWEBP + if (M->media.type == tgl_message_media_document && M->media.document->flags & TGLDF_STICKER) { + C->done = FALSE; + tgl_do_load_document (TLS, M->media.document, tgp_msg_on_loaded_document, C); + } + #endif + if (M->media.type == tgl_message_media_geo) { // TODO: load geo thumbnail } diff --git a/tgp-net.c b/tgp-net.c index eb192e2..24744d0 100644 --- a/tgp-net.c +++ b/tgp-net.c @@ -18,10 +18,6 @@ Copyright Vitaly Valtman 2013-2015 */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #define _GNU_SOURCE #include #include @@ -46,6 +42,8 @@ #include "telegram-base.h" #include #include +#include +#include #include #include diff --git a/tgp-structs.h b/tgp-structs.h index e2bcdaf..c13eb23 100755 --- a/tgp-structs.h +++ b/tgp-structs.h @@ -40,6 +40,7 @@ typedef struct { guint login_timer; guint out_timer; int in_fallback_chat; + int password_retries; } connection_data; typedef struct { diff --git a/tgp-utils.c b/tgp-utils.c index 90abeb6..b685592 100644 --- a/tgp-utils.c +++ b/tgp-utils.c @@ -18,8 +18,18 @@ Copyright Matthias Jentsch 2014-2015 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "tgp-utils.h" +#include "msglog.h" +#include "lodepng/lodepng.h" + #include +#ifdef HAVE_LIBWEBP +#include +#endif connection_data *get_conn_from_buddy (PurpleBuddy *buddy) { connection_data *c = purple_connection_get_protocol_data ( @@ -68,12 +78,12 @@ int str_not_empty (const char *string) { return string && string[0] != '\0'; } -int our_msg (struct tgl_state *TLS, struct tgl_message *M) { - return (M->flags & FLAG_SESSION_OUTBOUND) != 0; +int tgp_outgoing_msg (struct tgl_state *TLS, struct tgl_message *M) { + return (M->flags & TGLMF_SESSION_OUTBOUND); } -int out_msg (struct tgl_state *TLS, struct tgl_message *M) { - return M->out; +int tgp_our_msg (struct tgl_state *TLS, struct tgl_message *M) { + return TLS->our_id == tgl_get_peer_id(M->from_id); } tgl_peer_t *find_peer_by_name (struct tgl_state *TLS, const char *who) { @@ -124,3 +134,38 @@ void tgp_g_list_free_full (GList *list, GDestroyNotify free_func) { g_list_foreach (list, (GFunc)free_func, NULL); g_list_free (list); } + +const char *tgp_mime_to_filetype (const char *mime) { + int len = (int) strlen (mime); + int i; + for (i = 0; i < len - 1; i ++) { + if (mime[i] == '/') { + return mime + i + 1; + } + } + return NULL; +} + +#ifdef HAVE_LIBWEBP +void *tgp_webp_load_png (const char *filename, size_t *size) { + gchar *data = NULL; + size_t len; + GError *err = NULL; + g_file_get_contents (filename, &data, &len, &err); + if (err) { warning ("cannot open file %s: %s.", filename, err->message); return NULL; } + + int width, height; + uint8_t* decoded = WebPDecodeRGBA ((const uint8_t*)data, len, &width, &height); + g_free (data); + if (! decoded) { warning ("failed decoding webp"); return NULL; } + + unsigned char* png = NULL; + size_t pnglen; + unsigned error = lodepng_encode32 (&png, &pnglen, decoded, width, height); + free (decoded); + if (error) { warning ("failed encoding png"); return NULL; } + + *size = pnglen; + return png; +} +#endif diff --git a/tgp-utils.h b/tgp-utils.h index 168746d..614b7ab 100644 --- a/tgp-utils.h +++ b/tgp-utils.h @@ -34,12 +34,12 @@ tgl_peer_t *find_peer_by_name (struct tgl_state *TLS, const char *who); /** * Return whether this message was created by our client in this session */ -int our_msg (struct tgl_state *TLS, struct tgl_message *M); +int tgp_outgoing_msg (struct tgl_state *TLS, struct tgl_message *M); /** - * Return whether this message was created by the current user. + * Return whether this message was created by the current user */ -int out_msg (struct tgl_state *TLS, struct tgl_message *M); +int tgp_our_msg (struct tgl_state *TLS, struct tgl_message *M); const char *format_time (time_t date); char *format_img_full (int imgstore); @@ -49,5 +49,7 @@ long tgp_time_n_days_ago (int days); char *tgp_g_format_size (gint64 size); void tgp_g_queue_free_full (GQueue *queue, GDestroyNotify free_func); void tgp_g_list_free_full (GList *list, GDestroyNotify free_func); +const char *tgp_mime_to_filetype (const char *mime); +void *tgp_webp_load_png (const char *filename, size_t *size); #endif