first commit

This commit is contained in:
DrKLO 2013-10-25 19:19:00 +04:00
commit 4622ba9186
1029 changed files with 208243 additions and 0 deletions

339
LICENSE Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

13
TMessages.iml Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="Debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebug" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleTest" />
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="APK_PATH" value="/build/apk/TMessagesProj-debug-unaligned.apk" />
</configuration>
</facet>
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":TMessagesProj" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/source/r/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/source/r/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/assets" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/res" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/resources" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/apk" />
<excludeFolder url="file://$MODULE_DIR$/build/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android 4.3 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="support-v4-18.0.0" level="project" />
<orderEntry type="library" exported="" name="ComGoogleAndroidGmsPlayServices3159.aar" level="project" />
<orderEntry type="library" exported="" name="HockeySDK-3.0.0" level="project" />
<orderEntry type="library" exported="" name="native-libs" level="project" />
<orderEntry type="library" exported="" name="ComActionbarsherlockActionbarsherlock440.aar" level="project" />
</component>
</module>

View file

@ -0,0 +1,49 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.+'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
}
task nativeLibsToJar(
type: Zip,
description: 'create a jar archive of the native libs') {
destinationDir file("$buildDir/native-libs")
baseName 'native-libs'
extension 'jar'
from fileTree(dir: 'libs', include: '**/*.so')
into 'lib/'
}
tasks.withType(Compile) {
options.encoding = "UTF-8"
}
tasks.withType(Compile) {
compileTask -> compileTask.dependsOn(nativeLibsToJar)
}
dependencies {
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
compile 'com.google.android.gms:play-services:3.1.+'
compile 'net.hockeyapp.android:HockeySDK:3.0.0'
compile 'com.android.support:support-v4:18.0.+'
compile fileTree(dir: "$buildDir/native-libs", include: '*.jar')
}
android {
compileSdkVersion 18
buildToolsVersion "17.0.0"
defaultConfig {
minSdkVersion 8
targetSdkVersion 18
}
}

19
TMessagesProj/jni/Android.mk Executable file
View file

@ -0,0 +1,19 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tmessages
LOCAL_CFLAGS = -w
LOCAL_LDLIBS := -llog
LOCAL_SRC_FILES := \
./aes_core.c \
./aes_ige.c \
./aes_misc.c \
./jni.c \
./sqlite3.c \
./org_telegram_SQLite_SQLiteCursor.c \
./org_telegram_SQLite_SQLiteDatabase.c \
./org_telegram_SQLite_SQLitePreparedStatement.c \
./org_telegram_SQLite.c
include $(BUILD_SHARED_LIBRARY)

View file

@ -0,0 +1,2 @@
APP_PLATFORM := android-8
APP_ABI := armeabi armeabi-v7a x86 mips

147
TMessagesProj/jni/aes.h Normal file
View file

@ -0,0 +1,147 @@
/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
*/
#ifndef HEADER_AES_H
#define HEADER_AES_H
//#include <openssl/opensslconf.h>
#ifdef OPENSSL_NO_AES
#error AES is disabled.
#endif
#include <stddef.h>
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
/* Because array size can't be a const in C, the following two are macros.
Both sizes are in bytes. */
#define AES_MAXNR 14
#define AES_BLOCK_SIZE 16
#ifdef __cplusplus
extern "C" {
#endif
/* This should be a hidden type, but EVP requires that the size be known */
struct aes_key_st {
#ifdef AES_LONG
unsigned long rd_key[4 *(AES_MAXNR + 1)];
#else
unsigned int rd_key[4 *(AES_MAXNR + 1)];
#endif
int rounds;
};
typedef struct aes_key_st AES_KEY;
const char *AES_options(void);
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key, const int enc);
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num);
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num);
/* NB: the IV is _two_ blocks long */
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
/* NB: the IV is _four_ blocks long */
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
const AES_KEY *key2, const unsigned char *ivec,
const int enc);
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen);
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen);
#ifdef __cplusplus
}
#endif
#endif /* !HEADER_AES_H */

1358
TMessagesProj/jni/aes_core.c Normal file

File diff suppressed because it is too large Load diff

325
TMessagesProj/jni/aes_ige.c Normal file
View file

@ -0,0 +1,325 @@
/* crypto/aes/aes_ige.c -*- mode:C; c-file-style: "eay" -*- */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
*/
//#include "cryptlib.h"
#include "aes.h"
#include "aes_locl.h"
#include <assert.h>
#define OPENSSL_assert assert
#define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
typedef struct {
unsigned long data[N_WORDS];
} aes_block_t;
/* XXX: probably some better way to do this */
#if defined(__i386__) || defined(__x86_64__)
#define UNALIGNED_MEMOPS_ARE_FAST 1
#else
#define UNALIGNED_MEMOPS_ARE_FAST 0
#endif
#if UNALIGNED_MEMOPS_ARE_FAST
#define load_block(d, s) (d) = *(const aes_block_t *)(s)
#define store_block(d, s) *(aes_block_t *)(d) = (s)
#else
#define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE)
#define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE)
#endif
/* N.B. The IV for this mode is _twice_ the block size */
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc)
{
size_t n;
size_t len = length;
OPENSSL_assert(in && out && key && ivec);
OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
OPENSSL_assert((length%AES_BLOCK_SIZE) == 0);
len = length / AES_BLOCK_SIZE;
if (AES_ENCRYPT == enc)
{
if (in != out &&
(UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(long)==0))
{
aes_block_t *ivp = (aes_block_t *)ivec;
aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE);
while (len)
{
aes_block_t *inp = (aes_block_t *)in;
aes_block_t *outp = (aes_block_t *)out;
for(n=0 ; n < N_WORDS; ++n)
outp->data[n] = inp->data[n] ^ ivp->data[n];
AES_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key);
for(n=0 ; n < N_WORDS; ++n)
outp->data[n] ^= iv2p->data[n];
ivp = outp;
iv2p = inp;
--len;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
}
else
{
aes_block_t tmp, tmp2;
aes_block_t iv;
aes_block_t iv2;
load_block(iv, ivec);
load_block(iv2, ivec + AES_BLOCK_SIZE);
while (len)
{
load_block(tmp, in);
for(n=0 ; n < N_WORDS; ++n)
tmp2.data[n] = tmp.data[n] ^ iv.data[n];
AES_encrypt((unsigned char *)tmp2.data, (unsigned char *)tmp2.data, key);
for(n=0 ; n < N_WORDS; ++n)
tmp2.data[n] ^= iv2.data[n];
store_block(out, tmp2);
iv = tmp2;
iv2 = tmp;
--len;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, iv.data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
}
}
else
{
if (in != out &&
(UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(long)==0))
{
aes_block_t *ivp = (aes_block_t *)ivec;
aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE);
while (len)
{
aes_block_t tmp;
aes_block_t *inp = (aes_block_t *)in;
aes_block_t *outp = (aes_block_t *)out;
for(n=0 ; n < N_WORDS; ++n)
tmp.data[n] = inp->data[n] ^ iv2p->data[n];
AES_decrypt((unsigned char *)tmp.data, (unsigned char *)outp->data, key);
for(n=0 ; n < N_WORDS; ++n)
outp->data[n] ^= ivp->data[n];
ivp = inp;
iv2p = outp;
--len;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
}
else
{
aes_block_t tmp, tmp2;
aes_block_t iv;
aes_block_t iv2;
load_block(iv, ivec);
load_block(iv2, ivec + AES_BLOCK_SIZE);
while (len)
{
load_block(tmp, in);
tmp2 = tmp;
for(n=0 ; n < N_WORDS; ++n)
tmp.data[n] ^= iv2.data[n];
AES_decrypt((unsigned char *)tmp.data, (unsigned char *)tmp.data, key);
for(n=0 ; n < N_WORDS; ++n)
tmp.data[n] ^= iv.data[n];
store_block(out, tmp);
iv = tmp2;
iv2 = tmp;
--len;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, iv.data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
}
}
}
/*
* Note that its effectively impossible to do biIGE in anything other
* than a single pass, so no provision is made for chaining.
*/
/* N.B. The IV for this mode is _four times_ the block size */
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
const AES_KEY *key2, const unsigned char *ivec,
const int enc)
{
size_t n;
size_t len = length;
unsigned char tmp[AES_BLOCK_SIZE];
unsigned char tmp2[AES_BLOCK_SIZE];
unsigned char tmp3[AES_BLOCK_SIZE];
unsigned char prev[AES_BLOCK_SIZE];
const unsigned char *iv;
const unsigned char *iv2;
OPENSSL_assert(in && out && key && ivec);
OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
OPENSSL_assert((length%AES_BLOCK_SIZE) == 0);
if (AES_ENCRYPT == enc)
{
/* XXX: Do a separate case for when in != out (strictly should
check for overlap, too) */
/* First the forward pass */
iv = ivec;
iv2 = ivec + AES_BLOCK_SIZE;
while (len >= AES_BLOCK_SIZE)
{
for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
out[n] = in[n] ^ iv[n];
AES_encrypt(out, out, key);
for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
out[n] ^= iv2[n];
iv = out;
memcpy(prev, in, AES_BLOCK_SIZE);
iv2 = prev;
len -= AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
/* And now backwards */
iv = ivec + AES_BLOCK_SIZE*2;
iv2 = ivec + AES_BLOCK_SIZE*3;
len = length;
while(len >= AES_BLOCK_SIZE)
{
out -= AES_BLOCK_SIZE;
/* XXX: reduce copies by alternating between buffers */
memcpy(tmp, out, AES_BLOCK_SIZE);
for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
out[n] ^= iv[n];
/* hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); */
AES_encrypt(out, out, key);
/* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */
/* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */
for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
out[n] ^= iv2[n];
/* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */
iv = out;
memcpy(prev, tmp, AES_BLOCK_SIZE);
iv2 = prev;
len -= AES_BLOCK_SIZE;
}
}
else
{
/* First backwards */
iv = ivec + AES_BLOCK_SIZE*2;
iv2 = ivec + AES_BLOCK_SIZE*3;
in += length;
out += length;
while (len >= AES_BLOCK_SIZE)
{
in -= AES_BLOCK_SIZE;
out -= AES_BLOCK_SIZE;
memcpy(tmp, in, AES_BLOCK_SIZE);
memcpy(tmp2, in, AES_BLOCK_SIZE);
for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
tmp[n] ^= iv2[n];
AES_decrypt(tmp, out, key);
for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
out[n] ^= iv[n];
memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
iv = tmp3;
iv2 = out;
len -= AES_BLOCK_SIZE;
}
/* And now forwards */
iv = ivec;
iv2 = ivec + AES_BLOCK_SIZE;
len = length;
while (len >= AES_BLOCK_SIZE)
{
memcpy(tmp, out, AES_BLOCK_SIZE);
memcpy(tmp2, out, AES_BLOCK_SIZE);
for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
tmp[n] ^= iv2[n];
AES_decrypt(tmp, out, key);
for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
out[n] ^= iv[n];
memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
iv = tmp3;
iv2 = out;
len -= AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
}
}

View file

@ -0,0 +1,89 @@
/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
*/
#ifndef HEADER_AES_LOCL_H
#define HEADER_AES_LOCL_H
//#include <openssl/e_os2.h>
#ifdef OPENSSL_NO_AES
#error AES is disabled.
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
# define GETU32(p) SWAP(*((u32 *)(p)))
# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
#else
# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
#endif
#ifdef AES_LONG
typedef unsigned long u32;
#else
typedef unsigned int u32;
#endif
typedef unsigned short u16;
typedef unsigned char u8;
#define MAXKC (256/32)
#define MAXKB (256/8)
#define MAXNR 14
/* This controls loop-unrolling in aes_core.c */
#undef FULL_UNROLL
#endif /* !HEADER_AES_LOCL_H */

View file

@ -0,0 +1,85 @@
/* crypto/aes/aes_misc.c -*- mode:C; c-file-style: "eay" -*- */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
*/
//#include <openssl/opensslv.h>
//#include <openssl/crypto.h>
#include "aes.h"
#include "aes_locl.h"
const char AES_version[]="AES" ;//OPENSSL_VERSION_PTEXT;
const char *AES_options(void) {
#ifdef FULL_UNROLL
return "aes(full)";
#else
return "aes(partial)";
#endif
}
/* FIPS wrapper functions to block low level AES calls in FIPS mode */
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key)
{
#ifdef OPENSSL_FIPS
fips_cipher_abort(AES);
#endif
return private_AES_set_encrypt_key(userKey, bits, key);
}
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key)
{
#ifdef OPENSSL_FIPS
fips_cipher_abort(AES);
#endif
return private_AES_set_decrypt_key(userKey, bits, key);
}

183
TMessagesProj/jni/jni.c Normal file
View file

@ -0,0 +1,183 @@
#include <stdio.h>
#include <string.h>
#include <jni.h>
#include <sys/types.h>
#include <inttypes.h>
#include <android/log.h>
#include "aes.h"
#define LOG_TAG "tmessages_native"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
JNIEXPORT jbyteArray Java_org_telegram_messenger_Utilities_aesIgeEncryption(JNIEnv *env, jclass class, jbyteArray _what, jbyteArray _key, jbyteArray _iv, jboolean encrypt, jboolean changeIv) {
unsigned char *what = (unsigned char *)(*env)->GetByteArrayElements(env, _what, NULL);
unsigned char *key = (unsigned char *)(*env)->GetByteArrayElements(env, _key, NULL);
unsigned char *__iv = (unsigned char *)(*env)->GetByteArrayElements(env, _iv, NULL);
unsigned char *iv = 0;
if (!changeIv) {
iv = (unsigned char *)malloc((*env)->GetArrayLength(env, _iv));
memcpy(iv, __iv, (*env)->GetArrayLength(env, _iv));
} else {
iv = __iv;
}
int len = (*env)->GetArrayLength(env, _what);
AES_KEY akey;
if (!encrypt) {
AES_set_decrypt_key(key, (*env)->GetArrayLength(env, _key) * 8, &akey);
AES_ige_encrypt(what, what, len, &akey, iv, AES_DECRYPT);
} else {
AES_set_encrypt_key(key, (*env)->GetArrayLength(env, _key) * 8, &akey);
AES_ige_encrypt(what, what, len, &akey, iv, AES_ENCRYPT);
}
(*env)->ReleaseByteArrayElements(env, _what, what, 0);
(*env)->ReleaseByteArrayElements(env, _key, key, JNI_ABORT);
if (!changeIv) {
(*env)->ReleaseByteArrayElements(env, _iv, __iv, JNI_ABORT);
free(iv);
} else {
(*env)->ReleaseByteArrayElements(env, _iv, __iv, 0);
}
return _what;
}
uint64_t gcd(uint64_t a, uint64_t b){
while(a != 0 && b != 0) {
while((b & 1) == 0) b >>= 1;
while((a & 1) == 0) a >>= 1;
if(a > b) a -= b; else b -= a;
}
return b == 0 ? a : b;
}
JNIEXPORT jlong Java_org_telegram_messenger_Utilities_doPQNative(JNIEnv* env, jclass class, jlong _what) {
uint64_t what = _what;
int it = 0, i, j;
uint64_t g = 0;
for (i = 0; i < 3 || it < 1000; i++){
int q = ((lrand48() & 15) + 17) % what;
uint64_t x = (long long)lrand48() % (what - 1) + 1, y = x;
int lim = 1 << (i + 18), j;
for(j = 1; j < lim; j++){
++it;
uint64_t a = x, b = x, c = q;
while(b){
if(b & 1){
c += a;
if(c >= what) c -= what;
}
a += a;
if(a >= what) a -= what;
b >>= 1;
}
x = c;
uint64_t z = x < y ? what + x - y : x - y;
g = gcd(z, what);
if(g != 1) break;
if(!(j & (j - 1))) y = x;
}
if(g > 1 && g < what) break;
}
return g;
}
//sqlite
/*JNIEXPORT void Java_org_telegram_messenger_Utilities_beginTransaction(JNIEnv* env, jobject object, int dbHandle) {
sqlite3 *db = (sqlite3 *)dbHandle;
if (db == NULL) {
return;
}
sqlite3_exec(db, "BEGIN", 0, 0, 0);
}
JNIEXPORT void Java_org_telegram_messenger_Utilities_commitTransaction(JNIEnv* env, jobject object, int dbHandle) {
sqlite3 *db = (sqlite3 *)dbHandle;
if (db == NULL) {
return;
}
sqlite3_exec(db, "COMMIT", 0, 0, 0);
}
int Java_org_telegram_messenger_Utilities_step(JNIEnv* env, jobject object, int statementHandle) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int errcode = 0 ;
errcode = sqlite3_step(handle);
if (errcode == SQLITE_ROW) {
return 0;
} else if(errcode == SQLITE_DONE) {
return 1;
} else if(errcode == SQLITE_BUSY) {
return -1;
}
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
int Java_org_telegram_messenger_Utilities_columnType(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
return sqlite3_column_type(handle, columnIndex);
}
int Java_org_telegram_messenger_Utilities_columnIsNull(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
return SQLITE_NULL == valType;
}
int Java_org_telegram_messenger_Utilities_columnIntValue(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
if (SQLITE_NULL == valType) {
return 0;
}
return sqlite3_column_int(handle, columnIndex);
}
jdouble Java_org_telegram_messenger_Utilities_columnDoubleValue(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
if (SQLITE_NULL == valType) {
return 0;
}
return sqlite3_column_double(handle, columnIndex);
}
jstring Java_org_telegram_messenger_Utilities_columnStringValue(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
const char* str = sqlite3_column_text(handle, columnIndex);
if (str != 0) {
return (*env)->NewStringUTF(env, str);
}
return 0;
}
jbyteArray Java_org_telegram_messenger_Utilities_columnByteArrayValue(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
void *buf = sqlite3_column_blob(handle, columnIndex);
int length = sqlite3_column_bytes(handle, columnIndex);
if (buf != 0 && length > 0) {
jbyteArray result = (*env)->NewByteArray(env, length);
(*env)->SetByteArrayRegion(env, result, 0, length, buf);
return result;
}
return 0;
}*/

View file

@ -0,0 +1,11 @@
#include "sqlite3.h"
#include "org_telegram_SQLite.h"
void throw_sqlite3_exception(JNIEnv *env, sqlite3 *handle, int errcode) {
if (SQLITE_OK == errcode) {
errcode = sqlite3_errcode(handle);
}
const char *errmsg = sqlite3_errmsg(handle);
jclass exClass = (*env)->FindClass(env, "org/telegram/SQLite/SQLiteException");
(*env)->ThrowNew(env, exClass, errmsg);
}

View file

@ -0,0 +1,9 @@
#ifndef __SQLITE_H__
#define __SQLITE_H__
#include <jni.h>
#include "sqlite3.h"
void throw_sqlite3_exception(JNIEnv* env, sqlite3 *handle, int errcode);
#endif

View file

@ -0,0 +1,60 @@
#include "org_telegram_SQLite.h"
int Java_org_telegram_SQLite_SQLiteCursor_columnType(JNIEnv *env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
return sqlite3_column_type(handle, columnIndex);
}
int Java_org_telegram_SQLite_SQLiteCursor_columnIsNull(JNIEnv *env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
return SQLITE_NULL == valType;
}
int Java_org_telegram_SQLite_SQLiteCursor_columnIntValue(JNIEnv *env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
if (SQLITE_NULL == valType) {
return 0;
}
return sqlite3_column_int(handle, columnIndex);
}
long long Java_org_telegram_SQLite_SQLiteCursor_columnLongValue(JNIEnv *env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
if (SQLITE_NULL == valType) {
return 0;
}
return sqlite3_column_int64(handle, columnIndex);
}
double Java_org_telegram_SQLite_SQLiteCursor_columnDoubleValue(JNIEnv *env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
if (SQLITE_NULL == valType) {
return 0;
}
return sqlite3_column_double(handle, columnIndex);
}
jstring Java_org_telegram_SQLite_SQLiteCursor_columnStringValue(JNIEnv *env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
const char *str = sqlite3_column_text(handle, columnIndex);
if (str != 0) {
return (*env)->NewStringUTF(env, str);
}
return 0;
}
jbyteArray Java_org_telegram_SQLite_SQLiteCursor_columnByteArrayValue(JNIEnv *env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
void *buf = sqlite3_column_blob(handle, columnIndex);
int length = sqlite3_column_bytes(handle, columnIndex);
if (buf != 0 && length > 0) {
jbyteArray result = (*env)->NewByteArray(env, length);
(*env)->SetByteArrayRegion(env, result, 0, length, buf);
return result;
}
return 0;
}

View file

@ -0,0 +1,32 @@
#include "org_telegram_SQLite.h"
void Java_org_telegram_SQLite_SQLiteDatabase_closedb(JNIEnv *env, jobject object, int sqliteHandle) {
sqlite3 *handle = (sqlite3 *)sqliteHandle;
int err = sqlite3_close(handle);
if (SQLITE_OK != err) {
throw_sqlite3_exception(env, handle, err);
}
}
void Java_org_telegram_SQLite_SQLiteDatabase_beginTransaction(JNIEnv *env, jobject object, int sqliteHandle) {
sqlite3 *handle = (sqlite3 *)sqliteHandle;
sqlite3_exec(handle, "BEGIN", 0, 0, 0);
}
void Java_org_telegram_SQLite_SQLiteDatabase_commitTransaction(JNIEnv *env, jobject object, int sqliteHandle) {
sqlite3 *handle = (sqlite3 *)sqliteHandle;
sqlite3_exec(handle, "COMMIT", 0, 0, 0);
}
int Java_org_telegram_SQLite_SQLiteDatabase_opendb(JNIEnv *env, jobject object, jstring fileName) {
char const *fileNameStr = (*env)->GetStringUTFChars(env, fileName, 0);
sqlite3 *handle = 0;
int err = sqlite3_open(fileNameStr, &handle);
if (SQLITE_OK != err) {
throw_sqlite3_exception(env, handle, err);
}
if (fileNameStr != 0) {
(*env)->ReleaseStringUTFChars(env, fileName, fileNameStr);
}
return (int)handle;
}

View file

@ -0,0 +1,138 @@
#include "org_telegram_SQLite.h"
jfieldID queryArgsCountField;
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv* env = 0;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
jclass class = (*env)->FindClass(env, "org/telegram/SQLite/SQLitePreparedStatement");
queryArgsCountField = (*env)->GetFieldID(env, class, "queryArgsCount", "I");
return JNI_VERSION_1_4;
}
int Java_org_telegram_SQLite_SQLitePreparedStatement_step(JNIEnv* env, jobject object, int statementHandle) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int errcode = sqlite3_step(handle);
if (errcode == SQLITE_ROW) {
return 0;
} else if(errcode == SQLITE_DONE) {
return 1;
} else if(errcode == SQLITE_BUSY) {
return -1;
}
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
int Java_org_telegram_SQLite_SQLitePreparedStatement_prepare(JNIEnv *env, jobject object, int sqliteHandle, jstring sql) {
sqlite3* handle = (sqlite3 *)sqliteHandle;
char const *sqlStr = (*env)->GetStringUTFChars(env, sql, 0);
sqlite3_stmt *stmt_handle;
int errcode = sqlite3_prepare_v2(handle, sqlStr, -1, &stmt_handle, 0);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, handle, errcode);
} else {
int argsCount = sqlite3_bind_parameter_count(stmt_handle);
(*env)->SetIntField(env, object, queryArgsCountField, argsCount);
}
if (sqlStr != 0) {
(*env)->ReleaseStringUTFChars(env, sql, sqlStr);
}
return (int)stmt_handle;
}
void Java_org_telegram_SQLite_SQLitePreparedStatement_reset(JNIEnv *env, jobject object, int statementHandle) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int errcode = sqlite3_reset(handle);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
}
void Java_org_telegram_SQLite_SQLitePreparedStatement_finalize(JNIEnv *env, jobject object, int statementHandle) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int errcode = sqlite3_finalize (handle);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
}
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindByteArray(JNIEnv *env, jobject object, int statementHandle, int index, jbyteArray value) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
const void *buf = (*env)->GetByteArrayElements(env, value, 0);
int length = (*env)->GetArrayLength(env, value);
int errcode = sqlite3_bind_blob(handle, index, buf, length, SQLITE_STATIC);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
if (buf != 0) {
(*env)->ReleaseByteArrayElements(env, value, buf, 0);
}
}
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindString(JNIEnv *env, jobject object, int statementHandle, int index, jstring value) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle;
char const *valueStr = (*env)->GetStringUTFChars(env, value, 0);
int errcode = sqlite3_bind_text(handle, index, valueStr, -1, SQLITE_TRANSIENT);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
if (valueStr != 0) {
(*env)->ReleaseStringUTFChars(env, value, valueStr);
}
}
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindInt(JNIEnv *env, jobject object, int statementHandle, int index, int value) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle;
int errcode = sqlite3_bind_int(handle, index, value);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
}
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindLong(JNIEnv *env, jobject object, int statementHandle, int index, long long value) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle;
int errcode = sqlite3_bind_int64(handle, index, value);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
}
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindDouble(JNIEnv* env, jobject object, int statementHandle, int index, double value) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle;
int errcode = sqlite3_bind_double(handle, index, value);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
}
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindNull(JNIEnv* env, jobject object, int statementHandle, int index) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle;
int errcode = sqlite3_bind_null(handle, index);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
}

140460
TMessagesProj/jni/sqlite3.c Normal file

File diff suppressed because it is too large Load diff

7245
TMessagesProj/jni/sqlite3.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,484 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef _SQLITE3EXT_H_
#define _SQLITE3EXT_H_
#include "sqlite3.h"
typedef struct sqlite3_api_routines sqlite3_api_routines;
/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each others' shared
** libraries!
*/
struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
int (*aggregate_count)(sqlite3_context*);
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(sqlite3_stmt*,int,double);
int (*bind_int)(sqlite3_stmt*,int,int);
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(sqlite3_stmt*,int);
int (*bind_parameter_count)(sqlite3_stmt*);
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const char*));
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
int (*column_count)(sqlite3_stmt*pStmt);
const char * (*column_database_name)(sqlite3_stmt*,int);
const void * (*column_database_name16)(sqlite3_stmt*,int);
const char * (*column_decltype)(sqlite3_stmt*,int i);
const void * (*column_decltype16)(sqlite3_stmt*,int);
double (*column_double)(sqlite3_stmt*,int iCol);
int (*column_int)(sqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
const char * (*column_name)(sqlite3_stmt*,int);
const void * (*column_name16)(sqlite3_stmt*,int);
const char * (*column_origin_name)(sqlite3_stmt*,int);
const void * (*column_origin_name16)(sqlite3_stmt*,int);
const char * (*column_table_name)(sqlite3_stmt*,int);
const void * (*column_table_name16)(sqlite3_stmt*,int);
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
const void * (*column_text16)(sqlite3_stmt*,int iCol);
int (*column_type)(sqlite3_stmt*,int iCol);
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(sqlite3*,const void*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_function)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_function16)(sqlite3*,const void*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
int (*declare_vtab)(sqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(sqlite3*db);
const char * (*errmsg)(sqlite3*);
const void * (*errmsg16)(sqlite3*);
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
int (*expired)(sqlite3_stmt*);
int (*finalize)(sqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(sqlite3*);
void * (*get_auxdata)(sqlite3_context*,int);
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(sqlite3*);
sqlite_int64 (*last_insert_rowid)(sqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(sqlite3_stmt*pStmt);
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(sqlite3_context*,double);
void (*result_error)(sqlite3_context*,const char*,int);
void (*result_error16)(sqlite3_context*,const void*,int);
void (*result_int)(sqlite3_context*,int);
void (*result_int64)(sqlite3_context*,sqlite_int64);
void (*result_null)(sqlite3_context*);
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
int (*value_bytes16)(sqlite3_value*);
double (*value_double)(sqlite3_value*);
int (*value_int)(sqlite3_value*);
sqlite_int64 (*value_int64)(sqlite3_value*);
int (*value_numeric_type)(sqlite3_value*);
const unsigned char * (*value_text)(sqlite3_value*);
const void * (*value_text16)(sqlite3_value*);
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char *(*vmprintf)(const char*,va_list);
/* Added ??? */
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
/* Added by 3.3.13 */
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
/* Added by 3.4.1 */
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
int (*blob_bytes)(sqlite3_blob*);
int (*blob_close)(sqlite3_blob*);
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
int,sqlite3_blob**);
int (*blob_read)(sqlite3_blob*,void*,int,int);
int (*blob_write)(sqlite3_blob*,const void*,int,int);
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*),
void(*)(void*));
int (*file_control)(sqlite3*,const char*,int,void*);
sqlite3_int64 (*memory_highwater)(int);
sqlite3_int64 (*memory_used)(void);
sqlite3_mutex *(*mutex_alloc)(int);
void (*mutex_enter)(sqlite3_mutex*);
void (*mutex_free)(sqlite3_mutex*);
void (*mutex_leave)(sqlite3_mutex*);
int (*mutex_try)(sqlite3_mutex*);
int (*open_v2)(const char*,sqlite3**,int,const char*);
int (*release_memory)(int);
void (*result_error_nomem)(sqlite3_context*);
void (*result_error_toobig)(sqlite3_context*);
int (*sleep)(int);
void (*soft_heap_limit)(int);
sqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(sqlite3_vfs*,int);
int (*vfs_unregister)(sqlite3_vfs*);
int (*xthreadsafe)(void);
void (*result_zeroblob)(sqlite3_context*,int);
void (*result_error_code)(sqlite3_context*,int);
int (*test_control)(int, ...);
void (*randomness)(int,void*);
sqlite3 *(*context_db_handle)(sqlite3_context*);
int (*extended_result_codes)(sqlite3*,int);
int (*limit)(sqlite3*,int,int);
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
const char *(*sql)(sqlite3_stmt*);
int (*status)(int,int*,int*,int);
int (*backup_finish)(sqlite3_backup*);
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
int (*backup_pagecount)(sqlite3_backup*);
int (*backup_remaining)(sqlite3_backup*);
int (*backup_step)(sqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*));
int (*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
int (*extended_errcode)(sqlite3*);
void (*log)(int,const char*,...);
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(sqlite3_stmt*,int,int);
int (*strnicmp)(const char*,const char*,int);
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
int (*wal_autocheckpoint)(sqlite3*,int);
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
int (*vtab_config)(sqlite3*,int op,...);
int (*vtab_on_conflict)(sqlite3*);
/* Version 3.7.16 and later */
int (*close_v2)(sqlite3*);
const char *(*db_filename)(sqlite3*,const char*);
int (*db_readonly)(sqlite3*,const char*);
int (*db_release_memory)(sqlite3*);
const char *(*errstr)(int);
int (*stmt_busy)(sqlite3_stmt*);
int (*stmt_readonly)(sqlite3_stmt*);
int (*stricmp)(const char*,const char*);
int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
char *(*vsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
};
/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the sqlite3_api_routines structure
** definition. But the main library does not want to redefine
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#ifndef SQLITE_CORE
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
#endif
#define sqlite3_bind_blob sqlite3_api->bind_blob
#define sqlite3_bind_double sqlite3_api->bind_double
#define sqlite3_bind_int sqlite3_api->bind_int
#define sqlite3_bind_int64 sqlite3_api->bind_int64
#define sqlite3_bind_null sqlite3_api->bind_null
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
#define sqlite3_bind_text sqlite3_api->bind_text
#define sqlite3_bind_text16 sqlite3_api->bind_text16
#define sqlite3_bind_value sqlite3_api->bind_value
#define sqlite3_busy_handler sqlite3_api->busy_handler
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
#define sqlite3_changes sqlite3_api->changes
#define sqlite3_close sqlite3_api->close
#define sqlite3_collation_needed sqlite3_api->collation_needed
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
#define sqlite3_column_blob sqlite3_api->column_blob
#define sqlite3_column_bytes sqlite3_api->column_bytes
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
#define sqlite3_column_count sqlite3_api->column_count
#define sqlite3_column_database_name sqlite3_api->column_database_name
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
#define sqlite3_column_decltype sqlite3_api->column_decltype
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
#define sqlite3_column_double sqlite3_api->column_double
#define sqlite3_column_int sqlite3_api->column_int
#define sqlite3_column_int64 sqlite3_api->column_int64
#define sqlite3_column_name sqlite3_api->column_name
#define sqlite3_column_name16 sqlite3_api->column_name16
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
#define sqlite3_column_table_name sqlite3_api->column_table_name
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
#define sqlite3_column_text sqlite3_api->column_text
#define sqlite3_column_text16 sqlite3_api->column_text16
#define sqlite3_column_type sqlite3_api->column_type
#define sqlite3_column_value sqlite3_api->column_value
#define sqlite3_commit_hook sqlite3_api->commit_hook
#define sqlite3_complete sqlite3_api->complete
#define sqlite3_complete16 sqlite3_api->complete16
#define sqlite3_create_collation sqlite3_api->create_collation
#define sqlite3_create_collation16 sqlite3_api->create_collation16
#define sqlite3_create_function sqlite3_api->create_function
#define sqlite3_create_function16 sqlite3_api->create_function16
#define sqlite3_create_module sqlite3_api->create_module
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
#define sqlite3_data_count sqlite3_api->data_count
#define sqlite3_db_handle sqlite3_api->db_handle
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
#define sqlite3_errcode sqlite3_api->errcode
#define sqlite3_errmsg sqlite3_api->errmsg
#define sqlite3_errmsg16 sqlite3_api->errmsg16
#define sqlite3_exec sqlite3_api->exec
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_expired sqlite3_api->expired
#endif
#define sqlite3_finalize sqlite3_api->finalize
#define sqlite3_free sqlite3_api->free
#define sqlite3_free_table sqlite3_api->free_table
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
#define sqlite3_get_table sqlite3_api->get_table
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_global_recover sqlite3_api->global_recover
#endif
#define sqlite3_interrupt sqlite3_api->interruptx
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
#define sqlite3_libversion sqlite3_api->libversion
#define sqlite3_libversion_number sqlite3_api->libversion_number
#define sqlite3_malloc sqlite3_api->malloc
#define sqlite3_mprintf sqlite3_api->mprintf
#define sqlite3_open sqlite3_api->open
#define sqlite3_open16 sqlite3_api->open16
#define sqlite3_prepare sqlite3_api->prepare
#define sqlite3_prepare16 sqlite3_api->prepare16
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_profile sqlite3_api->profile
#define sqlite3_progress_handler sqlite3_api->progress_handler
#define sqlite3_realloc sqlite3_api->realloc
#define sqlite3_reset sqlite3_api->reset
#define sqlite3_result_blob sqlite3_api->result_blob
#define sqlite3_result_double sqlite3_api->result_double
#define sqlite3_result_error sqlite3_api->result_error
#define sqlite3_result_error16 sqlite3_api->result_error16
#define sqlite3_result_int sqlite3_api->result_int
#define sqlite3_result_int64 sqlite3_api->result_int64
#define sqlite3_result_null sqlite3_api->result_null
#define sqlite3_result_text sqlite3_api->result_text
#define sqlite3_result_text16 sqlite3_api->result_text16
#define sqlite3_result_text16be sqlite3_api->result_text16be
#define sqlite3_result_text16le sqlite3_api->result_text16le
#define sqlite3_result_value sqlite3_api->result_value
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->snprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
#define sqlite3_total_changes sqlite3_api->total_changes
#define sqlite3_trace sqlite3_api->trace
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
#endif
#define sqlite3_update_hook sqlite3_api->update_hook
#define sqlite3_user_data sqlite3_api->user_data
#define sqlite3_value_blob sqlite3_api->value_blob
#define sqlite3_value_bytes sqlite3_api->value_bytes
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
#define sqlite3_value_double sqlite3_api->value_double
#define sqlite3_value_int sqlite3_api->value_int
#define sqlite3_value_int64 sqlite3_api->value_int64
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
#define sqlite3_value_text sqlite3_api->value_text
#define sqlite3_value_text16 sqlite3_api->value_text16
#define sqlite3_value_text16be sqlite3_api->value_text16be
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
#define sqlite3_blob_close sqlite3_api->blob_close
#define sqlite3_blob_open sqlite3_api->blob_open
#define sqlite3_blob_read sqlite3_api->blob_read
#define sqlite3_blob_write sqlite3_api->blob_write
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
#define sqlite3_file_control sqlite3_api->file_control
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
#define sqlite3_memory_used sqlite3_api->memory_used
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
#define sqlite3_mutex_free sqlite3_api->mutex_free
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
#define sqlite3_mutex_try sqlite3_api->mutex_try
#define sqlite3_open_v2 sqlite3_api->open_v2
#define sqlite3_release_memory sqlite3_api->release_memory
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
#define sqlite3_sleep sqlite3_api->sleep
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find sqlite3_api->vfs_find
#define sqlite3_vfs_register sqlite3_api->vfs_register
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
#define sqlite3_result_error_code sqlite3_api->result_error_code
#define sqlite3_test_control sqlite3_api->test_control
#define sqlite3_randomness sqlite3_api->randomness
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
#define sqlite3_limit sqlite3_api->limit
#define sqlite3_next_stmt sqlite3_api->next_stmt
#define sqlite3_sql sqlite3_api->sql
#define sqlite3_status sqlite3_api->status
#define sqlite3_backup_finish sqlite3_api->backup_finish
#define sqlite3_backup_init sqlite3_api->backup_init
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
#define sqlite3_backup_step sqlite3_api->backup_step
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
#define sqlite3_db_config sqlite3_api->db_config
#define sqlite3_db_mutex sqlite3_api->db_mutex
#define sqlite3_db_status sqlite3_api->db_status
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
#define sqlite3_log sqlite3_api->log
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
#define sqlite3_sourceid sqlite3_api->sourceid
#define sqlite3_stmt_status sqlite3_api->stmt_status
#define sqlite3_strnicmp sqlite3_api->strnicmp
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook sqlite3_api->wal_hook
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
#define sqlite3_vtab_config sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define sqlite3_close_v2 sqlite3_api->close_v2
#define sqlite3_db_filename sqlite3_api->db_filename
#define sqlite3_db_readonly sqlite3_api->db_readonly
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
#define sqlite3_errstr sqlite3_api->errstr
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
#define sqlite3_stricmp sqlite3_api->stricmp
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
#endif /* SQLITE_CORE */
#ifndef SQLITE_CORE
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
#endif
#endif /* _SQLITE3EXT_H_ */

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.telegram.messenger"
android:versionCode="91"
android:versionName="1.2.4">
<supports-screens android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:resizeable="true"
android:xlargeScreens="true"/>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" />
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
<uses-feature android:name="android.hardware.telephony" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location.network" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.LOCATION" android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="org.telegram.messenger.permission.MAPS_RECEIVE"/>
<uses-permission android:name="org.telegram.messenger.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_PROFILE"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<permission android:name="org.telegram.messenger.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
<permission android:name="org.telegram.messenger.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/AppName"
android:theme="@style/Theme.Sherlock.Light"
android:name="org.telegram.ui.ApplicationLoader"
android:hardwareAccelerated="true">
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="your-google-maps-api-key-here" />
<activity
android:name="org.telegram.ui.LaunchActivity"
android:windowSoftInputMode="adjustResize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="video/*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile"/>
</intent-filter>
</activity>
<activity
android:name="org.telegram.ui.LoginActivity"
android:windowSoftInputMode="adjustResize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity
android:name="org.telegram.ui.IntroActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity
android:name="org.telegram.ui.ApplicationActivity"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.TMessages"
android:hardwareAccelerated="true"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity
android:name="org.telegram.ui.GalleryImageViewer"
android:theme="@style/Theme.TMessages.Gallery"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity android:name="net.hockeyapp.android.UpdateActivity" />
<receiver android:name="org.telegram.messenger.SmsListener">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<receiver
android:name="org.telegram.messenger.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="org.telegram.messenger" />
</intent-filter>
</receiver>
<service android:name="org.telegram.messenger.AuthenticatorService"
android:exported="true">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator"/>
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/auth"/>
</service>
<service android:name="org.telegram.messenger.ContactsSyncAdapterService"
android:exported="true">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/sync_contacts" />
<meta-data android:name="android.provider.CONTACTS_STRUCTURE"
android:resource="@xml/contacts" />
</service>
<uses-library android:name="com.google.android.maps" android:required="false"/>
</application>
</manifest>

Binary file not shown.

View file

@ -0,0 +1,236 @@
6723;NF;Norfolk Island
5999;CW;Curaçao
1939;PR;Puerto Rico
1876;JM;Jamaica
1869;KN;Saint Kitts and Nevis
1868;TT;Trinidad and Tobago
1849;DO;Dominican Republic
1829;DO;Dominican Republic
1809;DO;Dominican Republic
1787;PR;Puerto Rico
1784;VC;Saint Vincent and the Grenadines
1767;DM;Dominica
1758;LC;Saint Lucia
1721;SX;Bonaire, Sint Eustatius and Saba
1684;AS;American Samoa
1671;GU;Guam
1670;MP;Northern Mariana Islands
1664;MS;Montserrat
1649;TC;Turks and Caicos Islands
1473;GD;Grenada
1441;BM;Bermuda
1345;KY;Cayman Islands
1340;VI;US Virgin Islands
1284;VG;British Virgin Islands
1268;AG;Antigua and Barbuda
1264;AI;Anguilla
1246;BB;Barbados
1242;BS;Bahamas
998;UZ;Uzbekistan
996;KG;Kyrgyzstan
995;GE;Georgia
994;AZ;Azerbaijan
993;TM;Turkmenistan
992;TJ;Tajikistan
977;NP;Nepal
976;MN;Mongolia
975;BT;Bhutan
974;QA;Qatar
973;BH;Bahrain
972;IL;Israel
971;AE;United Arab Emirates
970;PS;Palestine
968;OM;Oman
967;YE;Yemen
966;SA;Saudi Arabia
965;KW;Kuwait
964;IQ;Iraq
963;SY;Syria
962;JO;Jordan
961;LB;Lebanon
960;MV;Maldives
886;TW;Taiwan
880;BD;Bangladesh
856;LA;Laos
855;KH;Cambodia
853;MO;Macau
852;HK;Hong Kong
850;KP;North Korea
692;MH;Marshall Islands
691;FM;Micronesia
690;TK;Tokelau
689;PF;French Polynesia
688;TV;Tuvalu
687;NC;New Caledonia
686;KI;Kiribati
685;WS;Samoa
683;NU;Niue
682;CK;Cook Islands
681;WF;Wallis and Futuna
680;PW;Palau
679;FJ;Fiji
678;VU;Vanuatu
677;SB;Solomon Islands
676;TO;Tonga
675;PG;Papua New Guinea
674;NR;Nauru
673;BN;Brunei Darussalam
672;AU;Australia
670;TL;East Timor
599;BQ;Sint Maarten
598;UY;Uruguay
597;SR;Suriname
596;MQ;Martinique
595;PY;Paraguay
594;GF;French Guiana
593;EC;Ecuador
592;GY;Guyana
591;BO;Bolivia
590;GP;Guadeloupe
509;HT;Haiti
508;PM;Saint Pierre and Miquelon
507;PA;Panama
506;CR;Costa Rica
505;NI;Nicaragua
504;HN;Honduras
503;SV;El Salvador
502;GT;Guatemala
501;BZ;Belize
500;FK;Falkland Islands
423;LI;Liechtenstein
421;SK;Slovakia
420;CZ;Czech Republic
389;MK;Macedonia
387;BA;Bosnia and Herzegovina
386;SI;Slovenia
385;HR;Croatia
382;ME;Montenegro
381;RS;Serbia
380;UA;Ukraine
378;SM;San Marino
377;MC;Monaco
376;AD;Andorra
375;BY;Belarus
374;AM;Armenia
373;MD;Moldova
372;EE;Estonia
371;LV;Latvia
370;LT;Lithuania
359;BG;Bulgaria
358;FI;Finland
357;CY;Cyprus
356;MT;Malta
355;AL;Albania
354;IS;Iceland
353;IE;Ireland
352;LU;Luxembourg
351;PT;Portugal
350;GI;Gibraltar
299;GL;Greenland
298;FO;Faroe Islands
297;AW;Aruba
291;ER;Eritrea
290;SH;Saint Helena
269;KM;Comoros
268;SZ;Swaziland
267;BW;Botswana
266;LS;Lesotho
265;MW;Malawi
264;NA;Namibia
263;ZW;Zimbabwe
262;RE;Réunion
261;MG;Madagascar
260;ZM;Zambia
258;MZ;Mozambique
257;BI;Burundi
256;UG;Uganda
255;TZ;Tanzania
254;KE;Kenya
253;DJ;Djibouti
252;SO;Somalia
251;ET;Ethiopia
250;RW;Rwanda
249;SD;Sudan
248;SC;Seychelles
247;SH;Saint Helena
246;IO;United Kingdom
245;GW;Guinea-Bissau
244;AO;Angola
243;CD;Congo, Democratic Republic
242;CG;Congo
241;GA;Gabon
240;GQ;Equatorial Guinea
239;ST;São Tomé and Príncipe
238;CV;Cape Verde
237;CM;Cameroon
236;CF;Central African Republic
235;TD;Chad
234;NG;Nigeria
233;GH;Ghana
232;SL;Sierra Leone
231;LR;Liberia
230;MU;Mauritius
229;BJ;Benin
228;TG;Togo
227;NE;Niger
226;BF;Burkina Faso
225;CI;Côte d`Ivoire
224;GN;Guinea
223;ML;Mali
222;MR;Mauritania
221;SN;Senegal
220;GM;Gambia
218;LY;Libya
216;TN;Tunisia
213;DZ;Algeria
212;MA;Morocco
211;SS;South Sudan
98;IR;Iran
95;MM;Myanmar
94;LK;Sri Lanka
93;AF;Afghanistan
92;PK;Pakistan
91;IN;India
90;TR;Turkey
86;CN;China
84;VN;Vietnam
82;KR;South Korea
81;JP;Japan
66;TH;Thailand
65;SG;Singapore
64;NZ;New Zealand
63;PH;Philippines
62;ID;Indonesia
61;AU;Australia
60;MY;Malaysia
58;VE;Venezuela
57;CO;Colombia
56;CL;Chile
55;BR;Brazil
54;AR;Argentina
53;CU;Cuba
52;MX;Mexico
51;PE;Peru
49;DE;Germany
48;PL;Poland
47;NO;Norway
46;SE;Sweden
45;DK;Denmark
44;GB;United Kingdom
43;AT;Austria
41;CH;Switzerland
40;RO;Romania
39;IT;Italy
36;HU;Hungary
34;ES;Spain
33;FR;France
32;BE;Belgium
31;NL;Netherlands
30;GR;Greece
27;ZA;South Africa
21;DZ;Algeria
20;EG;Egypt
7;KZ;Kazakhstan
7;RU;Russia
1;US;USA
1;CA;Canada

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 944 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 KiB

Binary file not shown.

View file

@ -0,0 +1,566 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet;
import java.io.EOFException;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.NotYetConnectedException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import jawnae.pyronet.events.PyroClientListener;
import jawnae.pyronet.traffic.ByteStream;
public class PyroClient {
private final PyroSelector selector;
final PyroServer server;
private final SelectionKey key;
private final ByteStream outbound;
// called by PyroSelector.connect()
PyroClient(PyroSelector selector, InetSocketAddress bind,
InetSocketAddress host) throws IOException {
this(selector, null, PyroClient.bindAndConfigure(selector,
SocketChannel.open(), bind));
((SocketChannel) this.key.channel()).connect(host);
}
// called by PyroClient and PyroServer
PyroClient(PyroSelector selector, PyroServer server, SelectionKey key) {
this.selector = selector;
this.selector.checkThread();
this.server = server;
this.key = key;
this.key.attach(this);
this.outbound = new ByteStream();
this.listeners = new CopyOnWriteArrayList<PyroClientListener>();
this.lastEventTime = System.currentTimeMillis();
}
//
private final List<PyroClientListener> listeners;
public void addListener(PyroClientListener listener) {
this.selector.checkThread();
this.listeners.add(listener);
}
public void removeListener(PyroClientListener listener) {
this.selector.checkThread();
this.listeners.remove(listener);
}
public void removeListeners() {
this.selector.checkThread();
this.listeners.clear();
}
/**
* Returns the PyroSelector that created this client
*/
public PyroSelector selector() {
return this.selector;
}
//
private Object attachment;
/**
* Attach any object to a client, for example to store session information
*/
public void attach(Object attachment) {
this.attachment = attachment;
}
/**
* Returns the previously attached object, or <code>null</code> if none is
* set
*/
public <T> T attachment() {
return (T) this.attachment;
}
//
/**
* Returns the local socket address (host+port)
*/
public InetSocketAddress getLocalAddress() {
Socket s = ((SocketChannel) key.channel()).socket();
return (InetSocketAddress) s.getLocalSocketAddress();
}
/**
* Returns the remove socket address (host+port)
*/
public InetSocketAddress getRemoteAddress() {
Socket s = ((SocketChannel) key.channel()).socket();
return (InetSocketAddress) s.getRemoteSocketAddress();
}
//
public void setTimeout(int ms) throws IOException {
this.selector.checkThread();
((SocketChannel) key.channel()).socket().setSoTimeout(ms);
// prevent a call to setTimeout from immediately causing a timeout
this.lastEventTime = System.currentTimeMillis();
this.timeout = ms;
}
public void setLinger(boolean enabled, int seconds) throws IOException {
this.selector.checkThread();
((SocketChannel) key.channel()).socket().setSoLinger(enabled, seconds);
}
public void setKeepAlive(boolean enabled) throws IOException {
this.selector.checkThread();
((SocketChannel) key.channel()).socket().setKeepAlive(enabled);
}
//
/**
* Returns the server that accepted this client.
*
* @throws PyroException
* if this client was not accepted by a server (it connected to
* a server)
*/
public final PyroServer getServer() throws PyroException {
if (this.server == null)
throw new PyroException("this client was not accepted by a server");
return this.server;
}
//
//
private boolean doEagerWrite = false;
/**
* If enabled, causes calls to write() to make an attempt to write the
* bytes, without waiting for the selector to signal writable state.
*/
public void setEagerWrite(boolean enabled) {
this.doEagerWrite = enabled;
}
//
public void writeCopy(ByteBuffer data) throws PyroException {
this.write(this.selector.copy(data));
}
/**
* Will enqueue the bytes to send them<br>
* 1. when the selector is ready to write, if eagerWrite is disabled
* (default)<br>
* 2. immediately, if eagerWrite is enabled<br>
* The ByteBuffer instance is kept, not copied, and thus should not be
* modified
*
* @throws PyroException
* when shutdown() has been called.
*/
public void write(ByteBuffer data) throws PyroException {
this.selector.checkThread();
if (!this.key.isValid()) {
// graceful, as this is meant to be async
return;
}
if (this.doShutdown) {
throw new PyroException("shutting down");
}
this.outbound.append(data);
if (this.doEagerWrite) {
try {
this.onReadyToWrite(System.currentTimeMillis());
} catch (NotYetConnectedException exc) {
this.adjustWriteOp();
} catch (IOException exc) {
this.onConnectionError(exc);
key.cancel();
}
} else {
this.adjustWriteOp();
}
}
/**
* Writes as many as possible bytes to the socket buffer
*/
public int flush() {
int total = 0;
while (this.outbound.hasData()) {
int written;
try {
written = this.onReadyToWrite(System.currentTimeMillis());
} catch (IOException exc) {
written = 0;
}
if (written == 0) {
break;
}
total += written;
}
return total;
}
/**
* Makes an attempt to write all outbound bytes, fails on failure.
*
* @throws PyroException
* on failure
*/
public int flushOrDie() throws PyroException {
int total = 0;
while (this.outbound.hasData()) {
int written;
try {
written = this.onReadyToWrite(System.currentTimeMillis());
} catch (IOException exc) {
written = 0;
}
if (written == 0) {
throw new PyroException("failed to flush, wrote " + total
+ " bytes");
}
total += written;
}
return total;
}
/**
* Returns whether there are bytes left in the outbound queue.
*/
public boolean hasDataEnqueued() {
this.selector.checkThread();
return this.outbound.hasData();
}
private boolean doShutdown = false;
/**
* Gracefully shuts down the connection. The connection is closed after the
* last outbound bytes are sent. Enqueuing new bytes after shutdown, is not
* allowed and will throw an exception
*/
public void shutdown() {
this.selector.checkThread();
this.doShutdown = true;
if (!this.hasDataEnqueued()) {
this.dropConnection();
}
}
/**
* Immediately drop the connection, regardless of any pending outbound
* bytes. Actual behaviour depends on the socket linger settings.
*/
public void dropConnection() {
this.selector.checkThread();
if (this.isDisconnected()) {
return;
}
Runnable drop = new Runnable() {
@Override
@SuppressWarnings("synthetic-access")
public void run() {
try {
if (key.channel().isOpen()) {
((SocketChannel) key.channel()).close();
}
} catch (Exception exc) {
selector().scheduleTask(this);
}
}
};
drop.run();
this.onConnectionError("local");
}
/**
* Returns whether the connection is connected to a remote client.
*/
public boolean isDisconnected() {
this.selector.checkThread();
return !((SocketChannel) this.key.channel()).isOpen();
}
//
void onInterestOp(long now) {
if (!key.isValid()) {
this.onConnectionError("remote");
} else {
try {
if (key.isConnectable())
this.onReadyToConnect(now);
if (key.isReadable())
this.onReadyToRead(now);
if (key.isWritable())
this.onReadyToWrite(now);
} catch (Exception exc) {
this.onConnectionError(exc);
key.cancel();
}
}
}
private long timeout = 0L;
private long lastEventTime;
boolean didTimeout(long now) {
if (this.timeout == 0)
return false; // never timeout
return (now - this.lastEventTime) > this.timeout;
}
private void onReadyToConnect(long now) throws IOException {
this.selector.checkThread();
this.lastEventTime = now;
this.selector.adjustInterestOp(key, SelectionKey.OP_CONNECT, false);
boolean result = ((SocketChannel) key.channel()).finishConnect();
for (PyroClientListener listener: this.listeners)
listener.connectedClient(this);
}
private void onReadyToRead(long now) throws IOException {
this.selector.checkThread();
this.lastEventTime = now;
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = this.selector.networkBuffer;
// read from channel
buffer.clear();
int bytes = channel.read(buffer);
if (bytes == -1)
throw new EOFException();
buffer.flip();
for (PyroClientListener listener: this.listeners)
listener.receivedData(this, buffer);
}
private int onReadyToWrite(long now) throws IOException {
this.selector.checkThread();
this.lastEventTime = now;
int sent = 0;
// copy outbound bytes into network buffer
ByteBuffer buffer = this.selector.networkBuffer;
buffer.clear();
this.outbound.get(buffer);
buffer.flip();
// write to channel
if (buffer.hasRemaining()) {
SocketChannel channel = (SocketChannel) key.channel();
sent = channel.write(buffer);
}
if (sent > 0) {
this.outbound.discard(sent);
}
for (PyroClientListener listener: this.listeners)
listener.sentData(this, sent);
this.adjustWriteOp();
if (this.doShutdown && !this.outbound.hasData()) {
this.dropConnection();
}
return sent;
}
void onConnectionError(final Object cause) {
this.selector.checkThread();
try {
// if the key is invalid, the channel may remain open!!
((SocketChannel) this.key.channel()).close();
} catch (Exception exc) {
// type: java.io.IOException
// message:
// "A non-blocking socket operation could not be completed immediately"
// try again later
this.selector.scheduleTask(new Runnable() {
@Override
public void run() {
PyroClient.this.onConnectionError(cause);
}
});
return;
}
if (this.server != null) {
this.server.onDisconnect(this);
}
if (cause instanceof ConnectException) {
for (PyroClientListener listener: this.listeners)
listener.unconnectableClient(this);
} else if (cause instanceof EOFException) // after read=-1
{
for (PyroClientListener listener: this.listeners)
listener.disconnectedClient(this);
} else if (cause instanceof IOException) {
for (PyroClientListener listener: this.listeners)
listener.droppedClient(this, (IOException) cause);
} else if (!(cause instanceof String)) {
for (PyroClientListener listener: this.listeners)
listener.unconnectableClient(this);
} else if (cause.equals("local")) {
for (PyroClientListener listener: this.listeners)
listener.disconnectedClient(this);
} else if (cause.equals("remote")) {
for (PyroClientListener listener: this.listeners)
listener.droppedClient(this, null);
} else {
throw new IllegalStateException("illegal cause: " + cause);
}
}
public String toString() {
return this.getClass().getSimpleName() + "[" + this.getAddressText()
+ "]";
}
private final String getAddressText() {
if (!this.key.channel().isOpen())
return "closed";
InetSocketAddress sockaddr = this.getRemoteAddress();
if (sockaddr == null)
return "connecting";
InetAddress inetaddr = sockaddr.getAddress();
return inetaddr.getHostAddress() + "@" + sockaddr.getPort();
}
//
void adjustWriteOp() {
this.selector.checkThread();
boolean interested = this.outbound.hasData();
this.selector.adjustInterestOp(this.key, SelectionKey.OP_WRITE,
interested);
}
static final SelectionKey bindAndConfigure(PyroSelector selector,
SocketChannel channel, InetSocketAddress bind) throws IOException {
selector.checkThread();
channel.socket().bind(bind);
return configure(selector, channel, true);
}
static final SelectionKey configure(PyroSelector selector,
SocketChannel channel, boolean connect) throws IOException {
selector.checkThread();
channel.configureBlocking(false);
// channel.socket().setSoLinger(false, 0); // this will b0rk your
// connections
channel.socket().setSoLinger(true, 4);
channel.socket().setReuseAddress(true);
channel.socket().setKeepAlive(false);
channel.socket().setTcpNoDelay(true);
channel.socket().setReceiveBufferSize(PyroSelector.BUFFER_SIZE);
channel.socket().setSendBufferSize(PyroSelector.BUFFER_SIZE);
int ops = SelectionKey.OP_READ;
if (connect)
ops |= SelectionKey.OP_CONNECT;
return selector.register(channel, ops);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet;
@SuppressWarnings("serial")
public class PyroException extends RuntimeException {
public PyroException() {
super();
}
public PyroException(String msg) {
super(msg);
}
public PyroException(String msg, Throwable cause) {
super(msg, cause);
}
}

View file

@ -0,0 +1,325 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import jawnae.pyronet.events.PyroSelectorListener;
public class PyroSelector {
public static boolean DO_NOT_CHECK_NETWORK_THREAD = true;
public static final int BUFFER_SIZE = 64 * 1024;
Thread networkThread;
final Selector nioSelector;
final ByteBuffer networkBuffer;
final PyroSelectorListener listener;
public PyroSelector() {
this(null);
}
public PyroSelector(PyroSelectorListener listener) {
this.listener = listener;
this.networkBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
try {
this.nioSelector = Selector.open();
} catch (IOException exc) {
throw new PyroException("Failed to open a selector?!", exc);
}
this.networkThread = Thread.currentThread();
}
//
public ByteBuffer malloc(int size) {
return ByteBuffer.allocate(size);
}
public ByteBuffer malloc(byte[] array) {
ByteBuffer copy = this.malloc(array.length);
copy.put(array);
copy.flip();
return copy;
}
public ByteBuffer copy(ByteBuffer buffer) {
ByteBuffer copy = this.malloc(buffer.remaining());
copy.put(buffer);
buffer.position(buffer.position() - copy.remaining());
copy.flip();
return copy;
}
//
public final boolean isNetworkThread() {
if (DO_NOT_CHECK_NETWORK_THREAD) {
return true;
}
return networkThread == Thread.currentThread();
}
public final Thread networkThread() {
return this.networkThread;
}
public final void checkThread() {
if (DO_NOT_CHECK_NETWORK_THREAD) {
return;
}
if (!this.isNetworkThread()) {
throw new PyroException(
"call from outside the network-thread, you must schedule tasks");
}
}
public PyroServer listen(InetSocketAddress end, int backlog)
throws IOException {
try {
return new PyroServer(this, nioSelector, end, backlog);
} catch (IOException exc) {
if (this.listener == null)
throw exc;
this.listener.serverBindFailed(exc);
return null;
}
}
public PyroServer listen(InetSocketAddress end) throws IOException {
return this.listen(end, 50);
}
public PyroServer listen(int port) throws IOException {
return this.listen(new InetSocketAddress(InetAddress.getLocalHost(),
port));
}
public PyroClient connect(InetSocketAddress host) throws IOException {
return this.connect(host, null);
}
public PyroClient connect(InetSocketAddress host, InetSocketAddress bind)
throws IOException {
try {
return new PyroClient(this, bind, host);
} catch (IOException exc) {
if (this.listener == null)
throw exc;
this.listener.clientBindFailed(exc);
return null;
}
}
public void select() {
this.select(10);
}
public void select(long eventTimeout) {
this.checkThread();
//
this.executePendingTasks();
this.performNioSelect(eventTimeout);
final long now = System.currentTimeMillis();
this.handleSelectedKeys(now);
this.handleSocketTimeouts(now);
}
private void executePendingTasks() {
while (true) {
Runnable task = this.tasks.poll();
if (task == null)
break;
if (this.listener != null)
this.listener.executingTask(task);
try {
task.run();
} catch (Throwable cause) {
if (this.listener != null)
this.listener.taskCrashed(task, cause);
else
cause.printStackTrace();
}
}
}
private final void performNioSelect(long timeout) {
int selected;
try {
selected = nioSelector.select(timeout);
} catch (IOException exc) {
if (this.listener != null)
this.listener.selectFailure(exc);
else
exc.printStackTrace();
return;
}
if (this.listener != null)
this.listener.selectedKeys(selected);
}
private final void handleSelectedKeys(long now) {
Iterator<SelectionKey> keys = nioSelector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (key.channel() instanceof ServerSocketChannel) {
PyroServer server = (PyroServer) key.attachment();
if (this.listener != null)
this.listener.serverSelected(server);
server.onInterestOp();
}
if (key.channel() instanceof SocketChannel) {
PyroClient client = (PyroClient) key.attachment();
if (this.listener != null)
this.listener.clientSelected(client, key.readyOps());
client.onInterestOp(now);
}
}
}
private final void handleSocketTimeouts(long now) {
for (SelectionKey key: nioSelector.keys()) {
if (key.channel() instanceof SocketChannel) {
PyroClient client = (PyroClient) key.attachment();
if (client.didTimeout(now)) {
try {
throw new SocketTimeoutException(
"PyroNet detected NIO timeout");
} catch (SocketTimeoutException exc) {
client.onConnectionError(exc);
}
}
}
}
}
public void spawnNetworkThread(final String name) {
// now no thread can access this selector
//
// N.B.
// -- updating this non-volatile field is thread-safe
// -- because the current thread can see it (causing it
// -- to become UNACCESSIBLE), and all other threads
// -- that might not see the change will
// -- (continue to) block access to this selector
this.networkThread = null;
new Thread(new Runnable() {
@Override
public void run() {
// spawned thread can access this selector
//
// N.B.
// -- updating this non-volatile field is thread-safe
// -- because the current thread can see it (causing it
// -- to become ACCESSIBLE), and all other threads
// -- that might not see the change will
// -- (continue to) block access to this selector
PyroSelector.this.networkThread = Thread.currentThread();
// start select-loop
try {
while (true) {
PyroSelector.this.select();
}
} catch (Exception exc) {
// this never be caused by Pyro-code
throw new IllegalStateException(exc);
}
}
}, name).start();
}
//
private BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>();
public void scheduleTask(Runnable task) {
if (task == null) {
throw new NullPointerException();
}
try {
this.tasks.put(task);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
wakeup();
}
public void wakeup() {
this.nioSelector.wakeup();
}
//
final SelectionKey register(SelectableChannel channel, int ops)
throws IOException {
return channel.register(this.nioSelector, ops);
}
final boolean adjustInterestOp(SelectionKey key, int op, boolean state) {
this.checkThread();
try {
int ops = key.interestOps();
boolean changed = state != ((ops & op) == op);
if (changed)
key.interestOps(state ? (ops | op) : (ops & ~op));
return changed;
} catch (CancelledKeyException exc) {
// ignore
return false;
}
}
}

View file

@ -0,0 +1,224 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import jawnae.pyronet.addon.PyroSelectorProvider;
import jawnae.pyronet.events.PyroServerListener;
public class PyroServer implements Iterable<PyroClient> {
private final PyroSelector selector;
public final SelectionKey serverKey;
final List<PyroClient> clients;
PyroServer(PyroSelector selector, Selector nioSelector,
InetSocketAddress endpoint, int backlog) throws IOException {
this.selector = selector;
this.selector.checkThread();
ServerSocketChannel ssc;
ssc = ServerSocketChannel.open();
ssc.socket().bind(endpoint, backlog);
ssc.configureBlocking(false);
this.serverKey = ssc.register(nioSelector, SelectionKey.OP_ACCEPT);
this.serverKey.attach(this);
this.clients = new ArrayList<PyroClient>();
this.listeners = new CopyOnWriteArrayList<PyroServerListener>();
}
//
private final List<PyroServerListener> listeners;
public void addListener(PyroServerListener listener) {
this.selector.checkThread();
this.listeners.add(listener);
}
public void removeListener(PyroServerListener listener) {
this.selector.checkThread();
this.listeners.remove(listener);
}
public void removeListeners() {
this.selector.checkThread();
this.listeners.clear();
}
/**
* Returns the network that created this server
*/
public PyroSelector selector() {
return this.selector;
}
private PyroSelectorProvider selectorProvider;
/**
* By installing a PyroSelectorProvider you alter the PyroSelector used to
* do the I/O of a PyroClient. This can be used for multi-threading your
* network code
*/
public void installSelectorProvider(PyroSelectorProvider selectorProvider) {
this.selector().checkThread();
this.selectorProvider = selectorProvider;
}
void onInterestOp() {
if (!serverKey.isValid())
throw new PyroException("invalid selection key");
try {
if (serverKey.isAcceptable()) {
this.onReadyToAccept();
}
} catch (IOException exc) {
throw new IllegalStateException(exc);
}
}
/**
* Returns an iterator to access all connected clients of this server
*/
@Override
public Iterator<PyroClient> iterator() {
this.selector.checkThread();
List<PyroClient> copy = new ArrayList<PyroClient>();
copy.addAll(this.clients);
return copy.iterator();
}
/**
* Closes the server socket. Any current connections will continue.
*/
public void close() throws IOException {
this.selector.checkThread();
this.serverKey.channel().close();
}
/**
* Closes the server socket. Any current connections will be closed.
*/
public void terminate() throws IOException {
this.close();
for (PyroClient client: this) {
client.dropConnection();
}
}
private void onReadyToAccept() throws IOException {
this.selector.checkThread();
final SocketChannel channel = ((ServerSocketChannel) serverKey
.channel()).accept();
final PyroSelector acceptedClientSelector;
{
if (this.selectorProvider == null)
acceptedClientSelector = this.selector;
else
acceptedClientSelector = this.selectorProvider
.provideFor(channel);
}
if (acceptedClientSelector == this.selector) {
SelectionKey clientKey = PyroClient.configure(
acceptedClientSelector, channel, false);
PyroClient client = new PyroClient(acceptedClientSelector, this,
clientKey);
this.fireAcceptedClient(client);
this.clients.add(client);
} else {
// create client in PyroClient-selector thread
acceptedClientSelector.scheduleTask(new Runnable() {
@Override
public void run() {
SelectionKey clientKey;
try {
clientKey = PyroClient.configure(
acceptedClientSelector, channel, false);
} catch (IOException exc) {
throw new IllegalStateException(exc);
}
final PyroClient client = new PyroClient(
acceptedClientSelector, PyroServer.this, clientKey);
PyroServer.this.fireAcceptedClient(client);
// add client to list in PyroServer-selector thread
PyroServer.this.selector().scheduleTask(new Runnable() {
@Override
public void run() {
PyroServer.this.clients.add(client);
}
});
PyroServer.this.selector().wakeup();
}
});
acceptedClientSelector.wakeup();
}
}
void fireAcceptedClient(PyroClient client) {
for (PyroServerListener listener: this.listeners) {
listener.acceptedClient(client);
}
}
void onDisconnect(final PyroClient client) {
if (this.selector().isNetworkThread()) {
this.clients.remove(client);
} else {
// we are in the PyroClient-selector thread
this.selector().scheduleTask(new Runnable() {
@Override
public void run() {
// call again from the PyroServer-selector thread
PyroServer.this.onDisconnect(client);
}
});
this.selector().wakeup();
}
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.addon;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import jawnae.pyronet.PyroSelector;
public class PyroRoundrobinSelectorProvider implements PyroSelectorProvider {
private final PyroSelector[] selectors;
private int index;
public PyroRoundrobinSelectorProvider(PyroSelector[] selectors) {
this.selectors = Arrays.copyOf(selectors, selectors.length);
}
@Override
public PyroSelector provideFor(SocketChannel channel) {
// this is called from the PyroServer-selector thread
return this.selectors[this.index++ % this.selectors.length];
}
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.addon;
import java.nio.channels.SocketChannel;
import jawnae.pyronet.PyroSelector;
public interface PyroSelectorProvider {
public PyroSelector provideFor(SocketChannel channel);
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.addon;
import java.nio.channels.SocketChannel;
import jawnae.pyronet.PyroSelector;
public class PyroSingletonSelectorProvider implements PyroSelectorProvider {
private final PyroSelector selector;
public PyroSingletonSelectorProvider(PyroSelector selector) {
this.selector = selector;
}
@Override
public PyroSelector provideFor(SocketChannel channel) {
return this.selector;
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import java.io.IOException;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public class PyroClientAdapter implements PyroClientListener {
public void connectedClient(PyroClient client) {
//
}
public void unconnectableClient(PyroClient client) {
System.out.println("unconnectable");
}
public void droppedClient(PyroClient client, IOException cause) {
if (cause != null) {
System.out.println(this.getClass().getSimpleName()
+ ".droppedClient() caught exception: " + cause);
}
}
public void disconnectedClient(PyroClient client) {
//
}
//
public void receivedData(PyroClient client, ByteBuffer data) {
//
}
public void sentData(PyroClient client, int bytes) {
//
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import java.io.IOException;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public interface PyroClientListener {
public void connectedClient(PyroClient client);
public void unconnectableClient(PyroClient client);
public void droppedClient(PyroClient client, IOException cause);
public void disconnectedClient(PyroClient client);
//
public void receivedData(PyroClient client, ByteBuffer data);
public void sentData(PyroClient client, int bytes);
}

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroServer;
public class PyroLazyBastardAdapter implements PyroSelectorListener,
PyroServerListener, PyroClientListener {
// --------------- PyroSelectorListener
public void executingTask(Runnable task) {
//
}
public void taskCrashed(Runnable task, Throwable cause) {
System.out.println(this.getClass().getSimpleName()
+ ".taskCrashed() caught exception:");
cause.printStackTrace();
}
public void selectedKeys(int count) {
//
}
public void selectFailure(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".selectFailure() caught exception:");
cause.printStackTrace();
}
public void serverSelected(PyroServer server) {
//
}
public void clientSelected(PyroClient client, int readyOps) {
//
}
// ------------- PyroServerListener
public void acceptedClient(PyroClient client) {
//
}
// ------------- PyroClientListener
public void connectedClient(PyroClient client) {
//
}
public void unconnectableClient(PyroClient client) {
System.out.println(this.getClass().getSimpleName()
+ ".unconnectableClient()");
}
public void droppedClient(PyroClient client, IOException cause) {
if (cause != null && !(cause instanceof EOFException)) {
System.out.println(this.getClass().getSimpleName()
+ ".droppedClient() caught exception: " + cause);
}
}
public void disconnectedClient(PyroClient client) {
//
}
//
public void receivedData(PyroClient client, ByteBuffer data) {
//
}
public void sentData(PyroClient client, int bytes) {
//
}
@Override
public void serverBindFailed(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".serverBindFailed() caught exception:");
cause.printStackTrace();
}
@Override
public void clientBindFailed(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".serverBindFailed() caught exception:");
cause.printStackTrace();
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import java.io.IOException;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroServer;
public class PyroSelectorAdapter implements PyroSelectorListener {
public void executingTask(Runnable task) {
//
}
public void taskCrashed(Runnable task, Throwable cause) {
System.out.println(this.getClass().getSimpleName()
+ " caught exception: " + cause);
}
//
public void selectedKeys(int count) {
//
}
public void selectFailure(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ " caught exception: " + cause);
}
//
public void serverSelected(PyroServer server) {
//
}
public void clientSelected(PyroClient client, int readyOps) {
//
}
//
@Override
public void serverBindFailed(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".serverBindFailed() caught exception: " + cause);
}
@Override
public void clientBindFailed(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".serverBindFailed() caught exception: " + cause);
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import java.io.IOException;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroServer;
public interface PyroSelectorListener {
public void executingTask(Runnable task);
public void taskCrashed(Runnable task, Throwable cause);
//
public void selectedKeys(int count);
public void selectFailure(IOException cause);
//
public void serverSelected(PyroServer server);
public void clientSelected(PyroClient client, int readyOps);
//
public void serverBindFailed(IOException cause);
public void clientBindFailed(IOException cause);
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import jawnae.pyronet.PyroClient;
public class PyroServerAdapter implements PyroServerListener {
@Override
public void acceptedClient(PyroClient client) {
//
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import jawnae.pyronet.PyroClient;
public interface PyroServerListener {
/**
* Note: invoked from the PyroSelector-thread that created this PyroClient
*/
public void acceptedClient(PyroClient client);
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
public interface ByteSink {
public static int FEED_ACCEPTED = 1;
public static int FEED_ACCEPTED_LAST = 2;
public static int FEED_REJECTED = 3;
/**
* determines what to do with the specified byte: accept, accept as final
* byte, reject
*/
public int feed(byte b);
/**
* Resets the state of this ByteSink, allowing it to be enqueued again
*/
public void reset();
/**
* Called by the client when this ByteSink is complete
*/
public void onReady(ByteBuffer buffer);
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
public abstract class ByteSinkEndsWith implements ByteSink {
private final ByteBuffer result;
private final byte[] endsWith;
private final boolean includeEndsWith;
private int matchCount;
private int filled;
public ByteSinkEndsWith(byte[] endsWith, int capacity,
boolean includeEndsWith) {
if (endsWith == null || endsWith.length == 0)
throw new IllegalStateException();
this.result = ByteBuffer.allocate(capacity);
this.endsWith = endsWith;
this.includeEndsWith = includeEndsWith;
this.reset();
}
@Override
public void reset() {
this.result.clear();
this.matchCount = 0;
this.filled = 0;
}
@Override
public int feed(byte b) {
if (this.endsWith[this.matchCount] == b) {
this.matchCount++;
} else {
this.matchCount = 0;
}
this.result.put(this.filled, b);
this.filled += 1;
if (this.matchCount == this.endsWith.length) {
int len = this.filled
- (this.includeEndsWith ? 0 : this.endsWith.length);
this.result.limit(len);
this.onReady(this.result);
return FEED_ACCEPTED_LAST;
}
return ByteSink.FEED_ACCEPTED;
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
public abstract class ByteSinkLength implements ByteSink {
private final ByteBuffer result;
private int filled;
public ByteSinkLength(int size) {
if (size == 0)
throw new IllegalArgumentException();
this.result = ByteBuffer.allocate(size);
this.reset();
}
@Override
public void reset() {
this.result.clear();
this.filled = 0;
}
@Override
public int feed(byte b) {
this.result.put(this.filled, b);
this.filled += 1;
if (this.filled == this.result.capacity()) {
this.onReady(this.result);
return FEED_ACCEPTED_LAST;
}
return ByteSink.FEED_ACCEPTED;
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public abstract class ByteSinkPacket16 implements ByteSink {
public static void sendTo(PyroClient client, byte[] payload) {
if (payload.length > 0x0000FFFF) {
throw new IllegalStateException("packet bigger than 64K-1 bytes");
}
byte[] wrapped = new byte[2 + payload.length];
wrapped[0] = (byte) (payload.length >> 8);
wrapped[1] = (byte) (payload.length >> 0);
System.arraycopy(payload, 0, wrapped, 2, payload.length);
client.write(client.selector().malloc(wrapped));
}
//
ByteSinkLength current;
public ByteSinkPacket16() {
this.reset();
}
@Override
public void reset() {
this.current = new ByteSinkLength(2) {
@Override
public void onReady(ByteBuffer buffer) {
// header is received
int len = buffer.getShort(0) & 0xFFFF;
current = new ByteSinkLength(len) {
@Override
public void onReady(ByteBuffer buffer) {
// sometime we want do reset in
// ByteSinkPacket16.this.onReady, then add the sink back
// to feeder, in such process, onReady should be execute
// at last.
current = null;
// content is received
ByteSinkPacket16.this.onReady(buffer);
}
};
}
};
}
@Override
public int feed(byte b) {
if (this.current == null) {
throw new IllegalStateException();
}
int result = this.current.feed(b);
if (result == FEED_ACCEPTED) {
return result;
}
// 'current' will be replaced by now
if (this.current == null) {
return result;
}
else {
return FEED_ACCEPTED;
}
// return this.current.feed(b);
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public abstract class ByteSinkPacket24 implements ByteSink {
public static void sendTo(PyroClient client, byte[] payload) {
if (payload.length > 0x00FFFFFF) {
throw new IllegalStateException("packet bigger than 16M-1 bytes");
}
byte[] wrapped = new byte[3 + payload.length];
wrapped[0] = (byte) (payload.length >> 16);
wrapped[1] = (byte) (payload.length >> 8);
wrapped[2] = (byte) (payload.length >> 0);
System.arraycopy(payload, 0, wrapped, 3, payload.length);
client.write(client.selector().malloc(wrapped));
}
//
ByteSinkLength current;
public ByteSinkPacket24() {
this.reset();
}
@Override
public void reset() {
this.current = new ByteSinkLength(3) {
@Override
public void onReady(ByteBuffer buffer) {
// header is received
int len = ((buffer.getShort(0) & 0xFFFF) << 8)
| (buffer.get(3) & 0xFF);
current = new ByteSinkLength(len) {
@Override
public void onReady(ByteBuffer buffer) {
// sometime we want do reset in
// ByteSinkPacket24.this.onReady, then add the sink back
// to feeder, in such process, onReady should be execute
// at last.
current = null;
// content is received
ByteSinkPacket24.this.onReady(buffer);
}
};
}
};
}
@Override
public int feed(byte b) {
if (this.current == null) {
throw new IllegalStateException();
}
int result = this.current.feed(b);
if (result == FEED_ACCEPTED) {
return result;
}
// 'current' will be replaced by now
if (this.current == null) {
return result;
} else {
return FEED_ACCEPTED;
}
// return this.current.feed(b);
}
}

View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public abstract class ByteSinkPacket32 implements ByteSink {
public static void sendTo(PyroClient client, byte[] payload) {
boolean isExtreme = (payload.length > 0xFFFFFFFF - 4);
byte[] wrapped = new byte[4 + (isExtreme ? 0 : payload.length)];
wrapped[0] = (byte) (payload.length >> 24);
wrapped[1] = (byte) (payload.length >> 16);
wrapped[2] = (byte) (payload.length >> 8);
wrapped[3] = (byte) (payload.length >> 0);
if (!isExtreme) {
System.arraycopy(payload, 0, wrapped, 4, payload.length);
}
client.write(client.selector().malloc(wrapped));
if (isExtreme) {
client.write(client.selector().malloc(payload));
}
}
//
ByteSinkLength current;
public ByteSinkPacket32() {
this.reset();
}
@Override
public void reset() {
this.current = new ByteSinkLength(4) {
@Override
public void onReady(ByteBuffer buffer) {
// header is received
int len = buffer.getInt(0);
current = new ByteSinkLength(len) {
@Override
public void onReady(ByteBuffer buffer) {
// sometime we want do reset in
// ByteSinkPacket24.this.onReady, then add the sink back
// to feeder, in such process, onReady should be execute
// at last.
current = null;
// content is received
ByteSinkPacket32.this.onReady(buffer);
}
};
}
};
}
@Override
public int feed(byte b) {
if (this.current == null) {
throw new IllegalStateException();
}
int result = this.current.feed(b);
if (result == FEED_ACCEPTED) {
return result;
}
// 'current' will be replaced by now
if (this.current == null) {
return result;
}
else {
return FEED_ACCEPTED;
}
// return this.current.feed(b);
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import jawnae.pyronet.PyroException;
public class ByteStream {
private final List<ByteBuffer> queue;
public ByteStream() {
// the queue is expected to be relatively small, and iterated often.
// hence removing the first element will be fast, even when using an
// ArrayList
this.queue = new ArrayList<ByteBuffer>();
}
/**
* Appends the ByteBuffer instance to the ByteStream. The bytes are not
* copied, so do not modify the contents of the ByteBuffer.
*/
public void append(ByteBuffer buf) {
if (buf == null)
throw new NullPointerException();
this.queue.add(buf);
}
/**
* Returns whether there are any bytes pending in this stream
*/
public boolean hasData() {
int size = this.queue.size();
for (int i = 0; i < size; i++)
if (this.queue.get(i).hasRemaining())
return true;
return false;
}
public int getByteCount() {
int size = this.queue.size();
int sum = 0;
for (int i = 0; i < size; i++)
sum += this.queue.get(i).remaining();
return sum;
}
/**
* Fills the specified buffer with as much bytes as possible. When N bytes
* are read, the buffer position will be increased by N
*/
public void get(ByteBuffer dst) {
if (dst == null) {
throw new NullPointerException();
}
for (ByteBuffer data: this.queue) {
// data pos/lim must not be modified
data = data.slice();
if (data.remaining() > dst.remaining()) {
data.limit(dst.remaining());
dst.put(data);
break;
}
dst.put(data);
if (!dst.hasRemaining()) {
break;
}
}
}
/**
* Discards the specified amount of bytes from the stream.
*
* @throws PyroException
* if it failed to discard the specified number of bytes
*/
public void discard(int count) {
int original = count;
while (count > 0) {
// peek at the first buffer
ByteBuffer data = this.queue.get(0);
if (count < data.remaining()) {
// discarding less bytes than remaining in buffer
data.position(data.position() + count);
count = 0;
break;
}
// discard the first buffer
this.queue.remove(0);
count -= data.remaining();
}
if (count != 0) {
// apparantly we cannot discard the amount of bytes
// the user demanded, this is a bug in other code
throw new PyroException("discarded " + (original - count) + "/"
+ original + " bytes");
}
}
public byte read() {
ByteBuffer data = this.queue.get(0);
byte result = data.get();
if (!data.hasRemaining()) {
// discard the first buffer
this.queue.remove(0);
}
return result;
}
}

View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroSelector;
import jawnae.pyronet.events.PyroClientAdapter;
public class PyroByteSinkFeeder extends PyroClientAdapter {
private final PyroSelector selector;
private final ByteStream inbound;
private final LinkedList<ByteSink> sinks;
public PyroByteSinkFeeder(PyroClient client) {
this(client.selector());
}
public PyroByteSinkFeeder(PyroSelector selector) {
this(selector, 8 * 1024);
}
public PyroByteSinkFeeder(PyroSelector selector, int bufferSize) {
this.selector = selector;
this.inbound = new ByteStream();
this.sinks = new LinkedList<ByteSink>();
}
//
@Override
public void receivedData(PyroClient client, ByteBuffer data) {
this.feed(data);
}
//
public ByteBuffer shutdown() {
int bytes = this.inbound.getByteCount();
ByteBuffer tmp = this.selector.malloc(bytes);
this.inbound.get(tmp);
this.inbound.discard(bytes);
tmp.flip();
return tmp;
}
public void addByteSink(ByteSink sink) {
this.selector.checkThread();
this.register(sink);
}
public void feed(ByteBuffer data) {
ByteBuffer copy = this.selector.copy(data);
this.inbound.append(copy);
this.fill();
}
final void register(ByteSink sink) {
this.sinks.addLast(sink);
this.fill();
}
private final void fill() {
if (this.sinks.isEmpty()) {
return;
}
ByteSink currentSink = this.sinks.removeFirst();
while (currentSink != null && inbound.hasData()) {
switch (currentSink.feed(inbound.read())) {
case ByteSink.FEED_ACCEPTED:
continue; // continue to next feed
case ByteSink.FEED_ACCEPTED_LAST:
break; // break out switch, not while
case ByteSink.FEED_REJECTED:
break; // break out switch, not while
}
if (this.sinks.isEmpty()) {
currentSink = null;
break;
}
currentSink = this.sinks.removeFirst();
}
if (currentSink != null) {
this.sinks.addFirst(currentSink);
}
}
}

View file

@ -0,0 +1,123 @@
// Copyright (c) 2012, Rick Maddy
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package org.telegram.PhoneFormat;
import java.util.ArrayList;
public class CallingCodeInfo {
public ArrayList<String> countries;
public String callingCode;
public ArrayList<String> trunkPrefixes;
public ArrayList<String> intlPrefixes;
public ArrayList<RuleSet> ruleSets;
//public ArrayList formatStrings;
String matchingAccessCode(String str) {
for (String code : intlPrefixes) {
if (str.startsWith(code)) {
return code;
}
}
return null;
}
String matchingTrunkCode(String str) {
for (String code : trunkPrefixes) {
if (str.startsWith(code)) {
return code;
}
}
return null;
}
String format(String orig) {
String str = orig;
String trunkPrefix = null;
String intlPrefix = null;
if (str.startsWith(callingCode)) {
intlPrefix = callingCode;
str = str.substring(intlPrefix.length());
} else {
String trunk = matchingTrunkCode(str);
if (trunk != null) {
trunkPrefix = trunk;
str = str.substring(trunkPrefix.length());
}
}
for (RuleSet set : ruleSets) {
String phone = set.format(str, intlPrefix, trunkPrefix, true);
if (phone != null) {
return phone;
}
}
for (RuleSet set : ruleSets) {
String phone = set.format(str, intlPrefix, trunkPrefix, false);
if (phone != null) {
return phone;
}
}
if (intlPrefix != null && str.length() != 0) {
return String.format("%s %s", intlPrefix, str);
}
return orig;
}
boolean isValidPhoneNumber(String orig) {
String str = orig;
String trunkPrefix = null;
String intlPrefix = null;
if (str.startsWith(callingCode)) {
intlPrefix = callingCode;
str = str.substring(intlPrefix.length());
} else {
String trunk = matchingTrunkCode(str);
if (trunk != null) {
trunkPrefix = trunk;
str = str.substring(trunkPrefix.length());
}
}
for (RuleSet set : ruleSets) {
boolean valid = set.isValid(str, intlPrefix, trunkPrefix, true);
if (valid) {
return valid;
}
}
for (RuleSet set : ruleSets) {
boolean valid = set.isValid(str, intlPrefix, trunkPrefix, false);
if (valid) {
return valid;
}
}
return false;
}
}

View file

@ -0,0 +1,365 @@
// Copyright (c) 2012, Rick Maddy
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package org.telegram.PhoneFormat;
import org.telegram.messenger.Utilities;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
public class PhoneFormat {
public byte[] data;
public ByteBuffer buffer;
public String defaultCountry;
public String defaultCallingCode;
public HashMap<String, Integer> callingCodeOffsets;
public HashMap<String, ArrayList<String>> callingCodeCountries;
public HashMap<String, CallingCodeInfo> callingCodeData;
public HashMap<String, String> countryCallingCode;
public static PhoneFormat Instance = new PhoneFormat();
public static String strip(String str) {
StringBuilder res = new StringBuilder(str);
String phoneChars = "0123456789+*#";
for (int i = res.length() - 1; i >= 0; i--) {
if (!phoneChars.contains(res.substring(i, i + 1))) {
res.deleteCharAt(i);
}
}
return res.toString();
}
public static String stripExceptNumbers(String str) {
StringBuilder res = new StringBuilder(str);
String phoneChars = "0123456789";
for (int i = res.length() - 1; i >= 0; i--) {
if (!phoneChars.contains(res.substring(i, i + 1))) {
res.deleteCharAt(i);
}
}
return res.toString();
}
public PhoneFormat() {
init(null);
}
public PhoneFormat(String countryCode) {
init(countryCode);
}
public void init(String countryCode) {
try {
InputStream stream = Utilities.applicationContext.getAssets().open("PhoneFormats.dat");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = stream.read(buf, 0, 1024)) != -1) {
bos.write(buf, 0, len);
}
data = bos.toByteArray();
buffer = ByteBuffer.wrap(data);
buffer.order(ByteOrder.LITTLE_ENDIAN);
} catch (Exception e) {
e.printStackTrace();
}
if (countryCode != null && countryCode.length() != 0) {
defaultCountry = countryCode;
} else {
Locale loc = Locale.getDefault();
defaultCountry = loc.getCountry().toLowerCase();
}
callingCodeOffsets = new HashMap<String, Integer>(255);
callingCodeCountries = new HashMap<String, ArrayList<String>>(255);
callingCodeData = new HashMap<String, CallingCodeInfo>(10);
countryCallingCode = new HashMap<String, String>(255);
parseDataHeader();
}
public String defaultCallingCode() {
return callingCodeForCountryCode(defaultCountry);
}
public String callingCodeForCountryCode(String countryCode) {
return countryCallingCode.get(countryCode.toLowerCase());
}
public ArrayList countriesForCallingCode(String callingCode) {
if (callingCode.startsWith("+")) {
callingCode = callingCode.substring(1);
}
return callingCodeCountries.get(callingCode);
}
public CallingCodeInfo findCallingCodeInfo(String str) {
CallingCodeInfo res = null;
for (int i = 0; i < 3; i++) {
if (i < str.length()) {
res = callingCodeInfo(str.substring(0, i + 1));
if (res != null) {
break;
}
} else {
break;
}
}
return res;
}
public String format(String orig) {
String str = strip(orig);
if (str.startsWith("+")) {
String rest = str.substring(1);
CallingCodeInfo info = findCallingCodeInfo(rest);
if (info != null) {
String phone = info.format(rest);
return "+" + phone;
} else {
return orig;
}
} else {
CallingCodeInfo info = callingCodeInfo(defaultCallingCode);
if (info == null) {
return orig;
}
String accessCode = info.matchingAccessCode(str);
if (accessCode != null) {
String rest = str.substring(accessCode.length());
String phone = rest;
CallingCodeInfo info2 = findCallingCodeInfo(rest);
if (info2 != null) {
phone = info2.format(rest);
}
if (phone.length() == 0) {
return accessCode;
} else {
return String.format("%s %s", accessCode, phone);
}
} else {
return info.format(str);
}
}
}
public boolean isPhoneNumberValid(String phoneNumber) {
String str = strip(phoneNumber);
if (str.startsWith("+")) {
String rest = str.substring(1);
CallingCodeInfo info = findCallingCodeInfo(rest);
return info != null && info.isValidPhoneNumber(rest);
} else {
CallingCodeInfo info = callingCodeInfo(defaultCallingCode);
if (info == null) {
return false;
}
String accessCode = info.matchingAccessCode(str);
if (accessCode != null) {
String rest = str.substring(accessCode.length());
if (rest.length() != 0) {
CallingCodeInfo info2 = findCallingCodeInfo(rest);
return info2 != null && info2.isValidPhoneNumber(rest);
} else {
return false;
}
} else {
return info.isValidPhoneNumber(str);
}
}
}
int value32(int offset) {
if (offset + 4 <= data.length) {
buffer.position(offset);
return buffer.getInt();
} else {
return 0;
}
}
short value16(int offset) {
if (offset + 2 <= data.length) {
buffer.position(offset);
return buffer.getShort();
} else {
return 0;
}
}
public String valueString(int offset) {
try {
for (int a = offset; a < data.length; a++) {
if (data[a] == '\0') {
if (offset == a - offset) {
return "";
}
return new String(data, offset, a - offset);
}
}
return "";
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public CallingCodeInfo callingCodeInfo(String callingCode) {
CallingCodeInfo res = callingCodeData.get(callingCode);
if (res == null) {
Integer num = callingCodeOffsets.get(callingCode);
if (num != null) {
final byte[] bytes = data;
int start = num;
int offset = start;
res = new CallingCodeInfo();
res.callingCode = callingCode;
res.countries = callingCodeCountries.get(callingCode);
callingCodeData.put(callingCode, res);
int block1Len = value16(offset);
offset += 2;
offset += 2;
int block2Len = value16(offset);
offset += 2;
offset += 2;
int setCnt = value16(offset);
offset += 2;
offset += 2;
ArrayList<String> strs = new ArrayList<String>(5);
String str;
while ((str = valueString(offset)).length() != 0) {
strs.add(str);
offset += str.length() + 1;
}
res.trunkPrefixes = strs;
offset++;
strs = new ArrayList<String>(5);
while ((str = valueString(offset)).length() != 0) {
strs.add(str);
offset += str.length() + 1;
}
res.intlPrefixes = strs;
ArrayList<RuleSet> ruleSets = new ArrayList<RuleSet>(setCnt);
offset = start + block1Len;
for (int s = 0; s < setCnt; s++) {
RuleSet ruleSet = new RuleSet();
ruleSet.matchLen = value16(offset);
offset += 2;
int ruleCnt = value16(offset);
offset += 2;
ArrayList<PhoneRule> rules = new ArrayList<PhoneRule>(ruleCnt);
for (int r = 0; r < ruleCnt; r++) {
PhoneRule rule = new PhoneRule();
rule.minVal = value32(offset);
offset += 4;
rule.maxVal = value32(offset);
offset += 4;
rule.byte8 = (int)bytes[offset++];
rule.maxLen = (int)bytes[offset++];
rule.otherFlag = (int)bytes[offset++];
rule.prefixLen = (int)bytes[offset++];
rule.flag12 = (int)bytes[offset++];
rule.flag13 = (int)bytes[offset++];
int strOffset = value16(offset);
offset += 2;
rule.format = valueString(start + block1Len + block2Len + strOffset);
int openPos = rule.format.indexOf("[[");
if (openPos != -1) {
int closePos = rule.format.indexOf("]]");
rule.format = String.format("%s%s", rule.format.substring(0, openPos), rule.format.substring(closePos + 2));
}
rules.add(rule);
if (rule.hasIntlPrefix) {
ruleSet.hasRuleWithIntlPrefix = true;
}
if (rule.hasTrunkPrefix) {
ruleSet.hasRuleWithTrunkPrefix = true;
}
}
ruleSet.rules = rules;
ruleSets.add(ruleSet);
}
res.ruleSets = ruleSets;
}
}
return res;
}
public void parseDataHeader() {
int count = value32(0);
int base = count * 12 + 4;
int spot = 4;
for (int i = 0; i < count; i++) {
String callingCode = valueString(spot);
spot += 4;
String country = valueString(spot);
spot += 4;
int offset = value32(spot) + base;
spot += 4;
if (country.equals(defaultCountry)) {
defaultCallingCode = callingCode;
}
countryCallingCode.put(country, callingCode);
callingCodeOffsets.put(callingCode, offset);
ArrayList<String> countries = callingCodeCountries.get(callingCode);
if (countries == null) {
countries = new ArrayList<String>();
callingCodeCountries.put(callingCode, countries);
}
countries.add(country);
}
if (defaultCallingCode != null) {
callingCodeInfo(defaultCallingCode);
}
}
}

View file

@ -0,0 +1,101 @@
// Copyright (c) 2012, Rick Maddy
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package org.telegram.PhoneFormat;
public class PhoneRule {
public int minVal;
public int maxVal;
public int byte8;
public int maxLen;
public int otherFlag;
public int prefixLen;
public int flag12;
public int flag13;
public String format;
public boolean hasIntlPrefix;
public boolean hasTrunkPrefix;
String format(String str, String intlPrefix, String trunkPrefix) {
boolean hadC = false;
boolean hadN = false;
boolean hasOpen = false;
int spot = 0;
StringBuilder res = new StringBuilder(20);
for (int i = 0; i < format.length(); i++) {
char ch = format.charAt(i);
switch (ch) {
case 'c':
hadC = true;
if (intlPrefix != null) {
res.append(intlPrefix);
}
break;
case 'n':
hadN = true;
if (trunkPrefix != null) {
res.append(trunkPrefix);
}
break;
case '#':
if (spot < str.length()) {
res.append(str.substring(spot, spot + 1));
spot++;
} else if (hasOpen) {
res.append(" ");
}
break;
case '(':
if (spot < str.length()) {
hasOpen = true;
}
default:
if (!(ch == ' ' && i > 0 && ((format.charAt(i - 1) == 'n' && trunkPrefix == null) || (format.charAt(i - 1) == 'c' && intlPrefix == null)))) {
if (spot < str.length() || (hasOpen && ch == ')')) {
res.append(format.substring(i, i + 1));
if (ch == ')') {
hasOpen = false;
}
}
}
break;
}
}
if (intlPrefix != null && !hadC) {
res.insert(0, String.format("%s ", intlPrefix));
} else if (trunkPrefix != null && !hadN) {
res.insert(0, trunkPrefix);
}
return res.toString();
}
boolean hasIntlPrefix() {
return (flag12 & 0x02) != 0;
}
boolean hasTrunkPrefix() {
return (flag12 & 0x01) != 0;
}
}

View file

@ -0,0 +1,138 @@
// Copyright (c) 2012, Rick Maddy
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package org.telegram.PhoneFormat;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RuleSet {
public int matchLen;
public ArrayList<PhoneRule> rules;
public boolean hasRuleWithIntlPrefix;
public boolean hasRuleWithTrunkPrefix;
public static Pattern pattern = Pattern.compile("[0-9]+");
String format(String str, String intlPrefix, String trunkPrefix, boolean prefixRequired) {
if (str.length() >= matchLen) {
String begin = str.substring(0, matchLen);
int val = 0;
Matcher matcher = pattern.matcher(begin);
if (matcher.find()) {
String num = matcher.group(0);
val = Integer.parseInt(num);
}
for (PhoneRule rule : rules) {
if (val >= rule.minVal && val <= rule.maxVal && str.length() <= rule.maxLen) {
if (prefixRequired) {
if (((rule.flag12 & 0x03) == 0 && trunkPrefix == null && intlPrefix == null) || (trunkPrefix != null && (rule.flag12 & 0x01) != 0) || (intlPrefix != null && (rule.flag12 & 0x02) != 0)) {
return rule.format(str, intlPrefix, trunkPrefix);
}
} else {
if ((trunkPrefix == null && intlPrefix == null) || (trunkPrefix != null && (rule.flag12 & 0x01) != 0) || (intlPrefix != null && (rule.flag12 & 0x02) != 0)) {
return rule.format(str, intlPrefix, trunkPrefix);
}
}
}
}
if (!prefixRequired) {
if (intlPrefix != null) {
for (PhoneRule rule : rules) {
if (val >= rule.minVal && val <= rule.maxVal && str.length() <= rule.maxLen) {
if (trunkPrefix == null || (rule.flag12 & 0x01) != 0) {
return rule.format(str, intlPrefix, trunkPrefix);
}
}
}
} else if (trunkPrefix != null) {
for (PhoneRule rule : rules) {
if (val >= rule.minVal && val <= rule.maxVal && str.length() <= rule.maxLen) {
if (intlPrefix == null || (rule.flag12 & 0x02) != 0) {
return rule.format(str, intlPrefix, trunkPrefix);
}
}
}
}
}
return null;
} else {
return null;
}
}
boolean isValid(String str, String intlPrefix, String trunkPrefix, boolean prefixRequired) {
if (str.length() >= matchLen) {
String begin = str.substring(0, matchLen);
int val = 0;
Matcher matcher = pattern.matcher(begin);
if (matcher.find()) {
String num = matcher.group(0);
val = Integer.parseInt(num);
}
for (PhoneRule rule : rules) {
if (val >= rule.minVal && val <= rule.maxVal && str.length() == rule.maxLen) {
if (prefixRequired) {
if (((rule.flag12 & 0x03) == 0 && trunkPrefix == null && intlPrefix == null) || (trunkPrefix != null && (rule.flag12 & 0x01) != 0) || (intlPrefix != null && (rule.flag12 & 0x02) != 0)) {
return true;
}
} else {
if ((trunkPrefix == null && intlPrefix == null) || (trunkPrefix != null && (rule.flag12 & 0x01) != 0) || (intlPrefix != null && (rule.flag12 & 0x02) != 0)) {
return true;
}
}
}
}
if (!prefixRequired) {
if (intlPrefix != null && !hasRuleWithIntlPrefix) {
for (PhoneRule rule : rules) {
if (val >= rule.minVal && val <= rule.maxVal && str.length() == rule.maxLen) {
if (trunkPrefix == null || (rule.flag12 & 0x01) != 0) {
return true;
}
}
}
} else if (trunkPrefix != null && !hasRuleWithTrunkPrefix) {
for (PhoneRule rule : rules) {
if (val >= rule.minVal && val <= rule.maxVal && str.length() == rule.maxLen) {
if (intlPrefix == null || (rule.flag12 & 0x02) != 0) {
return true;
}
}
}
}
}
return false;
} else {
return false;
}
}
}

View file

@ -0,0 +1,125 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.SQLite;
import android.util.Log;
public class SQLiteCursor {
public static final int FIELD_TYPE_INT = 1;
public static final int FIELD_TYPE_FLOAT = 2;
public static final int FIELD_TYPE_STRING = 3;
public static final int FIELD_TYPE_BYTEARRAY = 4;
public static final int FIELD_TYPE_NULL = 5;
SQLitePreparedStatement preparedStatement;
boolean inRow = false;
public SQLiteCursor(SQLitePreparedStatement stmt) {
preparedStatement = stmt;
}
public boolean isNull(int columnIndex) throws SQLiteException {
checkRow();
return columnIsNull(preparedStatement.getStatementHandle(), columnIndex) == 1;
}
public int intValue(int columnIndex) throws SQLiteException {
checkRow();
return columnIntValue(preparedStatement.getStatementHandle(), columnIndex);
}
public double doubleValue(int columnIndex) throws SQLiteException {
checkRow();
return columnDoubleValue(preparedStatement.getStatementHandle(), columnIndex);
}
public long longValue(int columnIndex) throws SQLiteException {
checkRow();
return columnLongValue(preparedStatement.getStatementHandle(), columnIndex);
}
public String stringValue(int columnIndex) throws SQLiteException {
checkRow();
return columnStringValue(preparedStatement.getStatementHandle(), columnIndex);
}
public byte[] byteArrayValue(int columnIndex) throws SQLiteException {
checkRow();
return columnByteArrayValue(preparedStatement.getStatementHandle(), columnIndex);
}
public int getTypeOf(int columnIndex) throws SQLiteException {
checkRow();
return columnType(preparedStatement.getStatementHandle(), columnIndex);
}
public Object objectValue(int columnIndex) throws SQLiteException {
checkRow();
int type = columnType(preparedStatement.getStatementHandle(), columnIndex);
switch (type) {
case FIELD_TYPE_INT:
return intValue(columnIndex);
case FIELD_TYPE_BYTEARRAY:
return byteArrayValue(columnIndex);
case FIELD_TYPE_FLOAT:
return doubleValue(columnIndex);
case FIELD_TYPE_STRING:
return stringValue(columnIndex);
}
return null;
}
public boolean next() throws SQLiteException {
int res = preparedStatement.step(preparedStatement.getStatementHandle());
if(res == -1) {
int repeatCount = 6;
while (repeatCount-- != 0) {
try {
Log.e("tmessages", "sqlite busy, waiting...");
Thread.sleep(500);
res = preparedStatement.step();
if (res == 0) {
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (res == -1) {
throw new SQLiteException("sqlite busy");
}
}
inRow = (res == 0);
return inRow;
}
public int getStatementHandle() {
return preparedStatement.getStatementHandle();
}
public void dispose() {
preparedStatement.dispose();
}
void checkRow() throws SQLiteException {
if (!inRow) {
throw new SQLiteException("You must call next before");
}
}
native int columnType(int statementHandle, int columnIndex);
native int columnIsNull(int statementHandle, int columnIndex);
native int columnIntValue(int statementHandle, int columnIndex);
native long columnLongValue(int statementHandle, int columnIndex);
native double columnDoubleValue(int statementHandle, int columnIndex);
native String columnStringValue(int statementHandle, int columnIndex);
native byte[] columnByteArrayValue(int statementHandle, int columnIndex);
}

View file

@ -0,0 +1,149 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.SQLite;
import java.util.HashMap;
import java.util.Map;
import android.util.Log;
public class SQLiteDatabase {
private final int sqliteHandle;
private final Map<String, SQLitePreparedStatement> preparedMap;
private boolean isOpen = false;
private boolean inTransaction = false;
public int getSQLiteHandle() {
return sqliteHandle;
}
public SQLiteDatabase(String fileName) throws SQLiteException {
sqliteHandle = opendb(fileName);
isOpen = true;
preparedMap = new HashMap<String, SQLitePreparedStatement>();
}
public boolean tableExists(String tableName) throws SQLiteException {
checkOpened();
String s = "SELECT rowid FROM sqlite_master WHERE type='table' AND name=?;";
return executeInt(s, tableName) != null;
}
public void execute(String sql, Object... args) throws SQLiteException {
checkOpened();
SQLiteCursor cursor = query(sql, args);
try {
cursor.next();
} finally {
cursor.dispose();
}
}
public SQLitePreparedStatement executeFast(String sql) throws SQLiteException{
return new SQLitePreparedStatement(this, sql, true);
}
public Integer executeInt(String sql, Object... args) throws SQLiteException {
checkOpened();
SQLiteCursor cursor = query(sql, args);
try {
if (!cursor.next()) {
return null;
}
return cursor.intValue(0);
} finally {
cursor.dispose();
}
}
public int executeIntOrThrow(String sql, Object... args) throws SQLiteException, SQLiteNoRowException {
checkOpened();
Integer val = executeInt(sql, args);
if (val != null) {
return val;
}
throw new SQLiteNoRowException();
}
public String executeString(String sql, Object... args) throws SQLiteException {
checkOpened();
SQLiteCursor cursor = query(sql, args);
try {
if (!cursor.next()) {
return null;
}
return cursor.stringValue(0);
} finally {
cursor.dispose();
}
}
public SQLiteCursor query(String sql, Object... args) throws SQLiteException {
checkOpened();
SQLitePreparedStatement stmt = preparedMap.get(sql);
if (stmt == null) {
stmt = new SQLitePreparedStatement(this, sql, false);
preparedMap.put(sql, stmt);
}
return stmt.query(args);
}
public SQLiteCursor queryFinalized(String sql, Object... args) throws SQLiteException {
checkOpened();
return new SQLitePreparedStatement(this, sql, true).query(args);
}
public void close() {
if (isOpen) {
try {
for (SQLitePreparedStatement stmt : preparedMap.values()) {
stmt.finalizeQuery();
}
closedb(sqliteHandle);
} catch (SQLiteException e) {
Log.e("tmessages", e.getMessage(), e);
}
isOpen = false;
}
}
void checkOpened() throws SQLiteException {
if (!isOpen) {
throw new SQLiteException("Database closed");
}
}
public void finalize() throws Throwable {
super.finalize();
close();
}
private StackTraceElement[] temp;
public void beginTransaction() throws SQLiteException {
if (inTransaction) {
throw new SQLiteException("database already in transaction");
}
inTransaction = true;
beginTransaction(sqliteHandle);
}
public void commitTransaction() {
inTransaction = false;
commitTransaction(sqliteHandle);
}
native int opendb(String fileName) throws SQLiteException;
native void closedb(int sqliteHandle) throws SQLiteException;
native void beginTransaction(int sqliteHandle);
native void commitTransaction(int sqliteHandle);
}

View file

@ -0,0 +1,27 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.SQLite;
public class SQLiteException extends Exception {
private static final long serialVersionUID = -2398298479089615621L;
public final int errorCode;
public SQLiteException(int errcode, String msg) {
super(msg);
errorCode = errcode;
}
public SQLiteException(String msg) {
this(0, msg);
}
public SQLiteException() {
errorCode = 0;
}
}

View file

@ -0,0 +1,13 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.SQLite;
public class SQLiteNoRowException extends Exception {
private static final long serialVersionUID = 4098095358028103112L;
}

View file

@ -0,0 +1,127 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.SQLite;
import android.util.Log;
public class SQLitePreparedStatement {
private boolean isFinalized = false;
private int sqliteStatementHandle;
private int queryArgsCount;
private boolean finalizeAfterQuery = false;
public int getStatementHandle() {
return sqliteStatementHandle;
}
public SQLitePreparedStatement(SQLiteDatabase db, String sql, boolean finalize) throws SQLiteException {
finalizeAfterQuery = finalize;
sqliteStatementHandle = prepare(db.getSQLiteHandle(), sql);
}
public SQLiteCursor query(Object[] args) throws SQLiteException {
if (args == null || args.length != queryArgsCount) {
throw new IllegalArgumentException();
}
checkFinalized();
reset(sqliteStatementHandle);
int i = 1;
for (Object obj : args) {
if (obj == null) {
bindNull(sqliteStatementHandle, i);
} else if (obj instanceof Integer) {
bindInt(sqliteStatementHandle, i, (Integer)obj);
} else if (obj instanceof Double) {
bindDouble(sqliteStatementHandle, i, (Double)obj);
} else if (obj instanceof String) {
bindString(sqliteStatementHandle, i, (String)obj);
} else if (obj instanceof byte[]) {
bindByteArray(sqliteStatementHandle, i, (byte[])obj);
} else {
throw new IllegalArgumentException();
}
i++;
}
return new SQLiteCursor(this);
}
public int step() throws SQLiteException {
return step(sqliteStatementHandle);
}
public SQLitePreparedStatement stepThis() throws SQLiteException {
step(sqliteStatementHandle);
return this;
}
public void requery() throws SQLiteException {
checkFinalized();
reset(sqliteStatementHandle);
}
public void dispose() {
if (finalizeAfterQuery) {
finalizeQuery();
}
}
void checkFinalized() throws SQLiteException {
if (isFinalized) {
throw new SQLiteException("Prepared query finalized");
}
}
public void finalizeQuery() {
if (isFinalized) {
return;
}
try {
isFinalized = true;
finalize(sqliteStatementHandle);
} catch (SQLiteException e) {
Log.e("tmessages", e.getMessage(), e);
}
}
public void bindInteger(int index, int value) throws SQLiteException {
bindInt(sqliteStatementHandle, index, value);
}
public void bindDouble(int index, double value) throws SQLiteException {
bindDouble(sqliteStatementHandle, index, value);
}
public void bindByteArray(int index, byte[] value) throws SQLiteException {
bindByteArray(sqliteStatementHandle, index, value);
}
public void bindString(int index, String value) throws SQLiteException {
bindString(sqliteStatementHandle, index, value);
}
public void bindLong(int index, long value) throws SQLiteException {
bindLong(sqliteStatementHandle, index, value);
}
native void bindByteArray(int statementHandle, int index, byte[] value) throws SQLiteException;
native void bindString(int statementHandle, int index, String value) throws SQLiteException;
native void bindInt(int statementHandle, int index, int value) throws SQLiteException;
native void bindLong(int statementHandle, int index, long value) throws SQLiteException;
native void bindDouble(int statementHandle, int index, double value) throws SQLiteException;
native void bindNull(int statementHandle, int index) throws SQLiteException;
native void reset(int statementHandle) throws SQLiteException;
native int prepare(int sqliteHandle, String sql) throws SQLiteException;
native void finalize(int statementHandle) throws SQLiteException;
native int step(int statementHandle) throws SQLiteException;
}

View file

@ -0,0 +1,436 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.TL;
import android.util.Log;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.SerializedData;
import java.util.HashMap;
public class TLClassStore {
private HashMap<Integer, Class> classStore;
public TLClassStore () {
classStore = new HashMap<Integer, Class>();
classStore.put(TLRPC.TL_chatPhotoEmpty.constructor, TLRPC.TL_chatPhotoEmpty.class);
classStore.put(TLRPC.TL_chatPhoto.constructor, TLRPC.TL_chatPhoto.class);
classStore.put(TLRPC.TL_futuresalts.constructor, TLRPC.TL_futuresalts.class);
classStore.put(TLRPC.TL_bad_msg_notification.constructor, TLRPC.TL_bad_msg_notification.class);
classStore.put(TLRPC.TL_bad_server_salt.constructor, TLRPC.TL_bad_server_salt.class);
classStore.put(TLRPC.TL_error.constructor, TLRPC.TL_error.class);
classStore.put(TLRPC.TL_messages_sentEncryptedMessage.constructor, TLRPC.TL_messages_sentEncryptedMessage.class);
classStore.put(TLRPC.TL_messages_sentEncryptedFile.constructor, TLRPC.TL_messages_sentEncryptedFile.class);
classStore.put(TLRPC.TL_auth_checkedPhone.constructor, TLRPC.TL_auth_checkedPhone.class);
classStore.put(TLRPC.TL_msgs_ack.constructor, TLRPC.TL_msgs_ack.class);
classStore.put(TLRPC.TL_messages_chatFull.constructor, TLRPC.TL_messages_chatFull.class);
classStore.put(TLRPC.TL_rpc_result.constructor, TLRPC.TL_rpc_result.class);
classStore.put(TLRPC.TL_contactStatus.constructor, TLRPC.TL_contactStatus.class);
classStore.put(TLRPC.TL_auth_authorization.constructor, TLRPC.TL_auth_authorization.class);
classStore.put(TLRPC.TL_messages_messages.constructor, TLRPC.TL_messages_messages.class);
classStore.put(TLRPC.TL_messages_messagesSlice.constructor, TLRPC.TL_messages_messagesSlice.class);
classStore.put(TLRPC.TL_rpc_answer_unknown.constructor, TLRPC.TL_rpc_answer_unknown.class);
classStore.put(TLRPC.TL_rpc_answer_dropped.constructor, TLRPC.TL_rpc_answer_dropped.class);
classStore.put(TLRPC.TL_rpc_answer_dropped_running.constructor, TLRPC.TL_rpc_answer_dropped_running.class);
classStore.put(TLRPC.TL_contacts_link.constructor, TLRPC.TL_contacts_link.class);
classStore.put(TLRPC.TL_encryptedFile.constructor, TLRPC.TL_encryptedFile.class);
classStore.put(TLRPC.TL_encryptedFileEmpty.constructor, TLRPC.TL_encryptedFileEmpty.class);
classStore.put(TLRPC.TL_peerUser.constructor, TLRPC.TL_peerUser.class);
classStore.put(TLRPC.TL_peerChat.constructor, TLRPC.TL_peerChat.class);
classStore.put(TLRPC.TL_destroy_session_ok.constructor, TLRPC.TL_destroy_session_ok.class);
classStore.put(TLRPC.TL_destroy_session_none.constructor, TLRPC.TL_destroy_session_none.class);
classStore.put(TLRPC.TL_updates_difference.constructor, TLRPC.TL_updates_difference.class);
classStore.put(TLRPC.TL_updates_getDifference.constructor, TLRPC.TL_updates_getDifference.class);
classStore.put(TLRPC.TL_updates_differenceSlice.constructor, TLRPC.TL_updates_differenceSlice.class);
classStore.put(TLRPC.TL_updates_differenceEmpty.constructor, TLRPC.TL_updates_differenceEmpty.class);
classStore.put(TLRPC.TL_geoPointEmpty.constructor, TLRPC.TL_geoPointEmpty.class);
classStore.put(TLRPC.TL_geoPoint.constructor, TLRPC.TL_geoPoint.class);
classStore.put(TLRPC.TL_messageForwarded.constructor, TLRPC.TL_messageForwarded.class);
classStore.put(TLRPC.TL_messageEmpty.constructor, TLRPC.TL_messageEmpty.class);
classStore.put(TLRPC.TL_message.constructor, TLRPC.TL_message.class);
classStore.put(TLRPC.TL_messageService.constructor, TLRPC.TL_messageService.class);
classStore.put(TLRPC.TL_inputPhoneContact.constructor, TLRPC.TL_inputPhoneContact.class);
classStore.put(TLRPC.TL_invokeAfterMsg.constructor, TLRPC.TL_invokeAfterMsg.class);
classStore.put(TLRPC.TL_messageMediaVideo.constructor, TLRPC.TL_messageMediaVideo.class);
classStore.put(TLRPC.TL_messageMediaGeo.constructor, TLRPC.TL_messageMediaGeo.class);
classStore.put(TLRPC.TL_messageMediaPhoto.constructor, TLRPC.TL_messageMediaPhoto.class);
classStore.put(TLRPC.TL_messageMediaEmpty.constructor, TLRPC.TL_messageMediaEmpty.class);
classStore.put(TLRPC.TL_messageMediaContact.constructor, TLRPC.TL_messageMediaContact.class);
classStore.put(TLRPC.TL_auth_sentCode.constructor, TLRPC.TL_auth_sentCode.class);
classStore.put(TLRPC.TL_peerNotifySettingsEmpty.constructor, TLRPC.TL_peerNotifySettingsEmpty.class);
classStore.put(TLRPC.TL_peerNotifySettings.constructor, TLRPC.TL_peerNotifySettings.class);
classStore.put(TLRPC.TL_msg_resend_req.constructor, TLRPC.TL_msg_resend_req.class);
classStore.put(TLRPC.TL_http_wait.constructor, TLRPC.TL_http_wait.class);
classStore.put(TLRPC.TL_contacts_blocked.constructor, TLRPC.TL_contacts_blocked.class);
classStore.put(TLRPC.TL_contacts_blockedSlice.constructor, TLRPC.TL_contacts_blockedSlice.class);
classStore.put(TLRPC.TL_inputGeoPoint.constructor, TLRPC.TL_inputGeoPoint.class);
classStore.put(TLRPC.TL_inputGeoPointEmpty.constructor, TLRPC.TL_inputGeoPointEmpty.class);
classStore.put(TLRPC.TL_help_inviteText.constructor, TLRPC.TL_help_inviteText.class);
classStore.put(TLRPC.TL_messages_dhConfigNotModified.constructor, TLRPC.TL_messages_dhConfigNotModified.class);
classStore.put(TLRPC.TL_messages_dhConfig.constructor, TLRPC.TL_messages_dhConfig.class);
classStore.put(TLRPC.TL_destroy_sessions_res.constructor, TLRPC.TL_destroy_sessions_res.class);
classStore.put(TLRPC.TL_contacts_contacts.constructor, TLRPC.TL_contacts_contacts.class);
classStore.put(TLRPC.TL_contacts_contactsNotModified.constructor, TLRPC.TL_contacts_contactsNotModified.class);
classStore.put(TLRPC.TL_photos_photos.constructor, TLRPC.TL_photos_photos.class);
classStore.put(TLRPC.TL_photos_photosSlice.constructor, TLRPC.TL_photos_photosSlice.class);
classStore.put(TLRPC.TL_chatFull.constructor, TLRPC.TL_chatFull.class);
classStore.put(TLRPC.TL_msgs_all_info.constructor, TLRPC.TL_msgs_all_info.class);
classStore.put(TLRPC.TL_inputPeerNotifySettings.constructor, TLRPC.TL_inputPeerNotifySettings.class);
classStore.put(TLRPC.TL_null.constructor, TLRPC.TL_null.class);
classStore.put(TLRPC.TL_inputUserSelf.constructor, TLRPC.TL_inputUserSelf.class);
classStore.put(TLRPC.TL_inputUserForeign.constructor, TLRPC.TL_inputUserForeign.class);
classStore.put(TLRPC.TL_inputUserEmpty.constructor, TLRPC.TL_inputUserEmpty.class);
classStore.put(TLRPC.TL_inputUserContact.constructor, TLRPC.TL_inputUserContact.class);
classStore.put(TLRPC.TL_p_q_inner_data.constructor, TLRPC.TL_p_q_inner_data.class);
classStore.put(TLRPC.TL_msgs_state_req.constructor, TLRPC.TL_msgs_state_req.class);
classStore.put(TLRPC.TL_boolTrue.constructor, TLRPC.TL_boolTrue.class);
classStore.put(TLRPC.TL_boolFalse.constructor, TLRPC.TL_boolFalse.class);
classStore.put(TLRPC.TL_auth_exportedAuthorization.constructor, TLRPC.TL_auth_exportedAuthorization.class);
classStore.put(TLRPC.TL_messages_statedMessagesLinks.constructor, TLRPC.TL_messages_statedMessagesLinks.class);
classStore.put(TLRPC.TL_messages_statedMessages.constructor, TLRPC.TL_messages_statedMessages.class);
classStore.put(TLRPC.TL_inputNotifyChats.constructor, TLRPC.TL_inputNotifyChats.class);
classStore.put(TLRPC.TL_inputNotifyPeer.constructor, TLRPC.TL_inputNotifyPeer.class);
classStore.put(TLRPC.TL_inputNotifyUsers.constructor, TLRPC.TL_inputNotifyUsers.class);
classStore.put(TLRPC.TL_inputNotifyGeoChatPeer.constructor, TLRPC.TL_inputNotifyGeoChatPeer.class);
classStore.put(TLRPC.TL_inputNotifyAll.constructor, TLRPC.TL_inputNotifyAll.class);
classStore.put(TLRPC.TL_inputEncryptedFileLocation.constructor, TLRPC.TL_inputEncryptedFileLocation.class);
classStore.put(TLRPC.TL_inputFileLocation.constructor, TLRPC.TL_inputFileLocation.class);
classStore.put(TLRPC.TL_inputVideoFileLocation.constructor, TLRPC.TL_inputVideoFileLocation.class);
classStore.put(TLRPC.TL_photos_photo.constructor, TLRPC.TL_photos_photo.class);
classStore.put(TLRPC.TL_userContact.constructor, TLRPC.TL_userContact.class);
classStore.put(TLRPC.TL_userRequest.constructor, TLRPC.TL_userRequest.class);
classStore.put(TLRPC.TL_userForeign.constructor, TLRPC.TL_userForeign.class);
classStore.put(TLRPC.TL_userDeleted.constructor, TLRPC.TL_userDeleted.class);
classStore.put(TLRPC.TL_userSelf.constructor, TLRPC.TL_userSelf.class);
classStore.put(TLRPC.TL_userEmpty.constructor, TLRPC.TL_userEmpty.class);
classStore.put(TLRPC.TL_geoChatMessage.constructor, TLRPC.TL_geoChatMessage.class);
classStore.put(TLRPC.TL_geoChatMessageService.constructor, TLRPC.TL_geoChatMessageService.class);
classStore.put(TLRPC.TL_geoChatMessageEmpty.constructor, TLRPC.TL_geoChatMessageEmpty.class);
classStore.put(TLRPC.TL_pong.constructor, TLRPC.TL_pong.class);
classStore.put(TLRPC.TL_messageActionChatEditPhoto.constructor, TLRPC.TL_messageActionChatEditPhoto.class);
classStore.put(TLRPC.TL_messageActionChatDeleteUser.constructor, TLRPC.TL_messageActionChatDeleteUser.class);
classStore.put(TLRPC.TL_messageActionChatDeletePhoto.constructor, TLRPC.TL_messageActionChatDeletePhoto.class);
classStore.put(TLRPC.TL_messageActionChatAddUser.constructor, TLRPC.TL_messageActionChatAddUser.class);
classStore.put(TLRPC.TL_messageActionChatCreate.constructor, TLRPC.TL_messageActionChatCreate.class);
classStore.put(TLRPC.TL_messageActionEmpty.constructor, TLRPC.TL_messageActionEmpty.class);
classStore.put(TLRPC.TL_messageActionChatEditTitle.constructor, TLRPC.TL_messageActionChatEditTitle.class);
classStore.put(TLRPC.TL_messageActionGeoChatCreate.constructor, TLRPC.TL_messageActionGeoChatCreate.class);
classStore.put(TLRPC.TL_messageActionGeoChatCheckin.constructor, TLRPC.TL_messageActionGeoChatCheckin.class);
classStore.put(TLRPC.TL_contacts_foreignLinkMutual.constructor, TLRPC.TL_contacts_foreignLinkMutual.class);
classStore.put(TLRPC.TL_contacts_foreignLinkUnknown.constructor, TLRPC.TL_contacts_foreignLinkUnknown.class);
classStore.put(TLRPC.TL_contacts_foreignLinkRequested.constructor, TLRPC.TL_contacts_foreignLinkRequested.class);
classStore.put(TLRPC.TL_dh_gen_retry.constructor, TLRPC.TL_dh_gen_retry.class);
classStore.put(TLRPC.TL_dh_gen_fail.constructor, TLRPC.TL_dh_gen_fail.class);
classStore.put(TLRPC.TL_dh_gen_ok.constructor, TLRPC.TL_dh_gen_ok.class);
classStore.put(TLRPC.TL_peerNotifyEventsAll.constructor, TLRPC.TL_peerNotifyEventsAll.class);
classStore.put(TLRPC.TL_chatLocated.constructor, TLRPC.TL_chatLocated.class);
classStore.put(TLRPC.TL_decryptedMessageService.constructor, TLRPC.TL_decryptedMessageService.class);
classStore.put(TLRPC.TL_decryptedMessage.constructor, TLRPC.TL_decryptedMessage.class);
classStore.put(TLRPC.TL_inputPeerNotifyEventsAll.constructor, TLRPC.TL_inputPeerNotifyEventsAll.class);
classStore.put(TLRPC.TL_client_DH_inner_data.constructor, TLRPC.TL_client_DH_inner_data.class);
classStore.put(TLRPC.TL_video.constructor, TLRPC.TL_video.class);
classStore.put(TLRPC.TL_videoEmpty.constructor, TLRPC.TL_videoEmpty.class);
classStore.put(TLRPC.TL_contactBlocked.constructor, TLRPC.TL_contactBlocked.class);
classStore.put(TLRPC.TL_inputAppEvent.constructor, TLRPC.TL_inputAppEvent.class);
classStore.put(TLRPC.TL_messages_affectedHistory.constructor, TLRPC.TL_messages_affectedHistory.class);
classStore.put(TLRPC.TL_inputMediaUploadedPhoto.constructor, TLRPC.TL_inputMediaUploadedPhoto.class);
classStore.put(TLRPC.TL_inputMediaVideo.constructor, TLRPC.TL_inputMediaVideo.class);
classStore.put(TLRPC.TL_inputMediaGeoPoint.constructor, TLRPC.TL_inputMediaGeoPoint.class);
classStore.put(TLRPC.TL_inputMediaContact.constructor, TLRPC.TL_inputMediaContact.class);
classStore.put(TLRPC.TL_inputMediaUploadedThumbVideo.constructor, TLRPC.TL_inputMediaUploadedThumbVideo.class);
classStore.put(TLRPC.TL_inputMediaUploadedVideo.constructor, TLRPC.TL_inputMediaUploadedVideo.class);
classStore.put(TLRPC.TL_inputMediaPhoto.constructor, TLRPC.TL_inputMediaPhoto.class);
classStore.put(TLRPC.TL_inputMediaEmpty.constructor, TLRPC.TL_inputMediaEmpty.class);
classStore.put(TLRPC.TL_geochats_messagesSlice.constructor, TLRPC.TL_geochats_messagesSlice.class);
classStore.put(TLRPC.TL_geochats_messages.constructor, TLRPC.TL_geochats_messages.class);
classStore.put(TLRPC.TL_messages_sentMessage.constructor, TLRPC.TL_messages_sentMessage.class);
classStore.put(TLRPC.TL_messages_sentMessageLink.constructor, TLRPC.TL_messages_sentMessageLink.class);
classStore.put(TLRPC.TL_encryptedMessageService.constructor, TLRPC.TL_encryptedMessageService.class);
classStore.put(TLRPC.TL_encryptedMessage.constructor, TLRPC.TL_encryptedMessage.class);
classStore.put(TLRPC.TL_server_DH_params_fail.constructor, TLRPC.TL_server_DH_params_fail.class);
classStore.put(TLRPC.TL_server_DH_params_ok.constructor, TLRPC.TL_server_DH_params_ok.class);
classStore.put(TLRPC.TL_userStatusEmpty.constructor, TLRPC.TL_userStatusEmpty.class);
classStore.put(TLRPC.TL_userStatusOnline.constructor, TLRPC.TL_userStatusOnline.class);
classStore.put(TLRPC.TL_userStatusOffline.constructor, TLRPC.TL_userStatusOffline.class);
classStore.put(TLRPC.TL_msg_copy.constructor, TLRPC.TL_msg_copy.class);
classStore.put(TLRPC.TL_contacts_importedContacts.constructor, TLRPC.TL_contacts_importedContacts.class);
classStore.put(TLRPC.TL_futureSalt.constructor, TLRPC.TL_futureSalt.class);
classStore.put(TLRPC.TL_updateEncryptedMessagesRead.constructor, TLRPC.TL_updateEncryptedMessagesRead.class);
classStore.put(TLRPC.TL_updateContactLink.constructor, TLRPC.TL_updateContactLink.class);
classStore.put(TLRPC.TL_updateReadMessages.constructor, TLRPC.TL_updateReadMessages.class);
classStore.put(TLRPC.TL_updateRestoreMessages.constructor, TLRPC.TL_updateRestoreMessages.class);
classStore.put(TLRPC.TL_updateUserTyping.constructor, TLRPC.TL_updateUserTyping.class);
classStore.put(TLRPC.TL_updateChatUserTyping.constructor, TLRPC.TL_updateChatUserTyping.class);
classStore.put(TLRPC.TL_updateUserName.constructor, TLRPC.TL_updateUserName.class);
classStore.put(TLRPC.TL_updateNewEncryptedMessage.constructor, TLRPC.TL_updateNewEncryptedMessage.class);
classStore.put(TLRPC.TL_updateNewMessage.constructor, TLRPC.TL_updateNewMessage.class);
classStore.put(TLRPC.TL_updateMessageID.constructor, TLRPC.TL_updateMessageID.class);
classStore.put(TLRPC.TL_updateDeleteMessages.constructor, TLRPC.TL_updateDeleteMessages.class);
classStore.put(TLRPC.TL_updateEncryptedChatTyping.constructor, TLRPC.TL_updateEncryptedChatTyping.class);
classStore.put(TLRPC.TL_updateChatParticipants.constructor, TLRPC.TL_updateChatParticipants.class);
classStore.put(TLRPC.TL_updateEncryption.constructor, TLRPC.TL_updateEncryption.class);
classStore.put(TLRPC.TL_updateActivation.constructor, TLRPC.TL_updateActivation.class);
classStore.put(TLRPC.TL_updateNewAuthorization.constructor, TLRPC.TL_updateNewAuthorization.class);
classStore.put(TLRPC.TL_updateNewGeoChatMessage.constructor, TLRPC.TL_updateNewGeoChatMessage.class);
classStore.put(TLRPC.TL_updateUserPhoto.constructor, TLRPC.TL_updateUserPhoto.class);
classStore.put(TLRPC.TL_updateContactRegistered.constructor, TLRPC.TL_updateContactRegistered.class);
classStore.put(TLRPC.TL_updateUserStatus.constructor, TLRPC.TL_updateUserStatus.class);
classStore.put(TLRPC.TL_rpc_error.constructor, TLRPC.TL_rpc_error.class);
classStore.put(TLRPC.TL_rpc_req_error.constructor, TLRPC.TL_rpc_req_error.class);
classStore.put(TLRPC.TL_inputEncryptedFile.constructor, TLRPC.TL_inputEncryptedFile.class);
classStore.put(TLRPC.TL_inputEncryptedFileEmpty.constructor, TLRPC.TL_inputEncryptedFileEmpty.class);
classStore.put(TLRPC.TL_inputEncryptedFileUploaded.constructor, TLRPC.TL_inputEncryptedFileUploaded.class);
classStore.put(TLRPC.TL_decryptedMessageActionSetMessageTTL.constructor, TLRPC.TL_decryptedMessageActionSetMessageTTL.class);
classStore.put(TLRPC.TL_contacts_myLinkRequested.constructor, TLRPC.TL_contacts_myLinkRequested.class);
classStore.put(TLRPC.TL_contacts_myLinkContact.constructor, TLRPC.TL_contacts_myLinkContact.class);
classStore.put(TLRPC.TL_contacts_myLinkEmpty.constructor, TLRPC.TL_contacts_myLinkEmpty.class);
classStore.put(TLRPC.TL_server_DH_inner_data.constructor, TLRPC.TL_server_DH_inner_data.class);
classStore.put(TLRPC.TL_new_session_created.constructor, TLRPC.TL_new_session_created.class);
classStore.put(TLRPC.TL_userProfilePhotoEmpty.constructor, TLRPC.TL_userProfilePhotoEmpty.class);
classStore.put(TLRPC.TL_userProfilePhoto.constructor, TLRPC.TL_userProfilePhoto.class);
classStore.put(TLRPC.TL_photo.constructor, TLRPC.TL_photo.class);
classStore.put(TLRPC.TL_photoEmpty.constructor, TLRPC.TL_photoEmpty.class);
classStore.put(TLRPC.TL_encryptedChatWaiting.constructor, TLRPC.TL_encryptedChatWaiting.class);
classStore.put(TLRPC.TL_encryptedChatEmpty.constructor, TLRPC.TL_encryptedChatEmpty.class);
classStore.put(TLRPC.TL_encryptedChatDiscarded.constructor, TLRPC.TL_encryptedChatDiscarded.class);
classStore.put(TLRPC.TL_encryptedChat.constructor, TLRPC.TL_encryptedChat.class);
classStore.put(TLRPC.TL_encryptedChatRequested.constructor, TLRPC.TL_encryptedChatRequested.class);
classStore.put(TLRPC.TL_geochats_statedMessage.constructor, TLRPC.TL_geochats_statedMessage.class);
classStore.put(TLRPC.TL_contact.constructor, TLRPC.TL_contact.class);
classStore.put(TLRPC.TL_config.constructor, TLRPC.TL_config.class);
classStore.put(TLRPC.TL_messages_chats.constructor, TLRPC.TL_messages_chats.class);
classStore.put(TLRPC.TL_chatParticipants.constructor, TLRPC.TL_chatParticipants.class);
classStore.put(TLRPC.TL_chatParticipantsForbidden.constructor, TLRPC.TL_chatParticipantsForbidden.class);
classStore.put(TLRPC.TL_decryptedMessageMediaContact.constructor, TLRPC.TL_decryptedMessageMediaContact.class);
classStore.put(TLRPC.TL_decryptedMessageMediaVideo.constructor, TLRPC.TL_decryptedMessageMediaVideo.class);
classStore.put(TLRPC.TL_decryptedMessageMediaGeoPoint.constructor, TLRPC.TL_decryptedMessageMediaGeoPoint.class);
classStore.put(TLRPC.TL_decryptedMessageMediaFile.constructor, TLRPC.TL_decryptedMessageMediaFile.class);
classStore.put(TLRPC.TL_decryptedMessageMediaEmpty.constructor, TLRPC.TL_decryptedMessageMediaEmpty.class);
classStore.put(TLRPC.TL_decryptedMessageMediaPhoto.constructor, TLRPC.TL_decryptedMessageMediaPhoto.class);
classStore.put(TLRPC.TL_chatParticipant.constructor, TLRPC.TL_chatParticipant.class);
classStore.put(TLRPC.TL_chatForbidden.constructor, TLRPC.TL_chatForbidden.class);
classStore.put(TLRPC.TL_geoChat.constructor, TLRPC.TL_geoChat.class);
classStore.put(TLRPC.TL_chatEmpty.constructor, TLRPC.TL_chatEmpty.class);
classStore.put(TLRPC.TL_chat.constructor, TLRPC.TL_chat.class);
classStore.put(TLRPC.TL_storage_fileUnknown.constructor, TLRPC.TL_storage_fileUnknown.class);
classStore.put(TLRPC.TL_storage_fileWebp.constructor, TLRPC.TL_storage_fileWebp.class);
classStore.put(TLRPC.TL_storage_filePng.constructor, TLRPC.TL_storage_filePng.class);
classStore.put(TLRPC.TL_storage_fileGif.constructor, TLRPC.TL_storage_fileGif.class);
classStore.put(TLRPC.TL_storage_fileMov.constructor, TLRPC.TL_storage_fileMov.class);
classStore.put(TLRPC.TL_storage_fileMp3.constructor, TLRPC.TL_storage_fileMp3.class);
classStore.put(TLRPC.TL_storage_fileJpeg.constructor, TLRPC.TL_storage_fileJpeg.class);
classStore.put(TLRPC.TL_storage_filePartial.constructor, TLRPC.TL_storage_filePartial.class);
classStore.put(TLRPC.TL_storage_fileMp4.constructor, TLRPC.TL_storage_fileMp4.class);
classStore.put(TLRPC.TL_inputMessagesFilterVideo.constructor, TLRPC.TL_inputMessagesFilterVideo.class);
classStore.put(TLRPC.TL_inputMessagesFilterEmpty.constructor, TLRPC.TL_inputMessagesFilterEmpty.class);
classStore.put(TLRPC.TL_inputMessagesFilterPhotos.constructor, TLRPC.TL_inputMessagesFilterPhotos.class);
classStore.put(TLRPC.TL_inputMessagesFilterPhotoVideo.constructor, TLRPC.TL_inputMessagesFilterPhotoVideo.class);
classStore.put(TLRPC.TL_geochats_located.constructor, TLRPC.TL_geochats_located.class);
classStore.put(TLRPC.TL_msgs_state_info.constructor, TLRPC.TL_msgs_state_info.class);
classStore.put(TLRPC.TL_upload_file.constructor, TLRPC.TL_upload_file.class);
classStore.put(TLRPC.TL_dialog.constructor, TLRPC.TL_dialog.class);
classStore.put(TLRPC.TL_messages_messageEmpty.constructor, TLRPC.TL_messages_messageEmpty.class);
classStore.put(TLRPC.TL_messages_message.constructor, TLRPC.TL_messages_message.class);
classStore.put(TLRPC.TL_fileLocation.constructor, TLRPC.TL_fileLocation.class);
classStore.put(TLRPC.TL_fileLocationUnavailable.constructor, TLRPC.TL_fileLocationUnavailable.class);
classStore.put(TLRPC.TL_inputGeoChat.constructor, TLRPC.TL_inputGeoChat.class);
classStore.put(TLRPC.TL_protoMessage.constructor, TLRPC.TL_protoMessage.class);
classStore.put(TLRPC.TL_photoSize.constructor, TLRPC.TL_photoSize.class);
classStore.put(TLRPC.TL_photoSizeEmpty.constructor, TLRPC.TL_photoSizeEmpty.class);
classStore.put(TLRPC.TL_photoCachedSize.constructor, TLRPC.TL_photoCachedSize.class);
classStore.put(TLRPC.TL_inputFile.constructor, TLRPC.TL_inputFile.class);
classStore.put(TLRPC.TL_messages_statedMessageLink.constructor, TLRPC.TL_messages_statedMessageLink.class);
classStore.put(TLRPC.TL_messages_statedMessage.constructor, TLRPC.TL_messages_statedMessage.class);
classStore.put(TLRPC.TL_userFull.constructor, TLRPC.TL_userFull.class);
classStore.put(TLRPC.TL_msg_new_detailed_info.constructor, TLRPC.TL_msg_new_detailed_info.class);
classStore.put(TLRPC.TL_msg_detailed_info.constructor, TLRPC.TL_msg_detailed_info.class);
classStore.put(TLRPC.TL_resPQ.constructor, TLRPC.TL_resPQ.class);
classStore.put(TLRPC.TL_updateShortChatMessage.constructor, TLRPC.TL_updateShortChatMessage.class);
classStore.put(TLRPC.TL_updates.constructor, TLRPC.TL_updates.class);
classStore.put(TLRPC.TL_updateShortMessage.constructor, TLRPC.TL_updateShortMessage.class);
classStore.put(TLRPC.TL_updateShort.constructor, TLRPC.TL_updateShort.class);
classStore.put(TLRPC.TL_updatesCombined.constructor, TLRPC.TL_updatesCombined.class);
classStore.put(TLRPC.TL_updatesTooLong.constructor, TLRPC.TL_updatesTooLong.class);
classStore.put(TLRPC.TL_messages_chat.constructor, TLRPC.TL_messages_chat.class);
classStore.put(TLRPC.TL_wallPaper.constructor, TLRPC.TL_wallPaper.class);
classStore.put(TLRPC.TL_wallPaperSolid.constructor, TLRPC.TL_wallPaperSolid.class);
classStore.put(TLRPC.TL_updates_state.constructor, TLRPC.TL_updates_state.class);
classStore.put(TLRPC.TL_inputEncryptedChat.constructor, TLRPC.TL_inputEncryptedChat.class);
classStore.put(TLRPC.TL_inputChatPhoto.constructor, TLRPC.TL_inputChatPhoto.class);
classStore.put(TLRPC.TL_inputChatPhotoEmpty.constructor, TLRPC.TL_inputChatPhotoEmpty.class);
classStore.put(TLRPC.TL_inputChatUploadedPhoto.constructor, TLRPC.TL_inputChatUploadedPhoto.class);
classStore.put(TLRPC.TL_inputVideoEmpty.constructor, TLRPC.TL_inputVideoEmpty.class);
classStore.put(TLRPC.TL_inputVideo.constructor, TLRPC.TL_inputVideo.class);
classStore.put(TLRPC.TL_nearestDc.constructor, TLRPC.TL_nearestDc.class);
classStore.put(TLRPC.TL_inputPhotoEmpty.constructor, TLRPC.TL_inputPhotoEmpty.class);
classStore.put(TLRPC.TL_inputPhoto.constructor, TLRPC.TL_inputPhoto.class);
classStore.put(TLRPC.TL_importedContact.constructor, TLRPC.TL_importedContact.class);
classStore.put(TLRPC.TL_inputPeerContact.constructor, TLRPC.TL_inputPeerContact.class);
classStore.put(TLRPC.TL_inputPeerChat.constructor, TLRPC.TL_inputPeerChat.class);
classStore.put(TLRPC.TL_inputPeerEmpty.constructor, TLRPC.TL_inputPeerEmpty.class);
classStore.put(TLRPC.TL_inputPeerSelf.constructor, TLRPC.TL_inputPeerSelf.class);
classStore.put(TLRPC.TL_inputPeerForeign.constructor, TLRPC.TL_inputPeerForeign.class);
classStore.put(TLRPC.TL_dcOption.constructor, TLRPC.TL_dcOption.class);
classStore.put(TLRPC.TL_inputPhotoCropAuto.constructor, TLRPC.TL_inputPhotoCropAuto.class);
classStore.put(TLRPC.TL_inputPhotoCrop.constructor, TLRPC.TL_inputPhotoCrop.class);
classStore.put(TLRPC.TL_messages_dialogs.constructor, TLRPC.TL_messages_dialogs.class);
classStore.put(TLRPC.TL_messages_dialogsSlice.constructor, TLRPC.TL_messages_dialogsSlice.class);
classStore.put(TLRPC.TL_req_pq.constructor, TLRPC.TL_req_pq.class);
classStore.put(TLRPC.TL_req_DH_params.constructor, TLRPC.TL_req_DH_params.class);
classStore.put(TLRPC.TL_set_client_DH_params.constructor, TLRPC.TL_set_client_DH_params.class);
classStore.put(TLRPC.TL_ping.constructor, TLRPC.TL_ping.class);
classStore.put(TLRPC.TL_destroy_session.constructor, TLRPC.TL_destroy_session.class);
classStore.put(TLRPC.TL_destroy_sessions.constructor, TLRPC.TL_destroy_sessions.class);
classStore.put(TLRPC.TL_get_future_salts.constructor, TLRPC.TL_get_future_salts.class);
classStore.put(TLRPC.TL_rpc_drop_answer.constructor, TLRPC.TL_rpc_drop_answer.class);
classStore.put(TLRPC.TL_auth_checkPhone.constructor, TLRPC.TL_auth_checkPhone.class);
classStore.put(TLRPC.TL_auth_sendCode.constructor, TLRPC.TL_auth_sendCode.class);
classStore.put(TLRPC.TL_auth_sendCall.constructor, TLRPC.TL_auth_sendCall.class);
classStore.put(TLRPC.TL_auth_signUp.constructor, TLRPC.TL_auth_signUp.class);
classStore.put(TLRPC.TL_auth_signIn.constructor, TLRPC.TL_auth_signIn.class);
classStore.put(TLRPC.TL_auth_logOut.constructor, TLRPC.TL_auth_logOut.class);
classStore.put(TLRPC.TL_auth_sendInvites.constructor, TLRPC.TL_auth_sendInvites.class);
classStore.put(TLRPC.TL_auth_exportAuthorization.constructor, TLRPC.TL_auth_exportAuthorization.class);
classStore.put(TLRPC.TL_auth_importAuthorization.constructor, TLRPC.TL_auth_importAuthorization.class);
classStore.put(TLRPC.TL_account_registerDevice.constructor, TLRPC.TL_account_registerDevice.class);
classStore.put(TLRPC.TL_account_unregisterDevice.constructor, TLRPC.TL_account_unregisterDevice.class);
classStore.put(TLRPC.TL_account_updateNotifySettings.constructor, TLRPC.TL_account_updateNotifySettings.class);
classStore.put(TLRPC.TL_account_getNotifySettings.constructor, TLRPC.TL_account_getNotifySettings.class);
classStore.put(TLRPC.TL_account_resetNotifySettings.constructor, TLRPC.TL_account_resetNotifySettings.class);
classStore.put(TLRPC.TL_account_updateProfile.constructor, TLRPC.TL_account_updateProfile.class);
classStore.put(TLRPC.TL_account_updateStatus.constructor, TLRPC.TL_account_updateStatus.class);
classStore.put(TLRPC.TL_account_getWallPapers.constructor, TLRPC.TL_account_getWallPapers.class);
classStore.put(TLRPC.TL_users_getUsers.constructor, TLRPC.TL_users_getUsers.class);
classStore.put(TLRPC.TL_users_getFullUser.constructor, TLRPC.TL_users_getFullUser.class);
classStore.put(TLRPC.TL_contacts_getStatuses.constructor, TLRPC.TL_contacts_getStatuses.class);
classStore.put(TLRPC.TL_contacts_getContacts.constructor, TLRPC.TL_contacts_getContacts.class);
classStore.put(TLRPC.TL_contacts_importContacts.constructor, TLRPC.TL_contacts_importContacts.class);
classStore.put(TLRPC.TL_contacts_deleteContact.constructor, TLRPC.TL_contacts_deleteContact.class);
classStore.put(TLRPC.TL_contacts_deleteContacts.constructor, TLRPC.TL_contacts_deleteContacts.class);
classStore.put(TLRPC.TL_contacts_block.constructor, TLRPC.TL_contacts_block.class);
classStore.put(TLRPC.TL_contacts_unblock.constructor, TLRPC.TL_contacts_unblock.class);
classStore.put(TLRPC.TL_contacts_getBlocked.constructor, TLRPC.TL_contacts_getBlocked.class);
classStore.put(TLRPC.TL_messages_getMessages.constructor, TLRPC.TL_messages_getMessages.class);
classStore.put(TLRPC.TL_messages_getDialogs.constructor, TLRPC.TL_messages_getDialogs.class);
classStore.put(TLRPC.TL_messages_getHistory.constructor, TLRPC.TL_messages_getHistory.class);
classStore.put(TLRPC.TL_messages_search.constructor, TLRPC.TL_messages_search.class);
classStore.put(TLRPC.TL_messages_readHistory.constructor, TLRPC.TL_messages_readHistory.class);
classStore.put(TLRPC.TL_messages_deleteHistory.constructor, TLRPC.TL_messages_deleteHistory.class);
classStore.put(TLRPC.TL_messages_deleteMessages.constructor, TLRPC.TL_messages_deleteMessages.class);
classStore.put(TLRPC.TL_messages_restoreMessages.constructor, TLRPC.TL_messages_restoreMessages.class);
classStore.put(TLRPC.TL_messages_receivedMessages.constructor, TLRPC.TL_messages_receivedMessages.class);
classStore.put(TLRPC.TL_messages_setTyping.constructor, TLRPC.TL_messages_setTyping.class);
classStore.put(TLRPC.TL_messages_sendMessage.constructor, TLRPC.TL_messages_sendMessage.class);
classStore.put(TLRPC.TL_messages_sendMedia.constructor, TLRPC.TL_messages_sendMedia.class);
classStore.put(TLRPC.TL_messages_forwardMessages.constructor, TLRPC.TL_messages_forwardMessages.class);
classStore.put(TLRPC.TL_messages_getChats.constructor, TLRPC.TL_messages_getChats.class);
classStore.put(TLRPC.TL_messages_getFullChat.constructor, TLRPC.TL_messages_getFullChat.class);
classStore.put(TLRPC.TL_messages_editChatTitle.constructor, TLRPC.TL_messages_editChatTitle.class);
classStore.put(TLRPC.TL_messages_editChatPhoto.constructor, TLRPC.TL_messages_editChatPhoto.class);
classStore.put(TLRPC.TL_messages_addChatUser.constructor, TLRPC.TL_messages_addChatUser.class);
classStore.put(TLRPC.TL_messages_deleteChatUser.constructor, TLRPC.TL_messages_deleteChatUser.class);
classStore.put(TLRPC.TL_messages_createChat.constructor, TLRPC.TL_messages_createChat.class);
classStore.put(TLRPC.TL_updates_getState.constructor, TLRPC.TL_updates_getState.class);
classStore.put(TLRPC.TL_photos_updateProfilePhoto.constructor, TLRPC.TL_photos_updateProfilePhoto.class);
classStore.put(TLRPC.TL_photos_uploadProfilePhoto.constructor, TLRPC.TL_photos_uploadProfilePhoto.class);
classStore.put(TLRPC.TL_upload_saveFilePart.constructor, TLRPC.TL_upload_saveFilePart.class);
classStore.put(TLRPC.TL_upload_getFile.constructor, TLRPC.TL_upload_getFile.class);
classStore.put(TLRPC.TL_help_getConfig.constructor, TLRPC.TL_help_getConfig.class);
classStore.put(TLRPC.TL_help_getNearestDc.constructor, TLRPC.TL_help_getNearestDc.class);
classStore.put(TLRPC.TL_help_saveAppLog.constructor, TLRPC.TL_help_saveAppLog.class);
classStore.put(TLRPC.TL_help_getInviteText.constructor, TLRPC.TL_help_getInviteText.class);
classStore.put(TLRPC.TL_photos_getUserPhotos.constructor, TLRPC.TL_photos_getUserPhotos.class);
classStore.put(TLRPC.TL_messages_forwardMessage.constructor, TLRPC.TL_messages_forwardMessage.class);
classStore.put(TLRPC.TL_messages_sendBroadcast.constructor, TLRPC.TL_messages_sendBroadcast.class);
classStore.put(TLRPC.TL_geochats_getLocated.constructor, TLRPC.TL_geochats_getLocated.class);
classStore.put(TLRPC.TL_geochats_getRecents.constructor, TLRPC.TL_geochats_getRecents.class);
classStore.put(TLRPC.TL_geochats_checkin.constructor, TLRPC.TL_geochats_checkin.class);
classStore.put(TLRPC.TL_geochats_getFullChat.constructor, TLRPC.TL_geochats_getFullChat.class);
classStore.put(TLRPC.TL_geochats_editChatTitle.constructor, TLRPC.TL_geochats_editChatTitle.class);
classStore.put(TLRPC.TL_geochats_editChatPhoto.constructor, TLRPC.TL_geochats_editChatPhoto.class);
classStore.put(TLRPC.TL_geochats_search.constructor, TLRPC.TL_geochats_search.class);
classStore.put(TLRPC.TL_geochats_getHistory.constructor, TLRPC.TL_geochats_getHistory.class);
classStore.put(TLRPC.TL_geochats_setTyping.constructor, TLRPC.TL_geochats_setTyping.class);
classStore.put(TLRPC.TL_geochats_sendMessage.constructor, TLRPC.TL_geochats_sendMessage.class);
classStore.put(TLRPC.TL_geochats_sendMedia.constructor, TLRPC.TL_geochats_sendMedia.class);
classStore.put(TLRPC.TL_geochats_createGeoChat.constructor, TLRPC.TL_geochats_createGeoChat.class);
classStore.put(TLRPC.TL_updates_getDifference.constructor, TLRPC.TL_updates_getDifference.class);
classStore.put(TLRPC.TL_messages_getDhConfig.constructor, TLRPC.TL_messages_getDhConfig.class);
classStore.put(TLRPC.TL_messages_requestEncryption.constructor, TLRPC.TL_messages_requestEncryption.class);
classStore.put(TLRPC.TL_messages_acceptEncryption.constructor, TLRPC.TL_messages_acceptEncryption.class);
classStore.put(TLRPC.TL_messages_discardEncryption.constructor, TLRPC.TL_messages_discardEncryption.class);
classStore.put(TLRPC.TL_messages_setEncryptedTyping.constructor, TLRPC.TL_messages_setEncryptedTyping.class);
classStore.put(TLRPC.TL_messages_readEncryptedHistory.constructor, TLRPC.TL_messages_readEncryptedHistory.class);
classStore.put(TLRPC.TL_messages_sendEncrypted.constructor, TLRPC.TL_messages_sendEncrypted.class);
classStore.put(TLRPC.TL_messages_sendEncryptedFile.constructor, TLRPC.TL_messages_sendEncryptedFile.class);
classStore.put(TLRPC.TL_messages_sendEncryptedService.constructor, TLRPC.TL_messages_sendEncryptedService.class);
classStore.put(TLRPC.TL_messages_receivedQueue.constructor, TLRPC.TL_messages_receivedQueue.class);
classStore.put(TLRPC.TL_msg_container.constructor, TLRPC.TL_msg_container.class);
classStore.put(TLRPC.TL_fileEncryptedLocation.constructor, TLRPC.TL_fileEncryptedLocation.class);
classStore.put(TLRPC.TL_messageActionTTLChange.constructor, TLRPC.TL_messageActionTTLChange.class);
classStore.put(TLRPC.TL_videoEncrypted.constructor, TLRPC.TL_videoEncrypted.class);
classStore.put(TLRPC.TL_gzip_packed.constructor, TLRPC.TL_gzip_packed.class);
classStore.put(TLRPC.Vector.constructor, TLRPC.Vector.class);
classStore.put(TLRPC.TL_userProfilePhotoOld.constructor, TLRPC.TL_userProfilePhotoOld.class);
}
static TLClassStore store = null;
public static TLClassStore Instance() {
if (store == null) {
store = new TLClassStore();
}
return store;
}
public TLObject TLdeserialize(SerializedData stream, int constructor) {
try {
return TLdeserialize(stream, constructor, null);
} catch (Exception e) {
return null;
}
}
public TLObject TLdeserialize(SerializedData stream, int constructor, TLObject request) {
Class objClass = classStore.get(constructor);
if (objClass != null) {
try {
TLObject response = (TLObject)objClass.newInstance();
if (response instanceof TLRPC.Vector) {
if (request != null) {
request.parseVector((TLRPC.Vector)response, stream);
} else {
int size = stream.readInt32();
for (int a = 0; a < size; a++) {
((TLRPC.Vector)response).objects.add(stream.readInt32());
}
}
} else {
response.readParams(stream);
}
return response;
} catch (IllegalAccessException e) {
Log.e("tmessages", "can't create class");
return null;
} catch (InstantiationException e2) {
Log.e("tmessages", "can't create class");
return null;
}
} else {
if (ConnectionsManager.DEBUG_VERSION) {
Log.e("tmessages", String.format("unknown class %x", constructor));
}
return null;
//throw new RuntimeException(String.format("unknown class %x", constructor));
}
}
}

View file

@ -0,0 +1,41 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.TL;
import org.telegram.messenger.SerializedData;
public class TLObject {
public TLObject () {
}
public void readParams(SerializedData stream) {
}
public byte[] serialize () {
return null;
}
public void serializeToStream(SerializedData stream) {
}
public Class<? extends TLObject> responseClass () {
return this.getClass();
}
public int layer () {
return 8;
}
public void parseVector(TLRPC.Vector vector, SerializedData data) {
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,30 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import java.util.HashMap;
public class Action {
public interface ActionDelegate {
void ActionDidFinishExecution(Action action, HashMap<String, Object> params);
void ActionDidFailExecution(Action action);
}
public ActionDelegate delegate;
public void execute(HashMap params) {
}
public void cancel() {
}
public int state;
}

View file

@ -0,0 +1,123 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.accounts.NetworkErrorException;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
public class AuthenticatorService extends Service {
private static class Authenticator extends AbstractAccountAuthenticator {
private final Context context;
public Authenticator(Context context) {
super(context);
this.context = context;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
throws NetworkErrorException {
return null;
/*Log.e(TAG, "addAccount");
// check if an account already exists; we only allow one
QuillAccount account = new QuillAccount(context);
if (account.exists())
return null;
// ok, go ahead and create new account
Intent intent = new Intent(context, LoginActivity.class);
intent.setAction(LoginActivity.ACTION_LOGIN);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
Bundle reply = new Bundle();
reply.putParcelable(AccountManager.KEY_INTENT, intent);
return reply;*/
}
@Override
public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, Account account) throws NetworkErrorException {
Bundle result = super.getAccountRemovalAllowed(response, account);
/*if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT)
&& !result.containsKey(AccountManager.KEY_INTENT)) {
final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
if (removalAllowed) {
context.sendBroadcast(new Intent("com.stels.messenger.LOGOUT"));
//((StelsApplication) mContext.getApplicationContext()).dropLogin();
}
}*/
return result;
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
return null;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
throws NetworkErrorException {
return null;
}
@Override
public String getAuthTokenLabel(String authTokenType) {
return null;
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response,
Account account, String[] features)
throws NetworkErrorException {
return null;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
throws NetworkErrorException {
return null;
}
}
private static Authenticator authenticator = null;
protected Authenticator getAuthenticator() {
if (authenticator == null) {
authenticator = new Authenticator(this);
}
return authenticator;
}
@Override
public IBinder onBind(Intent intent) {
if (intent.getAction().equals(AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
return getAuthenticator().getIBinder();
} else {
return null;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,65 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.accounts.Account;
import android.accounts.OperationCanceledException;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
public class ContactsSyncAdapterService extends Service {
private static SyncAdapterImpl sSyncAdapter = null;
public ContactsSyncAdapterService() {
super();
}
private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
private Context mContext;
public SyncAdapterImpl(Context context) {
super(context, true);
mContext = context;
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
try {
ContactsSyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
} catch (OperationCanceledException e) {
e.printStackTrace();
}
}
}
@Override
public IBinder onBind(Intent intent) {
return getSyncAdapter().getSyncAdapterBinder();
}
private SyncAdapterImpl getSyncAdapter() {
if (sSyncAdapter == null) {
sSyncAdapter = new SyncAdapterImpl(this);
}
return sSyncAdapter;
}
private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
throws OperationCanceledException {
Log.i("telegram", "performSync: " + account.toString());
}
}

View file

@ -0,0 +1,193 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.util.Log;
import org.telegram.TL.TLRPC;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Datacenter {
public int datacenterId;
public String address;
public int port;
public boolean authorized;
public long authSessionId;
public long authDownloadSessionId;
public long authUploadSessionId;
public byte[] authKey;
public byte[] authKeyId;
public TcpConnection connection;
public TcpConnection downloadConnection;
public TcpConnection uploadConnection;
private ArrayList<ServerSalt> authServerSaltSet = new ArrayList<ServerSalt>();
public Datacenter() {
authServerSaltSet = new ArrayList<ServerSalt>();
}
public Datacenter(SerializedData data) {
datacenterId = data.readInt32();
address = data.readString();
port = data.readInt32();
if (port == 25) {
port = 443;
}
int len = data.readInt32();
if (len != 0) {
authKey = data.readData(len);
}
len = data.readInt32();
if (len != 0) {
authKeyId = data.readData(len);
}
authorized = data.readInt32() != 0;
len = data.readInt32();
for (int a = 0; a < len; a++) {
ServerSalt salt = new ServerSalt();
salt.validSince = data.readInt32();
salt.validUntil = data.readInt32();
salt.value = data.readInt64();
if (authServerSaltSet == null) {
authServerSaltSet = new ArrayList<ServerSalt>();
}
authServerSaltSet.add(salt);
}
}
public void SerializeToStream(SerializedData stream) {
stream.writeInt32(datacenterId);
stream.writeString(address);
stream.writeInt32(port);
if (authKey != null) {
stream.writeInt32(authKey.length);
stream.writeRaw(authKey);
} else {
stream.writeInt32(0);
}
if (authKeyId != null) {
stream.writeInt32(authKeyId.length);
stream.writeRaw(authKeyId);
} else {
stream.writeInt32(0);
}
stream.writeInt32(authorized ? 1 : 0);
stream.writeInt32(authServerSaltSet.size());
for (ServerSalt salt : authServerSaltSet) {
stream.writeInt32(salt.validSince);
stream.writeInt32(salt.validUntil);
stream.writeInt64(salt.value);
}
}
public void clear() {
authKey = null;
authKeyId = null;
authorized = false;
authServerSaltSet.clear();
}
public void clearServerSalts() {
authServerSaltSet.clear();
}
public long selectServerSalt(int date) {
boolean cleanupNeeded = false;
long result = 0;
int maxRemainingInterval = 0;
for (ServerSalt salt : authServerSaltSet) {
if (salt.validUntil < date || (salt.validSince == 0 && salt.validUntil == Integer.MAX_VALUE)) {
cleanupNeeded = true;
} else if (salt.validSince <= date && salt.validUntil > date) {
if (maxRemainingInterval == 0 || Math.abs(salt.validUntil - date) > maxRemainingInterval) {
maxRemainingInterval = Math.abs(salt.validUntil - date);
result = salt.value;
}
}
}
if (cleanupNeeded) {
for (int i = 0; i < authServerSaltSet.size(); i++) {
ServerSalt salt = authServerSaltSet.get(i);
if (salt.validUntil < date) {
authServerSaltSet.remove(i);
i--;
}
}
}
if (ConnectionsManager.DEBUG_VERSION) {
if (result == 0) {
Log.e("tmessages", "Valid salt not found", null);
}
}
return result;
}
private class SaltComparator implements Comparator<ServerSalt> {
@Override
public int compare(ServerSalt o1, ServerSalt o2) {
if (o1.validSince < o2.validSince) {
return -1;
} else if (o1.validSince > o2.validSince) {
return 1;
}
return 0;
}
}
public void mergeServerSalts(int date, ArrayList<TLRPC.TL_futureSalt> salts) {
if (salts == null) {
return;
}
ArrayList<Long> existingSalts = new ArrayList<Long>(authServerSaltSet.size());
for (ServerSalt salt : authServerSaltSet) {
existingSalts.add(salt.value);
}
for (TLRPC.TL_futureSalt saltDesc : salts) {
long salt = saltDesc.salt;
if (!existingSalts.contains(salt) && saltDesc.valid_until > date) {
ServerSalt serverSalt = new ServerSalt();
serverSalt.validSince = saltDesc.valid_since;
serverSalt.validUntil = saltDesc.valid_until;
serverSalt.value = salt;
authServerSaltSet.add(serverSalt);
}
}
Collections.sort(authServerSaltSet, new SaltComparator());
}
public void addServerSalt(ServerSalt serverSalt) {
for (ServerSalt salt : authServerSaltSet) {
if (salt.value == serverSalt.value) {
return;
}
}
authServerSaltSet.add(serverSalt);
Collections.sort(authServerSaltSet, new SaltComparator());
}
boolean containsServerSalt(long value) {
for (ServerSalt salt : authServerSaltSet) {
if (salt.value == value) {
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,76 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
public class DispatchQueue extends Thread {
public Handler handler;
private final Object handlerSyncObject = new Object();
public DispatchQueue(final String threadName) {
setName(threadName);
start();
}
private void sendMessage(Message msg, int delay) {
if (handler == null) {
try {
synchronized (handlerSyncObject) {
handlerSyncObject.wait();
}
} catch (Throwable t) {
t.printStackTrace();
}
}
if (handler != null) {
if (delay <= 0) {
handler.sendMessage(msg);
} else {
handler.sendMessageDelayed(msg, delay);
}
}
}
public void postRunnable(Runnable runnable) {
postRunnable(runnable, 0);
}
public void postRunnable(Runnable runnable, int delay) {
if (handler == null) {
try {
synchronized (handlerSyncObject) {
handlerSyncObject.wait();
}
} catch (Throwable t) {
t.printStackTrace();
}
}
if (handler != null) {
if (delay <= 0) {
handler.post(runnable);
} else {
handler.postDelayed(runnable, delay);
}
}
}
public void run() {
Looper.prepare();
handler = new Handler();
synchronized (handlerSyncObject) {
handlerSyncObject.notify();
}
Looper.loop();
}
}

View file

@ -0,0 +1,620 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import java.io.InputStream;
import java.util.HashMap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.Spanned;
import android.text.style.DynamicDrawableSpan;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Emoji {
private static final int[] ROW_SIZES = {27, 29, 33, 34, 34};
private static HashMap<Long, DrawableInfo> rects = new HashMap<Long, DrawableInfo>();
private static int imgSize, drawImgSize, bigImgSize;
private static boolean inited = false;
private static Paint placeholderPaint;
private static Bitmap[] bmps = new Bitmap[5];
private static boolean[] loading = new boolean[5];
private static final char[] emojiChars={
0x00A9,
0x00AE,
0x203C,
0x2049,
0x2122,
0x2139,
0x2194,
0x2195,
0x2196,
0x2197,
0x2198,
0x2199,
0x21A9,
0x21AA,
0x231A,
0x231B,
0x23E9,
0x23EA,
0x23EB,
0x23EC,
0x23F0,
0x23F3,
0x24C2,
0x25AA,
0x25AB,
0x25B6,
0x25C0,
0x25FB,
0x25FC,
0x25FD,
0x25FE,
0x2600,
0x2601,
0x260E,
0x2611,
0x2614,
0x2615,
0x261D,
0x263A,
0x2648,
0x2649,
0x264A,
0x264B,
0x264C,
0x264D,
0x264E,
0x264F,
0x2650,
0x2651,
0x2652,
0x2653,
0x2660,
0x2663,
0x2665,
0x2666,
0x2668,
0x267B,
0x267F,
0x2693,
0x26A0,
0x26A1,
0x26AA,
0x26AB,
0x26BD,
0x26BE,
0x26C4,
0x26C5,
0x26CE,
0x26D4,
0x26EA,
0x26F2,
0x26F3,
0x26F5,
0x26FA,
0x26FD,
0x2702,
0x2705,
0x2708,
0x2709,
0x270A,
0x270B,
0x270C,
0x270F,
0x2712,
0x2714,
0x2716,
0x2728,
0x2733,
0x2734,
0x2744,
0x2747,
0x274C,
0x274E,
0x2753,
0x2754,
0x2755,
0x2757,
0x2764,
0x2795,
0x2796,
0x2797,
0x27A1,
0x27B0,
0x27BF,
0x2934,
0x2935,
0x2B05,
0x2B06,
0x2B07,
0x2B1B,
0x2B1C,
0x2B50,
0x2B55,
0x3030,
0x303D,
0x3297,
0x3299
};
public static long[][] data = {
new long[]
{},
new long[]
{0x00000000D83DDE04L, 0x00000000D83DDE03L, 0x00000000D83DDE00L, 0x00000000D83DDE0AL, 0x000000000000263AL, 0x00000000D83DDE09L, 0x00000000D83DDE0DL,
0x00000000D83DDE18L, 0x00000000D83DDE1AL, 0x00000000D83DDE17L, 0x00000000D83DDE19L, 0x00000000D83DDE1CL, 0x00000000D83DDE1DL, 0x00000000D83DDE1BL,
0x00000000D83DDE33L, 0x00000000D83DDE01L, 0x00000000D83DDE14L, 0x00000000D83DDE0CL, 0x00000000D83DDE12L, 0x00000000D83DDE1EL, 0x00000000D83DDE23L,
0x00000000D83DDE22L, 0x00000000D83DDE02L, 0x00000000D83DDE2DL, 0x00000000D83DDE2AL, 0x00000000D83DDE25L, 0x00000000D83DDE30L, 0x00000000D83DDE05L,
0x00000000D83DDE13L, 0x00000000D83DDE29L, 0x00000000D83DDE2BL, 0x00000000D83DDE28L, 0x00000000D83DDE31L, 0x00000000D83DDE20L, 0x00000000D83DDE21L,
0x00000000D83DDE24L, 0x00000000D83DDE16L, 0x00000000D83DDE06L, 0x00000000D83DDE0BL, 0x00000000D83DDE37L, 0x00000000D83DDE0EL, 0x00000000D83DDE34L,
0x00000000D83DDE35L, 0x00000000D83DDE32L, 0x00000000D83DDE1FL, 0x00000000D83DDE26L, 0x00000000D83DDE27L, 0x00000000D83DDE08L, 0x00000000D83DDC7FL,
0x00000000D83DDE2EL, 0x00000000D83DDE2CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L, 0x00000000D83DDE2FL, 0x00000000D83DDE36L, 0x00000000D83DDE07L,
0x00000000D83DDE0FL, 0x00000000D83DDE11L, 0x00000000D83DDC72L, 0x00000000D83DDC73L, 0x00000000D83DDC6EL, 0x00000000D83DDC77L, 0x00000000D83DDC82L,
0x00000000D83DDC76L, 0x00000000D83DDC66L, 0x00000000D83DDC67L, 0x00000000D83DDC68L, 0x00000000D83DDC69L, 0x00000000D83DDC74L, 0x00000000D83DDC75L,
0x00000000D83DDC71L, 0x00000000D83DDC7CL, 0x00000000D83DDC78L, 0x00000000D83DDE3AL, 0x00000000D83DDE38L, 0x00000000D83DDE3BL, 0x00000000D83DDE3DL,
0x00000000D83DDE3CL, 0x00000000D83DDE40L, 0x00000000D83DDE3FL, 0x00000000D83DDE39L, 0x00000000D83DDE3EL, 0x00000000D83DDC79L, 0x00000000D83DDC7AL,
0x00000000D83DDE48L, 0x00000000D83DDE49L, 0x00000000D83DDE4AL, 0x00000000D83DDC80L, 0x00000000D83DDC7DL, 0x00000000D83DDCA9L, 0x00000000D83DDD25L,
0x0000000000002728L, 0x00000000D83CDF1FL, 0x00000000D83DDCABL, 0x00000000D83DDCA5L, 0x00000000D83DDCA2L, 0x00000000D83DDCA6L, 0x00000000D83DDCA7L,
0x00000000D83DDCA4L, 0x00000000D83DDCA8L, 0x00000000D83DDC42L, 0x00000000D83DDC40L, 0x00000000D83DDC43L, 0x00000000D83DDC45L, 0x00000000D83DDC44L,
0x00000000D83DDC4DL, 0x00000000D83DDC4EL, 0x00000000D83DDC4CL, 0x00000000D83DDC4AL, 0x000000000000270AL, 0x000000000000270CL, 0x00000000D83DDC4BL,
0x000000000000270BL, 0x00000000D83DDC50L, 0x00000000D83DDC46L, 0x00000000D83DDC47L, 0x00000000D83DDC49L, 0x00000000D83DDC48L, 0x00000000D83DDE4CL,
0x00000000D83DDE4FL, 0x000000000000261DL, 0x00000000D83DDC4FL, 0x00000000D83DDCAAL, 0x00000000D83DDEB6L, 0x00000000D83CDFC3L, 0x00000000D83DDC83L,
0x00000000D83DDC6BL, 0x00000000D83DDC6AL, 0x00000000D83DDC6CL, 0x00000000D83DDC6DL, 0x00000000D83DDC8FL, 0x00000000D83DDC91L, 0x00000000D83DDC6FL,
0x00000000D83DDE46L, 0x00000000D83DDE45L, 0x00000000D83DDC81L, 0x00000000D83DDE4BL, 0x00000000D83DDC86L, 0x00000000D83DDC87L, 0x00000000D83DDC85L,
0x00000000D83DDC70L, 0x00000000D83DDE4EL, 0x00000000D83DDE4DL, 0x00000000D83DDE47L, 0x00000000D83CDFA9L, 0x00000000D83DDC51L, 0x00000000D83DDC52L,
0x00000000D83DDC5FL, 0x00000000D83DDC5EL, 0x00000000D83DDC61L, 0x00000000D83DDC60L, 0x00000000D83DDC62L, 0x00000000D83DDC55L, 0x00000000D83DDC54L,
0x00000000D83DDC5AL, 0x00000000D83DDC57L, 0x00000000D83CDFBDL, 0x00000000D83DDC56L, 0x00000000D83DDC58L, 0x00000000D83DDC59L, 0x00000000D83DDCBCL,
0x00000000D83DDC5CL, 0x00000000D83DDC5DL, 0x00000000D83DDC5BL, 0x00000000D83DDC53L, 0x00000000D83CDF80L, 0x00000000D83CDF02L, 0x00000000D83DDC84L,
0x00000000D83DDC9BL, 0x00000000D83DDC99L, 0x00000000D83DDC9CL, 0x00000000D83DDC9AL, 0x0000000000002764L, 0x00000000D83DDC94L, 0x00000000D83DDC97L,
0x00000000D83DDC93L, 0x00000000D83DDC95L, 0x00000000D83DDC96L, 0x00000000D83DDC9EL, 0x00000000D83DDC98L, 0x00000000D83DDC8CL, 0x00000000D83DDC8BL,
0x00000000D83DDC8DL, 0x00000000D83DDC8EL, 0x00000000D83DDC64L, 0x00000000D83DDC65L, 0x00000000D83DDCACL, 0x00000000D83DDC63L, 0x00000000D83DDCADL},
new long[]
{0x00000000D83DDC36L, 0x00000000D83DDC3AL, 0x00000000D83DDC31L, 0x00000000D83DDC2DL, 0x00000000D83DDC39L, 0x00000000D83DDC30L, 0x00000000D83DDC38L, 0x00000000D83DDC2FL,
0x00000000D83DDC28L, 0x00000000D83DDC3BL, 0x00000000D83DDC37L, 0x00000000D83DDC3DL, 0x00000000D83DDC2EL, 0x00000000D83DDC17L, 0x00000000D83DDC35L,
0x00000000D83DDC12L, 0x00000000D83DDC34L, 0x00000000D83DDC11L, 0x00000000D83DDC18L, 0x00000000D83DDC3CL, 0x00000000D83DDC27L, 0x00000000D83DDC26L,
0x00000000D83DDC24L, 0x00000000D83DDC25L, 0x00000000D83DDC23L, 0x00000000D83DDC14L, 0x00000000D83DDC0DL, 0x00000000D83DDC22L, 0x00000000D83DDC1BL,
0x00000000D83DDC1DL, 0x00000000D83DDC1CL, 0x00000000D83DDC1EL, 0x00000000D83DDC0CL, 0x00000000D83DDC19L, 0x00000000D83DDC1AL, 0x00000000D83DDC20L,
0x00000000D83DDC1FL, 0x00000000D83DDC2CL, 0x00000000D83DDC33L, 0x00000000D83DDC0BL, 0x00000000D83DDC04L, 0x00000000D83DDC0FL, 0x00000000D83DDC00L,
0x00000000D83DDC03L, 0x00000000D83DDC05L, 0x00000000D83DDC07L, 0x00000000D83DDC09L, 0x00000000D83DDC0EL, 0x00000000D83DDC10L, 0x00000000D83DDC13L,
0x00000000D83DDC15L, 0x00000000D83DDC16L, 0x00000000D83DDC01L, 0x00000000D83DDC02L, 0x00000000D83DDC32L, 0x00000000D83DDC21L, 0x00000000D83DDC0AL,
0x00000000D83DDC2BL, 0x00000000D83DDC2AL, 0x00000000D83DDC06L, 0x00000000D83DDC08L, 0x00000000D83DDC29L, 0x00000000D83DDC3EL, 0x00000000D83DDC90L,
0x00000000D83CDF38L, 0x00000000D83CDF37L, 0x00000000D83CDF40L, 0x00000000D83CDF39L, 0x00000000D83CDF3BL, 0x00000000D83CDF3AL, 0x00000000D83CDF41L,
0x00000000D83CDF43L, 0x00000000D83CDF42L, 0x00000000D83CDF3FL, 0x00000000D83CDF3EL, 0x00000000D83CDF44L, 0x00000000D83CDF35L, 0x00000000D83CDF34L,
0x00000000D83CDF32L, 0x00000000D83CDF33L, 0x00000000D83CDF30L, 0x00000000D83CDF31L, 0x00000000D83CDF3CL, 0x00000000D83CDF10L, 0x00000000D83CDF1EL,
0x00000000D83CDF1DL, 0x00000000D83CDF1AL, 0x00000000D83CDF11L, 0x00000000D83CDF12L, 0x00000000D83CDF13L, 0x00000000D83CDF14L, 0x00000000D83CDF15L,
0x00000000D83CDF16L, 0x00000000D83CDF17L, 0x00000000D83CDF18L, 0x00000000D83CDF1CL, 0x00000000D83CDF1BL, 0x00000000D83CDF19L, 0x00000000D83CDF0DL,
0x00000000D83CDF0EL, 0x00000000D83CDF0FL, 0x00000000D83CDF0BL, 0x00000000D83CDF0CL, 0x00000000D83CDF20L, 0x0000000000002B50L, 0x0000000000002600L,
0x00000000000026C5L, 0x0000000000002601L, 0x00000000000026A1L, 0x0000000000002614L, 0x0000000000002744L, 0x00000000000026C4L, 0x00000000D83CDF00L,
0x00000000D83CDF01L, 0x00000000D83CDF08L, 0x00000000D83CDF0AL},
new long[]
{0x00000000D83CDF8DL, 0x00000000D83DDC9DL, 0x00000000D83CDF8EL, 0x00000000D83CDF92L, 0x00000000D83CDF93L, 0x00000000D83CDF8FL, 0x00000000D83CDF86L, 0x00000000D83CDF87L,
0x00000000D83CDF90L, 0x00000000D83CDF91L, 0x00000000D83CDF83L, 0x00000000D83DDC7BL, 0x00000000D83CDF85L, 0x00000000D83CDF84L, 0x00000000D83CDF81L,
0x00000000D83CDF8BL, 0x00000000D83CDF89L, 0x00000000D83CDF8AL, 0x00000000D83CDF88L, 0x00000000D83CDF8CL, 0x00000000D83DDD2EL, 0x00000000D83CDFA5L,
0x00000000D83DDCF7L, 0x00000000D83DDCF9L, 0x00000000D83DDCFCL, 0x00000000D83DDCBFL, 0x00000000D83DDCC0L, 0x00000000D83DDCBDL, 0x00000000D83DDCBEL,
0x00000000D83DDCBBL, 0x00000000D83DDCF1L, 0x000000000000260EL, 0x00000000D83DDCDEL, 0x00000000D83DDCDFL, 0x00000000D83DDCE0L, 0x00000000D83DDCE1L,
0x00000000D83DDCFAL, 0x00000000D83DDCFBL, 0x00000000D83DDD0AL, 0x00000000D83DDD09L, 0x00000000D83DDD08L, 0x00000000D83DDD07L, 0x00000000D83DDD14L,
0x00000000D83DDD14L, 0x00000000D83DDCE2L, 0x00000000D83DDCE3L, 0x00000000000023F3L, 0x000000000000231BL, 0x00000000000023F0L, 0x000000000000231AL,
0x00000000D83DDD13L, 0x00000000D83DDD12L, 0x00000000D83DDD0FL, 0x00000000D83DDD10L, 0x00000000D83DDD11L, 0x00000000D83DDD0EL, 0x00000000D83DDCA1L,
0x00000000D83DDD26L, 0x00000000D83DDD06L, 0x00000000D83DDD05L, 0x00000000D83DDD0CL, 0x00000000D83DDD0BL, 0x00000000D83DDD0DL, 0x00000000D83DDEC0L,
0x00000000D83DDEBFL, 0x00000000D83DDEBDL, 0x00000000D83DDD27L, 0x00000000D83DDD29L, 0x00000000D83DDD28L, 0x00000000D83DDEAAL, 0x00000000D83DDEACL,
0x00000000D83DDCA3L, 0x00000000D83DDD2BL, 0x00000000D83DDD2AL, 0x00000000D83DDC8AL, 0x00000000D83DDC89L, 0x00000000D83DDCB0L, 0x00000000D83DDCB4L,
0x00000000D83DDCB5L, 0x00000000D83DDCB7L, 0x00000000D83DDCB6L, 0x00000000D83DDCB3L, 0x00000000D83DDCB8L, 0x00000000D83DDCF2L, 0x00000000D83DDCE7L,
0x00000000D83DDCE5L, 0x00000000D83DDCE4L, 0x0000000000002709L, 0x00000000D83DDCE9L, 0x00000000D83DDCE8L, 0x00000000D83DDCEFL, 0x00000000D83DDCEBL,
0x00000000D83DDCEAL, 0x00000000D83DDCECL, 0x00000000D83DDCEDL, 0x00000000D83DDCEEL, 0x00000000D83DDCE6L, 0x00000000D83DDCDDL, 0x00000000D83DDCC4L,
0x00000000D83DDCC3L, 0x00000000D83DDCD1L, 0x00000000D83DDCCAL, 0x00000000D83DDCC8L, 0x00000000D83DDCC9L, 0x00000000D83DDCDCL, 0x00000000D83DDCCBL,
0x00000000D83DDCC5L, 0x00000000D83DDCC6L, 0x00000000D83DDCC7L, 0x00000000D83DDCC1L, 0x00000000D83DDCC2L, 0x0000000000002702L, 0x00000000D83DDCCCL,
0x00000000D83DDCCEL, 0x0000000000002712L, 0x000000000000270FL, 0x00000000D83DDCCFL, 0x00000000D83DDCD0L, 0x00000000D83DDCD5L, 0x00000000D83DDCD7L,
0x00000000D83DDCD8L, 0x00000000D83DDCD9L, 0x00000000D83DDCD3L, 0x00000000D83DDCD4L, 0x00000000D83DDCD2L, 0x00000000D83DDCDAL, 0x00000000D83DDCD6L,
0x00000000D83DDD16L, 0x00000000D83DDCDBL, 0x00000000D83DDD2CL, 0x00000000D83DDD2DL, 0x00000000D83DDCF0L, 0x00000000D83CDFA8L, 0x00000000D83CDFACL,
0x00000000D83CDFA4L, 0x00000000D83CDFA7L, 0x00000000D83CDFBCL, 0x00000000D83CDFB5L, 0x00000000D83CDFB6L, 0x00000000D83CDFB9L, 0x00000000D83CDFBBL,
0x00000000D83CDFBAL, 0x00000000D83CDFB7L, 0x00000000D83CDFB8L, 0x00000000D83DDC7EL, 0x00000000D83CDFAEL, 0x00000000D83CDCCFL, 0x00000000D83CDFB4L,
0x00000000D83CDC04L, 0x00000000D83CDFB2L, 0x00000000D83CDFAFL, 0x00000000D83CDFC8L, 0x00000000D83CDFC0L, 0x00000000000026BDL, 0x00000000000026BEL,
0x00000000D83CDFBEL, 0x00000000D83CDFB1L, 0x00000000D83CDFC9L, 0x00000000D83CDFB3L, 0x00000000000026F3L, 0x00000000D83DDEB5L, 0x00000000D83DDEB4L,
0x00000000D83CDFC1L, 0x00000000D83CDFC7L, 0x00000000D83CDFC6L, 0x00000000D83CDFBFL, 0x00000000D83CDFC2L, 0x00000000D83CDFCAL, 0x00000000D83CDFC4L,
0x00000000D83CDFA3L, 0x0000000000002615L, 0x00000000D83CDF75L, 0x00000000D83CDF76L, 0x00000000D83CDF7CL, 0x00000000D83CDF7AL, 0x00000000D83CDF7BL,
0x00000000D83CDF78L, 0x00000000D83CDF79L, 0x00000000D83CDF77L, 0x00000000D83CDF74L, 0x00000000D83CDF55L, 0x00000000D83CDF54L, 0x00000000D83CDF5FL,
0x00000000D83CDF57L, 0x00000000D83CDF56L, 0x00000000D83CDF5DL, 0x00000000D83CDF5BL, 0x00000000D83CDF64L, 0x00000000D83CDF71L, 0x00000000D83CDF63L,
0x00000000D83CDF65L, 0x00000000D83CDF59L, 0x00000000D83CDF58L, 0x00000000D83CDF5AL, 0x00000000D83CDF5CL, 0x00000000D83CDF72L, 0x00000000D83CDF62L,
0x00000000D83CDF61L, 0x00000000D83CDF73L, 0x00000000D83CDF5EL, 0x00000000D83CDF69L, 0x00000000D83CDF6EL, 0x00000000D83CDF66L, 0x00000000D83CDF68L,
0x00000000D83CDF67L, 0x00000000D83CDF82L, 0x00000000D83CDF70L, 0x00000000D83CDF6AL, 0x00000000D83CDF6BL, 0x00000000D83CDF6CL, 0x00000000D83CDF6DL,
0x00000000D83CDF6FL, 0x00000000D83CDF4EL, 0x00000000D83CDF4FL, 0x00000000D83CDF4AL, 0x00000000D83CDF4BL, 0x00000000D83CDF52L, 0x00000000D83CDF47L,
0x00000000D83CDF49L, 0x00000000D83CDF53L, 0x00000000D83CDF51L, 0x00000000D83CDF48L, 0x00000000D83CDF4CL, 0x00000000D83CDF50L, 0x00000000D83CDF4DL,
0x00000000D83CDF60L, 0x00000000D83CDF46L, 0x00000000D83CDF45L, 0x00000000D83CDF3DL},
new long[]
{0x00000000D83CDFE0L, 0x00000000D83CDFE1L, 0x00000000D83CDFEBL, 0x00000000D83CDFE2L, 0x00000000D83CDFE3L, 0x00000000D83CDFE5L, 0x00000000D83CDFE6L, 0x00000000D83CDFEAL,
0x00000000D83CDFE9L, 0x00000000D83CDFE8L, 0x00000000D83DDC92L, 0x00000000000026EAL, 0x00000000D83CDFECL, 0x00000000D83CDFE4L, 0x00000000D83CDF07L,
0x00000000D83CDF06L, 0x00000000D83CDFEFL, 0x00000000D83CDFF0L, 0x00000000000026FAL, 0x00000000D83CDFEDL, 0x00000000D83DDDFCL, 0x00000000D83DDDFEL,
0x00000000D83DDDFBL, 0x00000000D83CDF04L, 0x00000000D83CDF05L, 0x00000000D83CDF03L, 0x00000000D83DDDFDL, 0x00000000D83CDF09L, 0x00000000D83CDFA0L,
0x00000000D83CDFA1L, 0x00000000000026F2L, 0x00000000D83CDFA2L, 0x00000000D83DDEA2L, 0x00000000000026F5L, 0x00000000D83DDEA4L, 0x00000000D83DDEA3L,
0x0000000000002693L, 0x00000000D83DDE80L, 0x0000000000002708L, 0x00000000D83DDCBAL, 0x00000000D83DDE81L, 0x00000000D83DDE82L, 0x00000000D83DDE8AL,
0x00000000D83DDE89L, 0x00000000D83DDE9EL, 0x00000000D83DDE86L, 0x00000000D83DDE84L, 0x00000000D83DDE85L, 0x00000000D83DDE88L, 0x00000000D83DDE87L,
0x00000000D83DDE9DL, 0x00000000D83DDE8BL, 0x00000000D83DDE83L, 0x00000000D83DDE8EL, 0x00000000D83DDE8CL, 0x00000000D83DDE8DL, 0x00000000D83DDE99L,
0x00000000D83DDE98L, 0x00000000D83DDE97L, 0x00000000D83DDE95L, 0x00000000D83DDE96L, 0x00000000D83DDE9BL, 0x00000000D83DDE9AL, 0x00000000D83DDEA8L,
0x00000000D83DDE93L, 0x00000000D83DDE94L, 0x00000000D83DDE92L, 0x00000000D83DDE91L, 0x00000000D83DDE90L, 0x00000000D83DDEB2L, 0x00000000D83DDEA1L,
0x00000000D83DDE9FL, 0x00000000D83DDEA0L, 0x00000000D83DDE9CL, 0x00000000D83DDC88L, 0x00000000D83DDE8FL, 0x00000000D83CDFABL, 0x00000000D83DDEA6L,
0x00000000D83DDEA5L, 0x00000000000026A0L, 0x00000000D83DDEA7L, 0x00000000D83DDD30L, 0x00000000000026FDL, 0x00000000D83CDFEEL, 0x00000000D83CDFB0L,
0x0000000000002668L, 0x00000000D83DDDFFL, 0x00000000D83CDFAAL, 0x00000000D83CDFADL, 0x00000000D83DDCCDL, 0x00000000D83DDEA9L, 0xD83CDDEFD83CDDF5L,
0xD83CDDF0D83CDDF7L, 0xD83CDDE9D83CDDEAL, 0xD83CDDE8D83CDDF3L, 0xD83CDDFAD83CDDF8L, 0xD83CDDEBD83CDDF7L, 0xD83CDDEAD83CDDF8L, 0xD83CDDEED83CDDF9L,
0xD83CDDF7D83CDDFAL, 0xD83CDDECD83CDDE7L},
new long[]
{0x00000000003120E3L, 0x00000000003220E3L, 0x00000000003320E3L, 0x00000000003420E3L, 0x00000000003520E3L, 0x00000000003620E3L, 0x00000000003720E3L, 0x00000000003820E3L,
0x00000000003920E3L, 0x00000000003020E3L, 0x00000000D83DDD1FL, 0x00000000D83DDD22L, 0x00000000002320E3L, 0x00000000D83DDD23L, 0x0000000000002B06L,
0x0000000000002B07L, 0x0000000000002B05L, 0x00000000000027A1L, 0x00000000D83DDD20L, 0x00000000D83DDD21L, 0x00000000D83DDD24L, 0x0000000000002197L,
0x0000000000002196L, 0x0000000000002198L, 0x0000000000002199L, 0x0000000000002194L, 0x0000000000002195L, 0x00000000D83DDD04L, 0x00000000000025C0L,
0x00000000000025B6L, 0x00000000D83DDD3CL, 0x00000000D83DDD3DL, 0x00000000000021A9L, 0x00000000000021AAL, 0x0000000000002139L, 0x00000000000023EAL,
0x00000000000023E9L, 0x00000000000023EBL, 0x00000000000023ECL, 0x0000000000002935L, 0x0000000000002934L, 0x00000000D83CDD97L, 0x00000000D83DDD00L,
0x00000000D83DDD01L, 0x00000000D83DDD02L, 0x00000000D83CDD95L, 0x00000000D83CDD99L, 0x00000000D83CDD92L, 0x00000000D83CDD93L, 0x00000000D83CDD96L,
0x00000000D83DDCF6L, 0x00000000D83CDFA6L, 0x00000000D83CDE01L, 0x00000000D83CDE2FL, 0x00000000D83CDE33L, 0x00000000D83CDE35L, 0x00000000D83CDE32L,
0x00000000D83CDE34L, 0x00000000D83CDE32L, 0x00000000D83CDE50L, 0x00000000D83CDE39L, 0x00000000D83CDE3AL, 0x00000000D83CDE36L, 0x00000000D83CDE1AL,
0x00000000D83DDEBBL, 0x00000000D83DDEB9L, 0x00000000D83DDEBAL, 0x00000000D83DDEBCL, 0x00000000D83DDEBEL, 0x00000000D83DDEB0L, 0x00000000D83DDEAEL,
0x00000000D83CDD7FL, 0x000000000000267FL, 0x00000000D83DDEADL, 0x00000000D83CDE37L, 0x00000000D83CDE38L, 0x00000000D83CDE02L, 0x00000000000024C2L,
0x00000000D83CDE51L, 0x0000000000003299L, 0x0000000000003297L, 0x00000000D83CDD91L, 0x00000000D83CDD98L, 0x00000000D83CDD94L, 0x00000000D83DDEABL,
0x00000000D83DDD1EL, 0x00000000D83DDCF5L, 0x00000000D83DDEAFL, 0x00000000D83DDEB1L, 0x00000000D83DDEB3L, 0x00000000D83DDEB7L, 0x00000000D83DDEB8L,
0x00000000000026D4L, 0x0000000000002733L, 0x0000000000002747L, 0x000000000000274EL, 0x0000000000002705L, 0x0000000000002734L, 0x00000000D83DDC9FL,
0x00000000D83CDD9AL, 0x00000000D83DDCF3L, 0x00000000D83DDCF4L, 0x00000000D83CDD70L, 0x00000000D83CDD71L, 0x00000000D83CDD8EL, 0x00000000D83CDD7EL,
0x00000000D83DDCA0L, 0x00000000000027BFL, 0x000000000000267BL, 0x0000000000002648L, 0x0000000000002649L, 0x000000000000264AL, 0x000000000000264BL,
0x000000000000264CL, 0x000000000000264DL, 0x000000000000264EL, 0x000000000000264FL, 0x0000000000002650L, 0x0000000000002651L, 0x0000000000002652L,
0x0000000000002653L, 0x00000000000026CEL, 0x00000000D83DDD2FL, 0x00000000D83CDFE7L, 0x00000000D83DDCB9L, 0x00000000D83DDCB2L, 0x00000000D83DDCB1L,
0x00000000000000A9L, 0x00000000000000AEL, 0x0000000000002122L, 0x000000000000303DL, 0x0000000000003030L, 0x00000000D83DDD1DL, 0x00000000D83DDD1AL,
0x00000000D83DDD19L, 0x00000000D83DDD1BL, 0x00000000D83DDD1CL, 0x000000000000274CL, 0x0000000000002B55L, 0x0000000000002757L, 0x0000000000002753L,
0x0000000000002755L, 0x0000000000002754L, 0x00000000D83DDD03L, 0x00000000D83DDD5BL, 0x00000000D83DDD67L, 0x00000000D83DDD50L, 0x00000000D83DDD5CL,
0x00000000D83DDD51L, 0x00000000D83DDD5DL, 0x00000000D83DDD52L, 0x00000000D83DDD5EL, 0x00000000D83DDD53L, 0x00000000D83DDD5FL, 0x00000000D83DDD54L,
0x00000000D83DDD60L, 0x00000000D83DDD55L, 0x00000000D83DDD56L, 0x00000000D83DDD57L, 0x00000000D83DDD58L, 0x00000000D83DDD59L, 0x00000000D83DDD5AL,
0x00000000D83DDD61L, 0x00000000D83DDD62L, 0x00000000D83DDD63L, 0x00000000D83DDD64L, 0x00000000D83DDD65L, 0x00000000D83DDD66L, 0x0000000000002716L,
0x0000000000002795L, 0x0000000000002796L, 0x0000000000002797L, 0x0000000000002660L, 0x0000000000002665L, 0x0000000000002663L, 0x0000000000002666L,
0x00000000D83DDCAEL, 0x00000000D83DDCAFL, 0x0000000000002714L, 0x0000000000002611L, 0x00000000D83DDD18L, 0x00000000D83DDD17L, 0x00000000000027B0L,
0x00000000D83DDD31L, 0x00000000D83DDD32L, 0x00000000D83DDD33L, 0x00000000000025FCL, 0x00000000000025FBL, 0x00000000000025FEL, 0x00000000000025FDL,
0x00000000000025AAL, 0x00000000000025ABL, 0x00000000D83DDD3AL, 0x0000000000002B1CL, 0x0000000000002B1BL, 0x00000000000026ABL, 0x00000000000026AAL,
0x00000000D83DDD34L, 0x00000000D83DDD35L, 0x00000000D83DDD3BL, 0x00000000D83DDD36L, 0x00000000D83DDD37L, 0x00000000D83DDD38L, 0x00000000D83DDD39L}};
static {
imgSize = Math.min(scale(30), Utilities.applicationContext.getResources().getDisplayMetrics().density < 1.5f ? 28 : 56);
drawImgSize = scale(20);
bigImgSize = scale(30);
if(Math.abs(imgSize - bigImgSize) < 5) {
bigImgSize = imgSize;
}
for (int j = 1; j < data.length; j++) {
int rsize = ROW_SIZES[j - 1];
for(int i = 0; i < data[j].length; i++) {
Rect rect = new Rect((i % rsize) * imgSize, (i / rsize) * imgSize, (i % rsize + 1) * imgSize, (i / rsize + 1) * imgSize);
rects.put(data[j][i], new DrawableInfo(rect, j - 1));
}
}
placeholderPaint = new Paint();
placeholderPaint.setColor(0x55000000);
}
public static int scale(float value) {
return (int)(Utilities.applicationContext.getResources().getDisplayMetrics().density * value);
}
private static Bitmap loadPage(final int page){
try {
int rsize = ROW_SIZES[page];
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
opts.inDither = false;
if (Utilities.applicationContext.getResources().getDisplayMetrics().density < 1.5f) {
opts.inSampleSize = 2;
}
int iw, ih;
InputStream is = Utilities.applicationContext.getAssets().open("emojisprite_" + page + ".png");
Bitmap color = BitmapFactory.decodeStream(is, null, opts);
is.close();
iw = color.getWidth();
ih = color.getHeight();
ih = (int)Math.round(((double)imgSize * rsize) * ((double)ih / iw));
iw = imgSize * rsize;
if(iw < color.getWidth() && ih < color.getWidth()) {
color = Bitmap.createScaledBitmap(color, iw, ih, true);
}
bmps[page] = color;
final Bitmap img = color;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
/*for (int a = 0; a < drawables.size(); a++) {
WeakReference<EmojiDrawable> it = drawables.get(a);
if (it.get() == null) {
drawables.remove(a);
a--;
} else {
EmojiDrawable drawable = it.get();
if (drawable.page == page) {
drawable.bmp = img;
}
drawable.invalidateSelf();
}
}*/
NotificationCenter.Instance.postNotificationName(999);
}
});
return color;
} catch(Throwable x) {
Log.e("tmessages", "Error loading emoji", x);
}
return null;
}
private static void loadPageAsync(final int page) {
if(loading[page]) {
return;
}
loading[page] = true;
new Thread(new Runnable() {
public void run() {
loadPage(page);
loading[page] = false;
}
}).start();
}
public static void invalidateAll(View view){
if(view instanceof ViewGroup) {
ViewGroup g = (ViewGroup)view;
for(int i = 0; i < g.getChildCount(); i++){
invalidateAll(g.getChildAt(i));
}
} else if(view instanceof TextView) {
view.invalidate();
}
}
public static Drawable getEmojiDrawable(long code){
DrawableInfo info = rects.get(code);
if(info == null){
Log.e("tmessages", "No emoji drawable for code " + String.format("%016X", code));
return null;
}
EmojiDrawable ed = new EmojiDrawable(info);
ed.setBounds(0, 0, drawImgSize, drawImgSize);
if(bmps[info.page] == null) {
loadPageAsync(info.page);
}
/*drawables.add(new WeakReference<EmojiDrawable>(ed));
try {
for (int a = 0; a < drawables.size(); a++) {
WeakReference<EmojiDrawable> it = drawables.get(a);
if (it.get() == null) {
drawables.remove(a);
a--;
}
}
} catch(Throwable x) {
x.printStackTrace();
}*/
return ed;
}
public static Drawable getEmojiBigDrawable(long code) {
EmojiDrawable ed = (EmojiDrawable)getEmojiDrawable(code);
if (ed == null) {
return null;
}
ed.setBounds(0, 0, bigImgSize, bigImgSize);
ed.fullSize = true;
return ed;
}
public static class EmojiDrawable extends Drawable {
Rect rect;
int page;
boolean fullSize = false;
private static Paint paint;
Bitmap bmp;
static {
paint = new Paint();
paint.setFilterBitmap(true);
}
public EmojiDrawable(DrawableInfo info){
rect = info.rect;
page = info.page;
}
@Override
public void draw(Canvas canvas) {
if(bmps[page] == null){
canvas.drawRect(getBounds(), placeholderPaint);
return;
}
if(bmp == null) {
bmp = bmps[page];
}
Rect b = copyBounds();
int cX = b.centerX(), cY = b.centerY();
b.left = cX - (fullSize ? bigImgSize : drawImgSize) / 2;
b.right = cX + (fullSize ? bigImgSize : drawImgSize) / 2;
b.top = cY - (fullSize ? bigImgSize : drawImgSize) / 2;
b.bottom = cY + (fullSize ? bigImgSize : drawImgSize) / 2;
canvas.drawBitmap(bmp, rect, b, paint);
}
@Override
public int getOpacity() {
return 0;
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
}
private static class DrawableInfo {
Rect rect;
int page;
public DrawableInfo(Rect rect, int p) {
this.rect = rect;
page = p;
}
}
private static boolean inArray(char c, char[] a) {
for(char cc : a) {
if(cc == c) {
return true;
}
}
return false;
}
public static CharSequence replaceEmoji(CharSequence cs) {
if (cs == null || cs.length() == 0) {
return cs;
}
Spannable s;
if (cs instanceof Spannable){
s = (Spannable)cs;
} else {
s = Spannable.Factory.getInstance().newSpannable(cs);
}
long buf = 0;
for (int i = 0; i < cs.length(); i++){
char c = cs.charAt(i);
if (c == 0xD83C || c == 0xD83D || (buf != 0 && (buf & 0xFFFFFFFF00000000L) == 0 && (c >= 0xDDE6 && c <= 0xDDFA))) {
buf <<= 16;
buf |= c;
} else if (buf > 0 && (c & 0xF000) == 0xD000) {
buf <<= 16;
buf |= c;
Drawable d = Emoji.getEmojiDrawable(buf);
if (d != null){
EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM);
if (c>= 0xDDE6 && c <= 0xDDFA) {
s.setSpan(span, i - 3, i + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
s.setSpan(span, i - 1, i + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
buf = 0;
} else if (c == 0x20E3) {
if (i > 0) {
char c2 = cs.charAt(i - 1);
if((c2 >= '0' && c2 <= '9') || c2 == '#') {
buf = c2;
buf <<= 16;
buf |= c;
Drawable d = Emoji.getEmojiDrawable(buf);
if(d != null) {
EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM);
s.setSpan(span, i - 1, i + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
buf = 0;
}
}
} else if(inArray(c, emojiChars)){
Drawable d = Emoji.getEmojiDrawable(c);
if(d != null){
EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM);
s.setSpan(span, i, i + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
return s;
}
public static class EmojiSpan extends ImageSpan {
public EmojiSpan(Drawable d, int verticalAlignment) {
super(d, verticalAlignment);
}
@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
if (fm == null) {
fm = new Paint.FontMetricsInt();
}
int sz = super.getSize(paint, text, start, end, fm);
int offset = (int)(8 * Utilities.applicationContext.getResources().getDisplayMetrics().density);
int w = (int)(20 * Utilities.applicationContext.getResources().getDisplayMetrics().density / 2);
fm.top = -w - offset;
fm.bottom = w - offset;
fm.ascent = -w - offset;
fm.leading = 0;
fm.descent = w - offset;
return sz;
}
}
public static class XImageSpan extends ImageSpan {
public int uid;
public XImageSpan(Drawable d, int verticalAlignment) {
super(d, verticalAlignment);
}
@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
if (fm == null) {
fm = new Paint.FontMetricsInt();
}
int sz = super.getSize(paint, text, start, end, fm);
int offset = (int)(6 * Utilities.applicationContext.getResources().getDisplayMetrics().density);
int w = (fm.bottom - fm.top) / 2;
fm.top = -w - offset;
fm.bottom = w - offset;
fm.ascent = -w - offset;
fm.leading = 0;
fm.descent = w - offset;
return sz;
}
}
// @Override
// public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
// if (fm == null) {
// fm = new Paint.FontMetricsInt();
// }
// paint.getFontMetricsInt(fm);
//
// int sz = super.getSize(paint, text, start, end, fm);
// if(fm != null) {
// fm.ascent = (int)paint.ascent();
// fm.descent = (int)paint.descent();
// }
// return sz;
// }
}

View file

@ -0,0 +1,87 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
import java.util.HashMap;
public class ExportAuthorizationAction extends Action {
public Datacenter datacenter;
TLRPC.TL_auth_exportedAuthorization exportedAuthorization;
int retryCount;
public ExportAuthorizationAction(Datacenter d) {
datacenter = d;
}
public void execute(HashMap options) {
if (datacenter == null) {
delegate.ActionDidFailExecution(this);
return;
}
beginExport();
}
void beginExport() {
TLRPC.TL_auth_exportAuthorization exportAuthorization = new TLRPC.TL_auth_exportAuthorization();
exportAuthorization.dc_id = datacenter.datacenterId;
ConnectionsManager.Instance.performRpc(exportAuthorization, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
exportedAuthorization = (TLRPC.TL_auth_exportedAuthorization)response;
beginImport();
} else {
retryCount++;
if (retryCount >= 3) {
delegate.ActionDidFailExecution(ExportAuthorizationAction.this);
} else {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
beginExport();
}
}, retryCount * 1500);
}
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
void beginImport() {
TLRPC.TL_auth_importAuthorization importAuthorization = new TLRPC.TL_auth_importAuthorization();
importAuthorization.bytes = exportedAuthorization.bytes;
importAuthorization.id = exportedAuthorization.id;
ConnectionsManager.Instance.performRpc(importAuthorization, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
delegate.ActionDidFinishExecution(ExportAuthorizationAction.this, null);
} else {
exportedAuthorization = null;
retryCount++;
if (retryCount >= 3) {
delegate.ActionDidFailExecution(ExportAuthorizationAction.this);
} else {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
beginExport();
}
}, retryCount * 1500);
}
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassEnableUnauthorized, datacenter.datacenterId);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,500 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
import java.io.RandomAccessFile;
import java.net.URL;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLConnection;
import java.util.Scanner;
public class FileLoadOperation {
private int downloadChunkSize = 1024 * 32;
public int datacenter_id;
private TLRPC.InputFileLocation location;
public volatile int state = 0;
private int downloadedBytes;
public int totalBytesCount;
public FileLoadOperationDelegate delegate;
public Bitmap image;
public String filter;
private byte[] key;
private byte[] iv;
private long requestToken = 0;
private File cacheFileTemp;
private File cacheFileFinal;
private String httpUrl;
private URLConnection httpConnection;
public boolean needBitmapCreate = true;
private InputStream httpConnectionStream;
private RandomAccessFile fileOutputStream;
public static interface FileLoadOperationDelegate {
public abstract void didFinishLoadingFile(FileLoadOperation operation);
public abstract void didFailedLoadingFile(FileLoadOperation operation);
public abstract void didChangedLoadProgress(FileLoadOperation operation, float progress);
}
public FileLoadOperation(TLRPC.FileLocation fileLocation) {
if (fileLocation instanceof TLRPC.TL_fileEncryptedLocation) {
location = new TLRPC.TL_inputEncryptedFileLocation();
location.id = fileLocation.volume_id;
location.volume_id = fileLocation.volume_id;
location.access_hash = fileLocation.secret;
location.local_id = fileLocation.local_id;
iv = new byte[32];
System.arraycopy(fileLocation.iv, 0, iv, 0, iv.length);
key = fileLocation.key;
datacenter_id = fileLocation.dc_id;
} else if (fileLocation instanceof TLRPC.TL_fileLocation) {
location = new TLRPC.TL_inputFileLocation();
location.volume_id = fileLocation.volume_id;
location.secret = fileLocation.secret;
location.local_id = fileLocation.local_id;
datacenter_id = fileLocation.dc_id;
}
}
public FileLoadOperation(TLRPC.Video videoLocation) {
if (videoLocation instanceof TLRPC.TL_video) {
location = new TLRPC.TL_inputVideoFileLocation();
datacenter_id = videoLocation.dc_id;
location.id = videoLocation.id;
location.access_hash = videoLocation.access_hash;
} else if (videoLocation instanceof TLRPC.TL_videoEncrypted) {
location = new TLRPC.TL_inputEncryptedFileLocation();
location.id = videoLocation.id;
location.access_hash = videoLocation.access_hash;
datacenter_id = videoLocation.dc_id;
iv = new byte[32];
System.arraycopy(videoLocation.iv, 0, iv, 0, iv.length);
key = videoLocation.key;
}
}
public FileLoadOperation(String url) {
httpUrl = url;
}
public void start() {
if (state != 0) {
return;
}
state = 1;
boolean ignoreCache = false;
boolean onlyCache = false;
String fileNameFinal;
String fileNameTemp;
if (httpUrl != null) {
fileNameFinal = Utilities.MD5(httpUrl);
fileNameTemp = fileNameFinal + "_temp.jpg";
fileNameFinal += ".jpg";
} else if (location.volume_id != 0 && location.local_id != 0) {
fileNameTemp = location.volume_id + "_" + location.local_id + "_temp.jpg";
fileNameFinal = location.volume_id + "_" + location.local_id + ".jpg";
if (datacenter_id == Integer.MIN_VALUE || location.volume_id == Integer.MIN_VALUE) {
onlyCache = true;
}
} else {
ignoreCache = true;
needBitmapCreate = false;
fileNameTemp = datacenter_id + "_" + location.id + "_temp.mp4";
fileNameFinal = datacenter_id + "_" + location.id + ".mp4";
}
boolean exist;
cacheFileFinal = new File(Utilities.getCacheDir(), fileNameFinal);
if ((exist = cacheFileFinal.exists()) && !ignoreCache) {
Utilities.cacheOutQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
int delay = 20;
if (FileLoader.Instance.runtimeHack != null) {
delay = 60;
}
if (FileLoader.lastCacheOutTime != 0 && FileLoader.lastCacheOutTime > System.currentTimeMillis() - delay) {
Thread.sleep(delay);
}
FileLoader.lastCacheOutTime = System.currentTimeMillis();
if (state != 1) {
return;
}
if (needBitmapCreate) {
FileInputStream is = new FileInputStream(cacheFileFinal);
BitmapFactory.Options opts = new BitmapFactory.Options();
float w_filter = 0;
float h_filter;
if (filter != null) {
String args[] = filter.split("_");
w_filter = Float.parseFloat(args[0]) * FileLoader.Instance.density;
h_filter = Float.parseFloat(args[1]) * FileLoader.Instance.density;
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(cacheFileFinal.getAbsolutePath(), opts);
float photoW = opts.outWidth;
float photoH = opts.outHeight;
float scaleFactor = Math.max(photoW / w_filter, photoH / h_filter);
if (scaleFactor < 1) {
scaleFactor = 1;
}
opts.inJustDecodeBounds = false;
opts.inSampleSize = (int)scaleFactor;
}
opts.inPreferredConfig = Bitmap.Config.RGB_565;
opts.inDither = false;
image = BitmapFactory.decodeStream(is, null, opts);
is.close();
if (image == null) {
cacheFileFinal.delete();
} else {
if (filter != null && image != null) {
float bitmapW = image.getWidth();
float bitmapH = image.getHeight();
if (bitmapW != w_filter && bitmapW > w_filter) {
float scaleFactor = bitmapW / w_filter;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, (int)w_filter, (int)(bitmapH / scaleFactor), true);
if (image != scaledBitmap) {
image.recycle();
image = scaledBitmap;
}
}
}
if (FileLoader.Instance.runtimeHack != null) {
FileLoader.Instance.runtimeHack.trackFree(image.getRowBytes() * image.getHeight());
}
}
}
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFinishLoadingFile(FileLoadOperation.this);
}
});
} catch (Exception e) {
cacheFileFinal.delete();
e.printStackTrace();
}
}
});
} else {
if (onlyCache) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
});
return;
}
cacheFileTemp = new File(Utilities.getCacheDir(), fileNameTemp);
if (cacheFileTemp.exists()) {
downloadedBytes = (int)cacheFileTemp.length();
downloadedBytes = downloadedBytes / 1024 * 1024;
}
if (exist) {
cacheFileFinal.delete();
}
try {
fileOutputStream = new RandomAccessFile(cacheFileTemp, "rws");
if (downloadedBytes != 0) {
fileOutputStream.seek(downloadedBytes);
}
} catch (Exception e) {
e.printStackTrace();
}
if (fileOutputStream == null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
});
}
if (httpUrl != null) {
startDownloadHTTPRequest();
} else {
startDownloadRequest();
}
}
}
public void cancel() {
if (state != 1) {
return;
}
state = 2;
if (httpUrl != null) {
try {
httpConnectionStream.close();
httpConnection = null;
httpConnectionStream = null;
} catch (Exception e) {
e.printStackTrace();
}
} else {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
fileOutputStream = null;
} catch (Exception e) {
e.printStackTrace();
}
}
if (requestToken != 0) {
ConnectionsManager.Instance.cancelRpc(requestToken, true);
}
}
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
private void onFinishLoadingFile() throws Exception {
if (state != 1) {
return;
}
state = 3;
fileOutputStream.close();
fileOutputStream = null;
final boolean renamed = cacheFileTemp.renameTo(cacheFileFinal);
if (needBitmapCreate) {
Utilities.cacheOutQueue.postRunnable(new Runnable() {
@Override
public void run() {
int delay = 20;
if (FileLoader.Instance.runtimeHack != null) {
delay = 60;
}
if (FileLoader.lastCacheOutTime != 0 && FileLoader.lastCacheOutTime > System.currentTimeMillis() - delay) {
try {
Thread.sleep(delay);
} catch (Exception e) {
e.printStackTrace();
}
}
BitmapFactory.Options opts = new BitmapFactory.Options();
float w_filter = 0;
float h_filter;
if (filter != null) {
String args[] = filter.split("_");
w_filter = Float.parseFloat(args[0]) * FileLoader.Instance.density;
h_filter = Float.parseFloat(args[1]) * FileLoader.Instance.density;
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(cacheFileFinal.getAbsolutePath(), opts);
float photoW = opts.outWidth;
float photoH = opts.outHeight;
float scaleFactor = Math.max(photoW / w_filter, photoH / h_filter);
if (scaleFactor < 1) {
scaleFactor = 1;
}
opts.inJustDecodeBounds = false;
opts.inSampleSize = (int) scaleFactor;
}
opts.inPreferredConfig = Bitmap.Config.RGB_565;
opts.inDither = false;
try {
if (renamed) {
image = BitmapFactory.decodeStream(new FileInputStream(cacheFileFinal), null, opts);
} else {
image = BitmapFactory.decodeStream(new FileInputStream(cacheFileTemp), null, opts);
}
if (filter != null && image != null) {
float bitmapW = image.getWidth();
float bitmapH = image.getHeight();
if (bitmapW != w_filter && bitmapW > w_filter) {
float scaleFactor = bitmapW / w_filter;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, (int) w_filter, (int) (bitmapH / scaleFactor), true);
if (image != scaledBitmap) {
image.recycle();
image = scaledBitmap;
}
}
}
if (FileLoader.Instance.runtimeHack != null) {
FileLoader.Instance.runtimeHack.trackFree(image.getRowBytes() * image.getHeight());
}
} catch (Exception e) {
e.printStackTrace();
}
delegate.didFinishLoadingFile(FileLoadOperation.this);
}
});
} else {
delegate.didFinishLoadingFile(FileLoadOperation.this);
}
}
private void startDownloadHTTPRequest() {
if (state != 1) {
return;
}
if (httpConnection == null) {
try {
URL downloadUrl = new URL(httpUrl);
httpConnection = downloadUrl.openConnection();
httpConnection.setConnectTimeout(5000);
httpConnection.setReadTimeout(5000);
httpConnection.connect();
httpConnectionStream = httpConnection.getInputStream();
} catch (Exception e) {
e.printStackTrace();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
});
return;
}
}
try {
byte[] data = new byte[1024 * 2];
int readed = httpConnectionStream.read(data);
if (readed > 0) {
fileOutputStream.write(data, 0, readed);
Utilities.imageLoadQueue.postRunnable(new Runnable() {
@Override
public void run() {
startDownloadHTTPRequest();
}
});
} else if (readed == -1) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
onFinishLoadingFile();
} catch (Exception e) {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
}
});
} else {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
});
}
} catch (Exception e) {
e.printStackTrace();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
});
try {
httpConnectionStream.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
private void startDownloadRequest() {
if (state != 1) {
return;
}
TLRPC.TL_upload_getFile req = new TLRPC.TL_upload_getFile();
req.location = location;
req.offset = downloadedBytes;
req.limit = downloadChunkSize;
requestToken = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
requestToken = 0;
if (error == null) {
TLRPC.TL_upload_file res = (TLRPC.TL_upload_file)response;
try {
if (res.bytes.length == 0) {
onFinishLoadingFile();
return;
}
if (key != null) {
res.bytes = Utilities.aesIgeEncryption(res.bytes, key, iv, false, true);
}
if (fileOutputStream != null) {
fileOutputStream.write(res.bytes);
}
downloadedBytes += res.bytes.length;
res.bytes = null;
if (totalBytesCount != 0) {
delegate.didChangedLoadProgress(FileLoadOperation.this, Math.min(1.0f, (float)downloadedBytes / (float)totalBytesCount));
}
if (downloadedBytes % downloadChunkSize == 0 || totalBytesCount != 0 && totalBytesCount != downloadedBytes) {
startDownloadRequest();
} else {
onFinishLoadingFile();
}
} catch (Exception e) {
delegate.didFailedLoadingFile(FileLoadOperation.this);
e.printStackTrace();
}
} else {
if (error.text.contains("FILE_MIGRATE_")) {
String errorMsg = error.text.replace("FILE_MIGRATE_", "");
Scanner scanner = new Scanner(errorMsg);
scanner.useDelimiter("");
Integer val;
try {
val = scanner.nextInt();
} catch (Exception e) {
val = null;
}
if (val == null) {
delegate.didFailedLoadingFile(FileLoadOperation.this);
} else {
datacenter_id = val;
startDownloadRequest();
}
} else if (error.text.contains("OFFSET_INVALID")) {
if (downloadedBytes % downloadChunkSize == 0) {
try {
onFinishLoadingFile();
} catch (Exception e) {
e.printStackTrace();
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
} else {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
} else {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
}
}
}, new RPCRequest.RPCProgressDelegate() {
@Override
public void progress(int length, int progress) {
}
}, null, true, RPCRequest.RPCRequestClassDownloadMedia, datacenter_id);
}
}

View file

@ -0,0 +1,969 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import org.telegram.TL.TLRPC;
import org.telegram.ui.Views.BackupImageView;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
public class FileLoader {
public static FileLoader Instance = new FileLoader();
public LruCache memCache;
private String ignoreRemoval = null;
private HashMap<String, CacheImage> imageLoading;
private HashMap<Integer, CacheImage> imageLoadingByKeys;
private Queue<FileLoadOperation> operationsQueue;
private Queue<FileLoadOperation> runningOperation;
private final int maxConcurentLoadingOpertaionsCount = 2;
private Queue<FileUploadOperation> uploadOperationQueue;
private HashMap<String, FileUploadOperation> uploadOperationPaths;
private int currentUploadOperationsCount = 0;
private Queue<FileLoadOperation> loadOperationQueue;
private HashMap<String, FileLoadOperation> loadOperationPaths;
private int currentLoadOperationsCount = 0;
public static long lastCacheOutTime = 0;
public ConcurrentHashMap<String, Float> fileProgresses = new ConcurrentHashMap<String, Float>();
private long lastProgressUpdateTime = 0;
public float density = 1;
private HashMap<String, Integer> BitmapUseCounts = new HashMap<String, Integer>();
int lastImageNum;
public static final int FileDidUpload = 10000;
public static final int FileDidFailUpload = 10001;
public static final int FileUploadProgressChanged = 10002;
public static final int FileLoadProgressChanged = 10003;
public static final int FileDidLoaded = 10004;
public static final int FileDidFailedLoad = 10005;
public class VMRuntimeHack {
private Object runtime = null;
private Method trackAllocation = null;
private Method trackFree = null;
public boolean trackAlloc(long size) {
if (runtime == null)
return false;
try {
Object res = trackAllocation.invoke(runtime, size);
return (res instanceof Boolean) ? (Boolean)res : true;
} catch (IllegalArgumentException e) {
return false;
} catch (IllegalAccessException e) {
return false;
} catch (InvocationTargetException e) {
return false;
}
}
public boolean trackFree(long size) {
if (runtime == null)
return false;
try {
Object res = trackFree.invoke(runtime, size);
return (res instanceof Boolean) ? (Boolean)res : true;
} catch (IllegalArgumentException e) {
return false;
} catch (IllegalAccessException e) {
return false;
} catch (InvocationTargetException e) {
return false;
}
}
@SuppressWarnings("unchecked")
public VMRuntimeHack() {
boolean success = false;
try {
Class cl = Class.forName("dalvik.system.VMRuntime");
Method getRt = cl.getMethod("getRuntime", new Class[0]);
runtime = getRt.invoke(null, new Object[0]);
trackAllocation = cl.getMethod("trackExternalAllocation", new Class[] {long.class});
trackFree = cl.getMethod("trackExternalFree", new Class[] {long.class});
success = true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
if (!success) {
Log.i("tmessages", "VMRuntime hack does not work!");
runtime = null;
trackAllocation = null;
trackFree = null;
}
}
}
public VMRuntimeHack runtimeHack = null;
private class CacheImage {
public String key;
public ArrayList<View> imageViewArray;
public FileLoadOperation loadOperation;
public void addImageView(View imageView) {
if (imageViewArray == null) {
imageViewArray = new ArrayList<View>();
}
boolean exist = false;
for (View v : imageViewArray) {
if (v == imageView) {
exist = true;
break;
}
}
if (!exist) {
imageViewArray.add(imageView);
}
}
public void removeImageView(View imageView) {
if (imageViewArray != null) {
for (int a = 0; a < imageViewArray.size(); a++) {
View obj = imageViewArray.get(a);
if (obj == null || obj == imageView) {
imageViewArray.remove(a);
a--;
}
}
}
}
public void callAndClear(Bitmap image) {
if (image != null) {
for (View imgView : imageViewArray) {
if (imgView instanceof BackupImageView) {
((BackupImageView)imgView).setImageBitmap(image, key);
} else if (imgView instanceof ImageView) {
((ImageView)imgView).setImageBitmap(image);
}
}
}
Utilities.imageLoadQueue.postRunnable(new Runnable() {
@Override
public void run() {
imageViewArray.clear();
loadOperation = null;
}
});
}
public void cancelAndClear() {
if (loadOperation != null) {
loadOperation.cancel();
loadOperation = null;
}
imageViewArray.clear();
}
}
public void incrementUseCount(String key) {
Integer count = BitmapUseCounts.get(key);
if (count == null) {
BitmapUseCounts.put(key, 1);
} else {
BitmapUseCounts.put(key, count + 1);
}
}
public boolean decrementUseCount(String key) {
Integer count = BitmapUseCounts.get(key);
if (count == null) {
return true;
}
if (count == 1) {
BitmapUseCounts.remove(key);
return true;
} else {
BitmapUseCounts.put(key, count - 1);
}
return false;
}
/*class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private CacheImage cacheImage;
private Bitmap bitmap;
private int data = 0;
public BitmapWorkerTask(ArrayList<WeakReference<View>> arr) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}*/
public FileLoader() {
int maxMemory = (int)Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 10;
density = Utilities.applicationContext.getResources().getDisplayMetrics().density;
if (Build.VERSION.SDK_INT < 11) {
runtimeHack = new VMRuntimeHack();
cacheSize = 1024 * 1024 * 3;
}
memCache = new LruCache(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
if(Build.VERSION.SDK_INT < 12) {
return bitmap.getRowBytes() * bitmap.getHeight();
} else {
return bitmap.getByteCount();
}
}
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) {
if (ignoreRemoval != null && key != null && ignoreRemoval.equals(key)) {
return;
}
Integer count = BitmapUseCounts.get(key);
if (count == null || count == 0) {
if (runtimeHack != null) {
runtimeHack.trackAlloc(oldBitmap.getRowBytes() * oldBitmap.getHeight());
}
oldBitmap.recycle();
}
}
};
imageLoading = new HashMap<String, CacheImage>();
imageLoadingByKeys = new HashMap<Integer, CacheImage>();
operationsQueue = new LinkedList<FileLoadOperation>();
runningOperation = new LinkedList<FileLoadOperation>();
uploadOperationQueue = new LinkedList<FileUploadOperation>();
uploadOperationPaths = new HashMap<String, FileUploadOperation>();
loadOperationPaths = new HashMap<String, FileLoadOperation>();
loadOperationQueue = new LinkedList<FileLoadOperation>();
}
public void cancelUploadFile(final String location) {
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
FileUploadOperation operation = uploadOperationPaths.get(location);
if (operation != null) {
uploadOperationQueue.remove(operation);
operation.cancel();
}
}
});
}
public boolean isInCache(String key) {
return memCache.get(key) != null;
}
public void uploadFile(final String location, final byte[] key, final byte[] iv) {
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
FileUploadOperation operation = new FileUploadOperation(location, key, iv);
uploadOperationPaths.put(location, operation);
operation.delegate = new FileUploadOperation.FileUploadOperationDelegate() {
@Override
public void didFinishUploadingFile(FileUploadOperation operation, final TLRPC.TL_inputFile inputFile, final TLRPC.TL_inputEncryptedFileUploaded inputEncryptedFile) {
NotificationCenter.Instance.postNotificationName(FileDidUpload, location, inputFile, inputEncryptedFile);
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
uploadOperationPaths.remove(location);
currentUploadOperationsCount--;
if (currentUploadOperationsCount < 2) {
FileUploadOperation operation = uploadOperationQueue.poll();
if (operation != null) {
currentUploadOperationsCount++;
operation.start();
}
}
}
});
}
@Override
public void didFailedUploadingFile(FileUploadOperation operation) {
fileProgresses.remove(location);
if (operation.state != 2) {
NotificationCenter.Instance.postNotificationName(FileDidFailUpload, location);
}
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
uploadOperationPaths.remove(location);
currentUploadOperationsCount--;
if (currentUploadOperationsCount < 2) {
FileUploadOperation operation = uploadOperationQueue.poll();
if (operation != null) {
currentUploadOperationsCount++;
operation.start();
}
}
}
});
}
@Override
public void didChangedUploadProgress(FileUploadOperation operation, final float progress) {
if (operation.state != 2) {
fileProgresses.put(location, progress);
}
long currentTime = System.currentTimeMillis();
if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 500) {
lastProgressUpdateTime = currentTime;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileUploadProgressChanged, location, progress);
}
});
}
}
};
if (currentUploadOperationsCount < 2) {
currentUploadOperationsCount++;
operation.start();
} else {
uploadOperationQueue.add(operation);
}
}
});
}
public void cancelLoadFile(final TLRPC.Video video, final TLRPC.PhotoSize photo) {
if (video == null && photo == null) {
return;
}
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
String fileName = null;
if (video != null) {
fileName = video.dc_id + "_" + video.id + ".mp4";
} else if (photo != null) {
fileName = photo.location.volume_id + "_" + photo.location.local_id + ".jpg";
}
FileLoadOperation operation = loadOperationPaths.get(fileName);
if (operation != null) {
loadOperationQueue.remove(operation);
operation.cancel();
}
}
});
}
public void loadFile(final TLRPC.Video video, final TLRPC.PhotoSize photo) {
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
String fileName = null;
if (video != null) {
fileName = video.dc_id + "_" + video.id + ".mp4";
} else if (photo != null) {
fileName = photo.location.volume_id + "_" + photo.location.local_id + ".jpg";
}
if (loadOperationPaths.containsKey(fileName)) {
return;
}
FileLoadOperation operation = null;
if (video != null) {
operation = new FileLoadOperation(video);
operation.totalBytesCount = video.size;
} else if (photo != null) {
operation = new FileLoadOperation(photo.location);
operation.totalBytesCount = photo.size;
operation.needBitmapCreate = false;
}
final String arg1 = fileName;
loadOperationPaths.put(fileName, operation);
operation.delegate = new FileLoadOperation.FileLoadOperationDelegate() {
@Override
public void didFinishLoadingFile(FileLoadOperation operation) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileLoadProgressChanged, arg1, 1.0f);
}
});
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileDidLoaded, arg1);
}
});
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
loadOperationPaths.remove(arg1);
currentLoadOperationsCount--;
if (currentLoadOperationsCount < 2) {
FileLoadOperation operation = loadOperationQueue.poll();
if (operation != null) {
currentLoadOperationsCount++;
operation.start();
}
}
}
});
}
@Override
public void didFailedLoadingFile(FileLoadOperation operation) {
fileProgresses.remove(arg1);
if (operation.state != 2) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileDidFailedLoad, arg1);
}
});
}
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
loadOperationPaths.remove(arg1);
currentLoadOperationsCount--;
if (currentLoadOperationsCount < 2) {
FileLoadOperation operation = loadOperationQueue.poll();
if (operation != null) {
currentLoadOperationsCount++;
operation.start();
}
}
}
});
}
@Override
public void didChangedLoadProgress(FileLoadOperation operation, final float progress) {
if (operation.state != 2) {
fileProgresses.put(arg1, progress);
}
long currentTime = System.currentTimeMillis();
if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 500) {
lastProgressUpdateTime = currentTime;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileLoadProgressChanged, arg1, progress);
}
});
}
}
};
if (currentLoadOperationsCount < 2) {
currentLoadOperationsCount++;
operation.start();
} else {
loadOperationQueue.add(operation);
}
}
});
}
Bitmap imageFromKey(String key) {
if (key == null) {
return null;
}
return memCache.get(key);
}
public void clearMemory() {
memCache.evictAll();
}
public void cleanDisk(boolean all) {
/*if (all) {
[cacheInQueue cancelAllOperations];
[[NSFileManager defaultManager] removeItemAtPath:diskCachePath error:nil];
[[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
} else {
NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:-cacheMaxCacheAge];
NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:diskCachePath];
for (NSString *fileName in fileEnumerator) {
NSString *filePath = [diskCachePath stringByAppendingPathComponent:fileName];
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
if ([[[attrs fileModificationDate] laterDate:expirationDate] isEqualToDate:expirationDate]) {
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
}
}
}*/
}
public void cancelLoadingForImageView(final View imageView) {
if (imageView == null) {
return;
}
Utilities.imageLoadQueue.postRunnable(new Runnable() {
@Override
public void run() {
Integer num = (Integer)imageView.getTag(R.string.CacheTag);
if (num == null) {
num = lastImageNum;
imageView.setTag(R.string.CacheTag, num);
lastImageNum++;
if (lastImageNum == Integer.MAX_VALUE) {
lastImageNum = 0;
}
}
CacheImage ei = imageLoadingByKeys.get(num);
if (ei != null) {
imageLoadingByKeys.remove(num);
ei.removeImageView(imageView);
if (ei.imageViewArray.size() == 0) {
checkOperationsAndClear(ei.loadOperation);
ei.cancelAndClear();
imageLoading.remove(ei.key);
}
}
}
});
}
public Bitmap getImageFromMemory(TLRPC.FileLocation url, View imageView, String filter, boolean cancel) {
return getImageFromMemory(url, null, imageView, filter, cancel);
}
public Bitmap getImageFromMemory(String url, View imageView, String filter, boolean cancel) {
return getImageFromMemory(null, url, imageView, filter, cancel);
}
public Bitmap getImageFromMemory(TLRPC.FileLocation url, String httpUrl, View imageView, String filter, boolean cancel) {
if ((url == null && httpUrl == null) || imageView == null)
return null;
String key;
if (httpUrl != null) {
key = Utilities.MD5(httpUrl);
} else if (filter == null) {
key = url.volume_id + "_" + url.local_id;
} else {
key = url.volume_id + "_" + url.local_id + "@" + filter;
}
Bitmap img = imageFromKey(key);
if (img != null && cancel) {
cancelLoadingForImageView(imageView);
}
return img;
}
private void performReplace(String oldKey, String newKey) {
Bitmap b = memCache.get(oldKey);
if (b != null) {
ignoreRemoval = oldKey;
memCache.remove(oldKey);
memCache.put(newKey, b);
ignoreRemoval = null;
}
Integer val = BitmapUseCounts.get(oldKey);
if (val != null) {
BitmapUseCounts.put(newKey, val);
BitmapUseCounts.remove(oldKey);
}
}
public void replaceImageInCache(final String oldKey, final String newKey) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
ArrayList<String> arr = memCache.getFilterKeys(oldKey);
if (arr != null) {
for (String filter : arr) {
performReplace(oldKey + "@" + filter, newKey + "@" + filter);
}
} else {
performReplace(oldKey, newKey);
}
}
});
}
public void loadImage(final String url, final View imageView, final String filter, final boolean cancel) {
loadImage(null, url, imageView, filter, cancel);
}
public void loadImage(final TLRPC.FileLocation url, final View imageView, final String filter, final boolean cancel) {
loadImage(url, null, imageView, filter, cancel);
}
public void loadImage(final TLRPC.FileLocation url, final String httpUrl, final View imageView, final String filter, final boolean cancel) {
if ((url == null && httpUrl == null) || imageView == null || (url != null && !(url instanceof TLRPC.TL_fileLocation) && !(url instanceof TLRPC.TL_fileEncryptedLocation))) {
return;
}
Utilities.imageLoadQueue.postRunnable(new Runnable() {
@Override
public void run() {
String key;
if (httpUrl != null) {
key = Utilities.MD5(httpUrl);
} else if (filter == null) {
key = url.volume_id + "_" + url.local_id;
} else {
key = url.volume_id + "_" + url.local_id + "@" + filter;
}
Integer num = (Integer)imageView.getTag(R.string.CacheTag);
if (num == null) {
num = lastImageNum;
imageView.setTag(R.string.CacheTag, num);
lastImageNum++;
if (lastImageNum == Integer.MAX_VALUE)
lastImageNum = 0;
}
boolean added = false;
boolean addToByKeys = true;
CacheImage alreadyLoadingImage = imageLoading.get(key);
if (cancel) {
CacheImage ei = imageLoadingByKeys.get(num);
if (ei != null) {
if (ei != alreadyLoadingImage) {
ei.removeImageView(imageView);
if (ei.imageViewArray.size() == 0) {
checkOperationsAndClear(ei.loadOperation);
ei.cancelAndClear();
imageLoading.remove(ei.key);
}
} else {
addToByKeys = false;
added = true;
}
}
}
if (alreadyLoadingImage != null && addToByKeys) {
alreadyLoadingImage.addImageView(imageView);
imageLoadingByKeys.put(num, alreadyLoadingImage);
added = true;
}
if (!added) {
final CacheImage img = new CacheImage();
img.key = key;
img.addImageView(imageView);
imageLoadingByKeys.put(num, img);
imageLoading.put(key, img);
final String arg2 = key;
FileLoadOperation loadOperation;
if (httpUrl != null) {
loadOperation = new FileLoadOperation(httpUrl);
} else {
loadOperation = new FileLoadOperation(url);
}
loadOperation.filter = filter;
loadOperation.delegate = new FileLoadOperation.FileLoadOperationDelegate() {
@Override
public void didFinishLoadingFile(final FileLoadOperation operation) {
enqueueImageProcessingOperationWithImage(operation.image, filter, arg2, img);
}
@Override
public void didFailedLoadingFile(final FileLoadOperation operation) {
if (url != null) {
if (url.volume_id != 0 && url.local_id != 0) {
fileProgresses.remove(url.volume_id + "_" + url.local_id + ".jpg");
}
}
Utilities.imageLoadQueue.postRunnable(new Runnable() {
@Override
public void run() {
for (View view : img.imageViewArray) {
Integer num = (Integer)view.getTag(R.string.CacheTag);
imageLoadingByKeys.remove(num);
imageLoading.remove(arg2);
checkOperationsAndClear(operation);
}
}
});
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
img.callAndClear(null);
}
});
}
@Override
public void didChangedLoadProgress(FileLoadOperation operation, float progress) {
if (url != null) {
if (url.volume_id != 0 && url.local_id != 0) {
fileProgresses.put(url.volume_id + "_" + url.local_id + ".jpg", progress);
}
}
}
};
img.loadOperation = loadOperation;
if (runningOperation.size() < maxConcurentLoadingOpertaionsCount) {
loadOperation.start();
runningOperation.add(loadOperation);
} else {
operationsQueue.add(loadOperation);
}
}
}
});
}
private void checkOperationsAndClear(FileLoadOperation operation) {
operationsQueue.remove(operation);
runningOperation.remove(operation);
while (runningOperation.size() < maxConcurentLoadingOpertaionsCount && operationsQueue.size() != 0) {
FileLoadOperation loadOperation = operationsQueue.poll();
runningOperation.add(loadOperation);
loadOperation.start();
}
}
public void processImage(Bitmap image, View imageView, String filter, boolean cancel) {
if (filter == null || imageView == null) {
return;
}
Integer num = (Integer)imageView.getTag(R.string.CacheTag);
if (num == null) {
num = lastImageNum;
imageView.setTag(R.string.CacheTag, num);
lastImageNum++;
if (lastImageNum == Integer.MAX_VALUE)
lastImageNum = 0;
}
boolean added = false;
boolean addToByKeys = true;
CacheImage alreadyLoadingImage = imageLoading.get(filter);
if (cancel) {
CacheImage ei = imageLoadingByKeys.get(num);
if (ei != null) {
if (ei != alreadyLoadingImage) {
ei.removeImageView(imageView);
if (ei.imageViewArray.size() == 0) {
checkOperationsAndClear(ei.loadOperation);
ei.cancelAndClear();
imageLoading.remove(ei.key);
}
} else {
addToByKeys = false;
added = true;
}
}
}
if (alreadyLoadingImage != null && addToByKeys) {
alreadyLoadingImage.addImageView(imageView);
imageLoadingByKeys.put(num, alreadyLoadingImage);
added = true;
}
if (!added) {
CacheImage img = new CacheImage();
img.key = filter;
img.addImageView(imageView);
imageLoadingByKeys.put(num, img);
imageLoading.put(filter, img);
enqueueImageProcessingOperationWithImage(image, filter, filter, img);
}
}
void enqueueImageProcessingOperationWithImage(final Bitmap image, final String filter, final String key, final CacheImage img) {
if (image == null || key == null) {
return;
}
Utilities.imageLoadQueue.postRunnable(new Runnable() {
@Override
public void run() {
for (View v : img.imageViewArray) {
Integer num = (Integer)v.getTag(R.string.CacheTag);
imageLoadingByKeys.remove(num);
}
checkOperationsAndClear(img.loadOperation);
imageLoading.remove(key);
}
});
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
img.callAndClear(image);
if (memCache.get(key) == null) {
memCache.put(key, image);
}
}
});
}
/*AsyncTask
NSBlockOperation *processingOperation = [NSBlockOperation blockOperationWithBlock:^(void) {
if (countCores() == 1)
[NSThread sleepForTimeInterval:0.1];
UIImage *filterImage = [UIImage decodedImageWithImage:image andFilter:filter];
if (!filterImage)
filterImage = image;
dispatch_async(dispatch_get_main_queue(), ^{
if (filterImage) {
if (![memCache objectForKey:key]) {
[memCache setObject:filterImage forKey:key];
[memArray addObject:key];
}
}
for (UIView *view in img.imageViewArray) {
NSNumber *num = objc_getAssociatedObject(view, &VIEW_CACHE_KEY);
[imageLoadingByKeys removeObjectForKey:num];
}
[img callAndClear:filterImage];
[imageLoading removeObjectForKey:key];
});
}];
[imageProcessingQueue addOperation:processingOperation];
*/
public static Bitmap loadBitmap(String path, float maxWidth, float maxHeight) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, bmOptions);
float photoW = bmOptions.outWidth;
float photoH = bmOptions.outHeight;
float scaleFactor = Math.max(photoW / maxWidth, photoH / maxHeight);
if (scaleFactor < 1) {
scaleFactor = 1;
}
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = (int)scaleFactor;
ExifInterface exif;
Matrix matrix = null;
try {
exif = new ExifInterface(path);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
break;
}
} catch (Exception e) {
e.printStackTrace();
}
Bitmap b;
try {
b = BitmapFactory.decodeFile(path, bmOptions);
if (b != null && matrix != null) {
b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
}
} catch (Exception e) {
e.printStackTrace();
FileLoader.Instance.memCache.evictAll();
b = BitmapFactory.decodeFile(path, bmOptions);
if (b != null && matrix != null) {
b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
}
}
return b;
}
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache) {
if (bitmap == null) {
return null;
}
float photoW = bitmap.getWidth();
float photoH = bitmap.getHeight();
if (photoW == 0 || photoH == 0) {
return null;
}
float scaleFactor = Math.max(photoW / maxWidth, photoH / maxHeight);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int)(photoW / scaleFactor), (int)(photoH / scaleFactor), true);
TLRPC.TL_fileLocation location = new TLRPC.TL_fileLocation();
location.volume_id = Integer.MIN_VALUE;
location.dc_id = Integer.MIN_VALUE;
location.local_id = UserConfig.lastLocalId;
UserConfig.lastLocalId--;
TLRPC.PhotoSize size;
if (!cache) {
size = new TLRPC.TL_photoSize();
} else {
size = new TLRPC.TL_photoCachedSize();
}
size.location = location;
size.w = (int)(photoW / scaleFactor);
size.h = (int)(photoH / scaleFactor);
try {
if (!cache) {
String fileName = location.volume_id + "_" + location.local_id + ".jpg";
final File cacheFile = new File(Utilities.getCacheDir(), fileName);
FileOutputStream stream = new FileOutputStream(cacheFile);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream);
size.size = (int)stream.getChannel().size();
} else {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream);
size.bytes = stream.toByteArray();
size.size = size.bytes.length;
}
if (scaledBitmap != bitmap) {
scaledBitmap.recycle();
}
return size;
} catch (Exception e) {
return null;
}
}
}

View file

@ -0,0 +1,170 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;
public class FileUploadOperation {
private final int uploadChunkSize = 1024 * 32;
private String uploadingFilePath;
public int state = 0;
private byte[] readBuffer = new byte[uploadChunkSize];
public FileUploadOperationDelegate delegate;
private long requestToken = 0;
private int currentPartNum = 0;
private long currentFileId;
private boolean isLastPart = false;
private long totalFileSize = 0;
private long currentUploaded = 0;
private byte[] key;
private byte[] iv;
private int fingerprint;
FileInputStream stream;
MessageDigest mdEnc = null;
public static interface FileUploadOperationDelegate {
public abstract void didFinishUploadingFile(FileUploadOperation operation, TLRPC.TL_inputFile inputFile, TLRPC.TL_inputEncryptedFileUploaded inputEncryptedFile);
public abstract void didFailedUploadingFile(FileUploadOperation operation);
public abstract void didChangedUploadProgress(FileUploadOperation operation, float progress);
}
public FileUploadOperation(String location, byte[] keyarr, byte[] ivarr) {
uploadingFilePath = location;
if (ivarr != null && keyarr != null) {
iv = new byte[32];
key = keyarr;
System.arraycopy(ivarr, 0, iv, 0, 32);
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] arr = new byte[64];
System.arraycopy(key, 0, arr, 0, 32);
System.arraycopy(iv, 0, arr, 32, 32);
byte[] digest = md.digest(arr);
byte[] fingerprintBytes = new byte[4];
for (int a = 0; a < 4; a++) {
fingerprintBytes[a] = (byte)(digest[a] ^ digest[a + 4]);
}
fingerprint = Utilities.bytesToInt(fingerprintBytes);
} catch (Exception e) {
e.printStackTrace();
}
}
currentFileId = (long)(MessagesController.random.nextDouble() * Long.MAX_VALUE);
try {
mdEnc = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public void start() {
if (state != 0) {
return;
}
state = 1;
startUploadRequest();
}
public void cancel() {
if (state != 1) {
return;
}
state = 2;
if (requestToken != 0) {
ConnectionsManager.Instance.cancelRpc(requestToken, true);
}
delegate.didFailedUploadingFile(this);
}
private void startUploadRequest() {
if (state != 1) {
return;
}
TLRPC.TL_upload_saveFilePart req = new TLRPC.TL_upload_saveFilePart();
req.file_part = currentPartNum;
req.file_id = currentFileId;
try {
if (stream == null) {
File cacheFile = new File(uploadingFilePath);
stream = new FileInputStream(cacheFile);
totalFileSize = cacheFile.length();
}
int readed = stream.read(readBuffer);
int toAdd = 0;
if (key != null && readed % 16 != 0) {
toAdd += 16 - readed % 16;
}
byte[] sendBuffer = new byte[readed + toAdd];
if (readed != uploadChunkSize) {
isLastPart = true;
}
System.arraycopy(readBuffer, 0, sendBuffer, 0, readed);
if (key != null) {
sendBuffer = Utilities.aesIgeEncryption(sendBuffer, key, iv, true, true);
}
mdEnc.update(sendBuffer, 0, readed + toAdd);
req.bytes = sendBuffer;
currentUploaded += readed;
} catch (Exception e) {
e.printStackTrace();
delegate.didFailedUploadingFile(this);
return;
}
requestToken = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
requestToken = 0;
if (error == null) {
if (response instanceof TLRPC.TL_boolTrue) {
currentPartNum++;
delegate.didChangedUploadProgress(FileUploadOperation.this, (float)currentUploaded / (float)totalFileSize);
if (isLastPart) {
state = 3;
if (key == null) {
TLRPC.TL_inputFile result = new TLRPC.TL_inputFile();
result.md5_checksum = String.format(Locale.US, "%32s", new BigInteger(1, mdEnc.digest()).toString(16)).replace(' ', '0');
result.parts = currentPartNum;
result.id = currentFileId;
result.name = uploadingFilePath.substring(uploadingFilePath.lastIndexOf("/") + 1);
delegate.didFinishUploadingFile(FileUploadOperation.this, result, null);
} else {
TLRPC.TL_inputEncryptedFileUploaded result = new TLRPC.TL_inputEncryptedFileUploaded();
result.md5_checksum = String.format(Locale.US, "%32s", new BigInteger(1, mdEnc.digest()).toString(16)).replace(' ', '0');
result.parts = currentPartNum;
result.id = currentFileId;
result.key_fingerprint = fingerprint;
delegate.didFinishUploadingFile(FileUploadOperation.this, null, result);
}
} else {
startUploadRequest();
}
} else {
delegate.didFailedUploadingFile(FileUploadOperation.this);
}
} else {
delegate.didFailedUploadingFile(FileUploadOperation.this);
}
}
}, new RPCRequest.RPCProgressDelegate() {
@Override
public void progress(int length, int progress) {
}
}, null, true, RPCRequest.RPCRequestClassUploadMedia, ConnectionsManager.DEFAULT_DATACENTER_ID);
}
}

View file

@ -0,0 +1,233 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import org.json.JSONObject;
import org.telegram.TL.TLRPC;
import org.telegram.ui.ApplicationLoader;
import org.telegram.ui.LaunchActivity;
public class GcmBroadcastReceiver extends BroadcastReceiver {
public static final int NOTIFICATION_ID = 1;
@Override
public void onReceive(final Context context, final Intent intent) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.i("tmessages", "GCM received intent: " + intent);
}
setResultCode(Activity.RESULT_OK);
if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
SharedPreferences preferences = context.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
boolean globalEnabled = preferences.getBoolean("EnableAll", true);
if (!globalEnabled) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.i("tmessages", "GCM disabled");
}
return;
}
Thread thread = new Thread(new Runnable() {
public void run() {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String messageType = gcm.getMessageType(intent);
sendNotification(context, intent.getExtras());
}
});
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
} else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
if (ConnectionsManager.DEBUG_VERSION) {
String registration = intent.getStringExtra("registration_id");
if (intent.getStringExtra("error") != null) {
Log.e("tmessages", "Registration failed, should try again later.");
} else if (intent.getStringExtra("unregistered") != null) {
Log.e("tmessages", "unregistration done, new messages from the authorized sender will be rejected");
} else if (registration != null) {
Log.e("tmessages", "registration id = " + registration);
}
}
}
}
private void sendNotification(Context context, Bundle extras) {
if (!UserConfig.clientActivated || context == null || extras == null) {
return;
}
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "received push " + extras);
}
SharedPreferences preferences = context.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
boolean groupEnabled = preferences.getBoolean("EnableGroup", true);
boolean globalVibrate = preferences.getBoolean("EnableVibrateAll", true);
boolean groupVibrate = preferences.getBoolean("EnableVibrateGroup", true);
if (ApplicationLoader.Instance != null && (ApplicationLoader.lastPauseTime == 0 || ApplicationLoader.lastPauseTime > System.currentTimeMillis() - 200)) {
return;
}
String defaultPath = null;
Uri defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI;
if (defaultUri != null) {
defaultPath = defaultUri.getPath();
}
String globalSound = preferences.getString("GlobalSoundPath", defaultPath);
String chatSound = preferences.getString("GroupSoundPath", defaultPath);
String userSoundPath = null;
String chatSoundPath = null;
NotificationManager mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(context, LaunchActivity.class);
String msg = extras.getString("message");
try {
String to_id = extras.getString("user_id");
int to = Integer.parseInt(to_id);
if (to != UserConfig.clientUserId) {
return;
}
} catch (Exception e) {
e.printStackTrace();
}
int chat_id = 0;
int user_id = 0;
TLRPC.User user = null;
TLRPC.Chat chat = null;
String custom = extras.getString("custom");
try {
if (custom != null) {
JSONObject obj = new JSONObject(custom);
if (obj.has("chat_id")) {
Object object = obj.get("chat_id");
if (object instanceof Integer) {
chat_id = (Integer)object;
} else if (object instanceof String) {
chat_id = Integer.parseInt((String)object);
}
if (chat_id != 0) {
intent.putExtra("chatId", chat_id);
}
} else if (obj.has("from_id")) {
Object object = obj.get("from_id");
if (object instanceof Integer) {
user_id = (Integer)object;
} else if (object instanceof String) {
user_id = Integer.parseInt((String)object);
}
if (user_id != 0) {
intent.putExtra("userId", user_id);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (user_id != 0) {
String key = "notify_" + user_id;
boolean value = preferences.getBoolean(key, true);
if (!value) {
return;
}
userSoundPath = preferences.getString("sound_path_" + user_id, null);
}
if (chat_id != 0) {
if (!groupEnabled) {
return;
}
String key = "notify_" + (-chat_id);
boolean value = preferences.getBoolean(key, true);
if (!value) {
return;
}
chatSoundPath = preferences.getString("sound_chat_path_" + chat_id, null);
}
boolean needVibrate;
boolean needPreview = true;
String choosenSoundPath = null;
if (chat_id != 0) {
needVibrate = groupVibrate;
} else {
needVibrate = globalVibrate;
}
if (user_id != 0) {
if (userSoundPath != null) {
choosenSoundPath = userSoundPath;
} else if (globalSound != null) {
choosenSoundPath = globalSound;
}
} else if (chat_id != 0) {
if (chatSoundPath != null) {
choosenSoundPath = chatSoundPath;
} else if (chatSound != null) {
choosenSoundPath = chatSound;
}
}
intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
//intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setContentTitle(Utilities.applicationContext.getString(R.string.AppName))
.setSmallIcon(R.drawable.notification)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg)
.setAutoCancel(true);
if (needPreview) {
mBuilder.setTicker(msg);
}
if (needVibrate) {
mBuilder.setVibrate(new long[]{0, 100, 0, 100});
}
if (choosenSoundPath != null && !choosenSoundPath.equals("NoSound")) {
if (choosenSoundPath.equals(defaultPath)) {
mBuilder.setSound(defaultUri);
} else {
mBuilder.setSound(Uri.parse(choosenSoundPath));
}
}
mBuilder.setContentIntent(contentIntent);
mNotificationManager.cancel(NOTIFICATION_ID);
Notification notification = mBuilder.build();
notification.ledARGB = 0xff00ff00;
notification.ledOnMS = 1000;
notification.ledOffMS = 1000;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
mNotificationManager.notify(NOTIFICATION_ID, notification);
}
}

View file

@ -0,0 +1,573 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.util.Log;
import org.telegram.TL.TLClassStore;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
public class HandshakeAction extends Action implements TcpConnection.TcpConnectionDelegate {
private ArrayList<Long> processedMessageIds;
private byte[] authNonce;
private byte[] authServerNonce;
private byte[] authNewNonce;
private byte[] authKey;
private byte[] authKeyId;
private boolean processedPQRes;
private byte[] reqPQMsgData;
private byte[] reqDHMsgData;
private byte[] setClientDHParamsMsgData;
private boolean wasDisconnect = false;
private long lastOutgoingMessageId;
int timeDifference;
ServerSalt serverSalt;
public Datacenter datacenter;
public HandshakeAction(Datacenter datacenter) {
this.datacenter = datacenter;
}
public void execute(HashMap params) {
Log.d("tmessages", String.format("Begin handshake with DC%d", datacenter.datacenterId));
beginHandshake(true);
}
void beginHandshake(boolean dropConnection) {
if (datacenter.connection == null) {
datacenter.connection = new TcpConnection(datacenter.address, datacenter.port);
datacenter.connection.delegate = this;
datacenter.connection.datacenterId = datacenter.datacenterId;
datacenter.connection.transportRequestClass = RPCRequest.RPCRequestClassGeneric;
}
processedMessageIds = new ArrayList<Long>();
authNonce = null;
authServerNonce = null;
authNewNonce = null;
authKey = null;
authKeyId = null;
processedPQRes = false;
reqPQMsgData = null;
reqDHMsgData = null;
setClientDHParamsMsgData = null;
if (dropConnection) {
datacenter.connection.suspendConnection(true);
datacenter.connection.connect();
}
TLRPC.TL_req_pq reqPq = new TLRPC.TL_req_pq();
byte[] nonceBytes = new byte[16];
for (int a = 0; a < 16; a++) {
nonceBytes[a] = (byte)(MessagesController.random.nextDouble() * 255);
}
authNonce = reqPq.nonce = nonceBytes;
reqPQMsgData = sendMessageData(reqPq, generateMessageId());
}
final Integer lock = 1;
static ArrayList<HashMap<String, Object>> serverPublicKeys = null;
HashMap<String, Object> selectPublicKey(ArrayList<Long> fingerprints) {
synchronized (lock) {
if (serverPublicKeys == null) {
serverPublicKeys = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> map;
map = new HashMap<String, Object>();
map.put("key", new BigInteger[]{
new BigInteger("c150023e2f70db7985ded064759cfecf0af328e69a41daf4d6f01b538135" +
"a6f91f8f8b2a0ec9ba9720ce352efcf6c5680ffc424bd634864902de0b4bd6d49f4e580230e" +
"3ae97d95c8b19442b3c0a10d8f5633fecedd6926a7f6dab0ddb7d457f9ea81b8465fcd6fffe" +
"ed114011df91c059caedaf97625f6c96ecc74725556934ef781d866b34f011fce4d835a0901" +
"96e9a5f0e4449af7eb697ddb9076494ca5f81104a305b6dd27665722c46b60e5df680fb16b2" +
"10607ef217652e60236c255f6a28315f4083a96791d7214bf64c1df4fd0db1944fb26a2a570" +
"31b32eee64ad15a8ba68885cde74a5bfc920f6abf59ba5c75506373e7130f9042da922179251f", 16),
new BigInteger("010001", 16)});
map.put("fingerprint", 0xc3b42b026ce86b21L);
serverPublicKeys.add(map);
}
}
for (HashMap<String, Object> keyDesc : serverPublicKeys) {
long keyFingerprint = (Long)keyDesc.get("fingerprint");
for (long nFingerprint : fingerprints) {
if (nFingerprint == keyFingerprint) {
return keyDesc;
}
}
}
return null;
}
long generateMessageId() {
long messageId = (long)((((double)System.currentTimeMillis()) * 4294967296.0) / 1000.0);
if (messageId <= lastOutgoingMessageId) {
messageId = lastOutgoingMessageId + 1;
}
while (messageId % 4 != 0) {
messageId++;
}
lastOutgoingMessageId = messageId;
return messageId;
}
byte[] sendMessageData(TLObject message, long messageId) {
byte[] messageData;
SerializedData innerOs = new SerializedData();
message.serializeToStream(innerOs);
messageData = innerOs.toByteArray();
SerializedData messageOs = new SerializedData();
messageOs.writeInt64(0);
messageOs.writeInt64(messageId);
messageOs.writeInt32(messageData.length);
messageOs.writeRaw(messageData);
byte[] transportData = messageOs.toByteArray();
datacenter.connection.sendData(transportData, false, false);
return transportData;
}
void processMessage(TLObject message, long messageId) {
if (message instanceof TLRPC.TL_resPQ) {
if (processedPQRes) {
TLRPC.TL_msgs_ack msgsAck = new TLRPC.TL_msgs_ack();
msgsAck.msg_ids = new ArrayList<Long>();
msgsAck.msg_ids.add(messageId);
sendMessageData(msgsAck, generateMessageId());
return;
}
processedPQRes = true;
final TLRPC.TL_resPQ resPq = (TLRPC.TL_resPQ)message;
if (Arrays.equals(authNonce, resPq.nonce)) {
final HashMap<String, Object> publicKey = selectPublicKey(resPq.server_public_key_fingerprints);
if (publicKey == null) {
Log.e("tmessages", "***** Couldn't find valid server public key");
beginHandshake(false);
return;
}
authServerNonce = resPq.server_nonce;
ByteBuffer data = ByteBuffer.wrap(resPq.pq);
final long pqf = data.getLong();
final long messageIdf = messageId;
Utilities.globalQueue.postRunnable(new Runnable() {
@Override
public void run() {
final Utilities.TPFactorizedValue factorizedPq = Utilities.getFactorizedValue(pqf);
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
ByteBuffer pBytes = ByteBuffer.allocate(4);
pBytes.putInt((int)factorizedPq.p);
byte[] pData = pBytes.array();
ByteBuffer qBytes = ByteBuffer.allocate(4);
qBytes.putInt((int)factorizedPq.q);
byte[] qData = qBytes.array();
TLRPC.TL_req_DH_params reqDH = new TLRPC.TL_req_DH_params();
reqDH.nonce = authNonce;
reqDH.server_nonce = authServerNonce;
reqDH.p = pData;
reqDH.q = qData;
reqDH.public_key_fingerprint = (Long)publicKey.get("fingerprint");
SerializedData os = new SerializedData();
TLRPC.TL_p_q_inner_data innerData = new TLRPC.TL_p_q_inner_data();
innerData.nonce = authNonce;
innerData.server_nonce = authServerNonce;
innerData.pq = resPq.pq;
innerData.p = reqDH.p;
innerData.q = reqDH.q;
byte[] nonceBytes = new byte[32];
for (int a = 0; a < 32; a++) {
nonceBytes[a] = (byte)(MessagesController.random.nextDouble() * 255);
}
innerData.new_nonce = authNewNonce = nonceBytes;
innerData.serializeToStream(os);
byte[] innerDataBytes = os.toByteArray();
SerializedData dataWithHash = new SerializedData();
dataWithHash.writeRaw(Utilities.computeSHA1(innerDataBytes));
dataWithHash.writeRaw(innerDataBytes);
while (dataWithHash.length() < 255) {
dataWithHash.writeByte(0);
}
byte[] encryptedBytes = Utilities.encryptWithRSA((BigInteger[])publicKey.get("key"), dataWithHash.toByteArray());
SerializedData encryptedData = new SerializedData();
encryptedData.writeRaw(encryptedBytes);
if (encryptedData.length() < 256) {
SerializedData newEncryptedData = new SerializedData();
for (int i = 0; i < 256 - encryptedData.length(); i++) {
newEncryptedData.writeByte(0);
}
newEncryptedData.writeRaw(encryptedData.toByteArray());
encryptedData = newEncryptedData;
}
reqDH.encrypted_data = encryptedData.toByteArray();
TLRPC.TL_msgs_ack msgsAck = new TLRPC.TL_msgs_ack();
msgsAck.msg_ids = new ArrayList<Long>();
msgsAck.msg_ids.add(messageIdf);
sendMessageData(msgsAck, generateMessageId());
reqPQMsgData = null;
reqDHMsgData = sendMessageData(reqDH, generateMessageId());
}
});
}
});
} else {
Log.e("tmessages", "***** Error: invalid handshake nonce");
beginHandshake(false);
}
} else if (message instanceof TLRPC.Server_DH_Params) {
if (message instanceof TLRPC.TL_server_DH_params_ok) {
TLRPC.TL_server_DH_params_ok serverDhParams = (TLRPC.TL_server_DH_params_ok)message;
SerializedData tmpAesKey = new SerializedData();
SerializedData newNonceAndServerNonce = new SerializedData();
newNonceAndServerNonce.writeRaw(authNewNonce);
newNonceAndServerNonce.writeRaw(authServerNonce);
SerializedData serverNonceAndNewNonce = new SerializedData();
serverNonceAndNewNonce.writeRaw(authServerNonce);
serverNonceAndNewNonce.writeRaw(authNewNonce);
tmpAesKey.writeRaw(Utilities.computeSHA1(newNonceAndServerNonce.toByteArray()));
byte[] serverNonceAndNewNonceHash = Utilities.computeSHA1(serverNonceAndNewNonce.toByteArray());
byte[] serverNonceAndNewNonceHash0_12 = new byte[12];
System.arraycopy(serverNonceAndNewNonceHash, 0, serverNonceAndNewNonceHash0_12, 0, 12);
tmpAesKey.writeRaw(serverNonceAndNewNonceHash0_12);
SerializedData tmpAesIv = new SerializedData();
byte[] serverNonceAndNewNonceHash12_8 = new byte[8];
System.arraycopy(serverNonceAndNewNonceHash, 12, serverNonceAndNewNonceHash12_8, 0, 8);
tmpAesIv.writeRaw(serverNonceAndNewNonceHash12_8);
SerializedData newNonceAndNewNonce = new SerializedData();
newNonceAndNewNonce.writeRaw(authNewNonce);
newNonceAndNewNonce.writeRaw(authNewNonce);
tmpAesIv.writeRaw(Utilities.computeSHA1(newNonceAndNewNonce.toByteArray()));
byte[] newNonce0_4 = new byte[4];
System.arraycopy(authNewNonce, 0, newNonce0_4, 0, 4);
tmpAesIv.writeRaw(newNonce0_4);
byte[] answerWithHash = Utilities.aesIgeEncryption(serverDhParams.encrypted_answer, tmpAesKey.toByteArray(), tmpAesIv.toByteArray(), false, false);
byte[] answerHash = new byte[20];
System.arraycopy(answerWithHash, 0, answerHash, 0, 20);
byte[] answerData = new byte[answerWithHash.length - 20];
System.arraycopy(answerWithHash, 20, answerData, 0, answerWithHash.length - 20);
boolean hashVerified = false;
for (int i = 0; i < 16; i++) {
byte[] computedAnswerHash = Utilities.computeSHA1(answerData);
if (Arrays.equals(computedAnswerHash, answerHash)) {
hashVerified = true;
break;
}
byte[] answerData2 = new byte[answerData.length - 1];
System.arraycopy(answerData, 0, answerData2, 0, answerData.length - 1);
answerData = answerData2;
}
if (!hashVerified) {
Log.e("tmessages", "***** Couldn't decode DH params");
beginHandshake(false);
return;
}
SerializedData answerIs = new SerializedData(answerData);
int constructor = answerIs.readInt32();
TLRPC.TL_server_DH_inner_data dhInnerData = (TLRPC.TL_server_DH_inner_data)TLClassStore.Instance().TLdeserialize(answerIs, constructor);
if (!(dhInnerData instanceof TLRPC.TL_server_DH_inner_data)) {
Log.e("tmessages", "***** Couldn't parse decoded DH params");
beginHandshake(false);
return;
}
if (!Arrays.equals(authNonce, dhInnerData.nonce)) {
Log.e("tmessages", "***** Invalid DH nonce");
beginHandshake(false);
return;
}
if (!Arrays.equals(authServerNonce, dhInnerData.server_nonce)) {
Log.e("tmessages", "***** Invalid DH server nonce");
beginHandshake(false);
return;
}
byte[] b = new byte[256];
for (int a = 0; a < 256; a++) {
b[a] = (byte)(MessagesController.random.nextDouble() * 255);
}
BigInteger i_g_b = BigInteger.valueOf(dhInnerData.g);
i_g_b = i_g_b.modPow(new BigInteger(1, b), new BigInteger(1, dhInnerData.dh_prime));
byte[] g_b = i_g_b.toByteArray();
BigInteger i_authKey = new BigInteger(1, dhInnerData.g_a);
i_authKey = i_authKey.modPow(new BigInteger(1, b), new BigInteger(1, dhInnerData.dh_prime));
authKey = i_authKey.toByteArray();
if (authKey.length > 256) {
byte[] correctedAuth = new byte[256];
System.arraycopy(authKey, 1, correctedAuth, 0, 256);
authKey = correctedAuth;
} else if (authKey.length < 256) {
byte[] correctedAuth = new byte[256];
System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length);
for (int a = 0; a < 256 - authKey.length; a++) {
authKey[a] = 0;
}
authKey = correctedAuth;
}
byte[] authKeyHash = Utilities.computeSHA1(authKey);
authKeyId = new byte[8];
System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8);
SerializedData serverSaltData = new SerializedData();
for (int i = 7; i >= 0; i--) {
byte a_ = authNewNonce[i];
byte b_ = authServerNonce[i];
byte x = (byte)(a_ ^ b_);
serverSaltData.writeByte(x);
}
ByteBuffer saltBuffer = ByteBuffer.wrap(serverSaltData.toByteArray());
timeDifference = dhInnerData.server_time - (int)(System.currentTimeMillis() / 1000);
serverSalt = new ServerSalt();
serverSalt.validSince = (int)(System.currentTimeMillis() / 1000) + timeDifference;
serverSalt.validUntil = (int)(System.currentTimeMillis() / 1000) + timeDifference + 30 * 60;
serverSalt.value = saltBuffer.getLong();
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", String.format(Locale.US, "===== Time difference: %d", timeDifference));
}
TLRPC.TL_client_DH_inner_data clientInnerData = new TLRPC.TL_client_DH_inner_data();
clientInnerData.nonce = authNonce;
clientInnerData.server_nonce = authServerNonce;
clientInnerData.g_b = g_b;
clientInnerData.retry_id = 0;
SerializedData os = new SerializedData();
clientInnerData.serializeToStream(os);
byte[] clientInnerDataBytes = os.toByteArray();
SerializedData clientDataWithHash = new SerializedData();
clientDataWithHash.writeRaw(Utilities.computeSHA1(clientInnerDataBytes));
clientDataWithHash.writeRaw(clientInnerDataBytes);
while (clientDataWithHash.length() % 16 != 0) {
clientDataWithHash.writeByte(0);
}
TLRPC.TL_set_client_DH_params setClientDhParams = new TLRPC.TL_set_client_DH_params();
setClientDhParams.nonce = authNonce;
setClientDhParams.server_nonce = authServerNonce;
setClientDhParams.encrypted_data = Utilities.aesIgeEncryption(clientDataWithHash.toByteArray(), tmpAesKey.toByteArray(), tmpAesIv.toByteArray(), true, false);
TLRPC.TL_msgs_ack msgsAck = new TLRPC.TL_msgs_ack();
msgsAck.msg_ids = new ArrayList<Long>();
msgsAck.msg_ids.add(messageId);
sendMessageData(msgsAck, generateMessageId());
reqDHMsgData = null;
setClientDHParamsMsgData = sendMessageData(setClientDhParams, generateMessageId());
} else {
Log.e("tmessages", "***** Couldn't set DH params");
beginHandshake(false);
}
} else if (message instanceof TLRPC.Set_client_DH_params_answer) {
TLRPC.Set_client_DH_params_answer dhAnswer = (TLRPC.Set_client_DH_params_answer)message;
if (!Arrays.equals(authNonce, dhAnswer.nonce)) {
Log.e("tmessages", "***** Invalid DH answer nonce");
beginHandshake(false);
return;
}
if (!Arrays.equals(authServerNonce, dhAnswer.server_nonce)) {
Log.e("tmessages", "***** Invalid DH answer server nonce");
beginHandshake(false);
return;
}
reqDHMsgData = null;
TLRPC.TL_msgs_ack msgsAck = new TLRPC.TL_msgs_ack();
msgsAck.msg_ids = new ArrayList<Long>();
msgsAck.msg_ids.add(messageId);
sendMessageData(msgsAck, generateMessageId());
byte[] authKeyAuxHashFull = Utilities.computeSHA1(authKey);
byte[] authKeyAuxHash = new byte[8];
System.arraycopy(authKeyAuxHashFull, 0, authKeyAuxHash, 0, 8);
SerializedData newNonce1 = new SerializedData();
newNonce1.writeRaw(authNewNonce);
newNonce1.writeByte(1);
newNonce1.writeRaw(authKeyAuxHash);
byte[] newNonceHash1Full = Utilities.computeSHA1(newNonce1.toByteArray());
byte[] newNonceHash1 = new byte[16];
System.arraycopy(newNonceHash1Full, newNonceHash1Full.length - 16, newNonceHash1, 0, 16);
SerializedData newNonce2 = new SerializedData();
newNonce2.writeRaw(authNewNonce);
newNonce2.writeByte(2);
newNonce2.writeRaw(authKeyAuxHash);
byte[] newNonceHash2Full = Utilities.computeSHA1(newNonce2.toByteArray());
byte[] newNonceHash2 = new byte[16];
System.arraycopy(newNonceHash2Full, newNonceHash2Full.length - 16, newNonceHash2, 0, 16);
SerializedData newNonce3 = new SerializedData();
newNonce3.writeRaw(authNewNonce);
newNonce3.writeByte(3);
newNonce3.writeRaw(authKeyAuxHash);
byte[] newNonceHash3Full = Utilities.computeSHA1(newNonce3.toByteArray());
byte[] newNonceHash3 = new byte[16];
System.arraycopy(newNonceHash3Full, newNonceHash3Full.length - 16, newNonceHash3, 0, 16);
if (message instanceof TLRPC.TL_dh_gen_ok) {
TLRPC.TL_dh_gen_ok dhGenOk = (TLRPC.TL_dh_gen_ok)message;
if (!Arrays.equals(newNonceHash1, dhGenOk.new_nonce_hash1)) {
Log.e("tmessages", "***** Invalid DH answer nonce hash 1");
beginHandshake(false);
return;
}
Log.d("tmessages", String.format("Handshake with DC%d completed", datacenter.datacenterId));
datacenter.connection.delegate = null;
final Action parent = this;
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
datacenter.authKey = authKey;
datacenter.authKeyId = authKeyId;
datacenter.addServerSalt(serverSalt);
HashMap<String, Object> resultDict = new HashMap<String, Object>();
resultDict.put("timeDifference", timeDifference);
if (delegate != null) {
delegate.ActionDidFinishExecution(parent, resultDict);
}
}
});
} else if (message instanceof TLRPC.TL_dh_gen_retry) {
TLRPC.TL_dh_gen_retry dhRetry = (TLRPC.TL_dh_gen_retry)message;
if (!Arrays.equals(newNonceHash2, dhRetry.new_nonce_hash2)) {
Log.e("tmessages", "***** Invalid DH answer nonce hash 2");
beginHandshake(false);
return;
}
Log.d("tmessages", "***** Retry DH");
beginHandshake(false);
} else if (message instanceof TLRPC.TL_dh_gen_fail) {
TLRPC.TL_dh_gen_fail dhFail = (TLRPC.TL_dh_gen_fail)message;
if (!Arrays.equals(newNonceHash3, dhFail.new_nonce_hash3)) {
Log.e("tmessages", "***** Invalid DH answer nonce hash 3");
beginHandshake(false);
return;
}
Log.d("tmessages", "***** Server declined DH params");
beginHandshake(false);
} else {
Log.e("tmessages", "***** Unknown DH params response");
beginHandshake(false);
}
} else {
TLRPC.TL_msgs_ack msgsAck = new TLRPC.TL_msgs_ack();
msgsAck.msg_ids = new ArrayList<Long>();
msgsAck.msg_ids.add(messageId);
sendMessageData(msgsAck, generateMessageId());
}
}
@Override
public void tcpConnectionClosed(TcpConnection connection) {
wasDisconnect = true;
}
@Override
public void tcpConnectionConnected(TcpConnection connection) {
if (!wasDisconnect) {
return;
}
if (reqPQMsgData != null) {
datacenter.connection.sendData(reqPQMsgData, false, false);
} else if (reqDHMsgData != null) {
datacenter.connection.sendData(reqDHMsgData, false, false);
} else if (setClientDHParamsMsgData != null) {
datacenter.connection.sendData(setClientDHParamsMsgData, false, false);
}
}
@Override
public void tcpConnectionQuiackAckReceived(TcpConnection connection, int ack) {
}
@Override
public void tcpConnectionReceivedData(TcpConnection connection, byte[] data) {
SerializedData is = new SerializedData(data);
long keyId = is.readInt64();
if (keyId == 0) {
long messageId = is.readInt64();
if (processedMessageIds.contains(messageId)) {
Log.d("tmessages", String.format("===== Duplicate message id %d received, ignoring", messageId));
return;
}
int messageLength = is.readInt32();
int constructor = is.readInt32();
TLObject object = TLClassStore.Instance().TLdeserialize(is, constructor);
if (object != null) {
processedMessageIds.add(messageId);
}
processMessage(object, messageId);
} else {
Log.d("tmessages", "***** Received encrypted message while in handshake, restarting");
beginHandshake(true);
}
}
}

View file

@ -0,0 +1,298 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.graphics.Bitmap;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Static library version of {@link android.util.LruCache}. Used to write apps
* that run on API levels prior to 12. When running on API level 12 or above,
* this implementation is still used; it does not try to switch to the
* framework's implementation. See the framework SDK documentation for a class
* overview.
*/
public class LruCache {
private final LinkedHashMap<String, Bitmap> map;
private final LinkedHashMap<String, ArrayList<String>> mapFilters;
/** Size of this cache in units. Not necessarily the number of elements. */
private int size;
private int maxSize;
private int putCount;
private int evictionCount;
private int hitCount;
private int missCount;
/**
* @param maxSize for caches that do not override {@link #sizeOf}, this is
* the maximum number of entries in the cache. For all other caches,
* this is the maximum sum of the sizes of the entries in this cache.
*/
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
this.mapFilters = new LinkedHashMap<String, ArrayList<String>>();
}
/**
* Returns the value for {@code key} if it exists in the cache or can be
* created by {@code #create}. If a value was returned, it is moved to the
* head of the queue. This returns null if a value is not cached and cannot
* be created.
*/
public final Bitmap get(String key) {
if (key == null) {
throw new NullPointerException("key == null");
}
Bitmap mapValue;
synchronized (this) {
mapValue = map.get(key);
if (mapValue != null) {
hitCount++;
return mapValue;
}
missCount++;
}
return null;
}
public ArrayList<String> getFilterKeys(String key) {
ArrayList<String> arr = mapFilters.get(key);
if (arr != null) {
return new ArrayList<String>(arr);
}
return null;
}
/**
* Caches {@code value} for {@code key}. The value is moved to the head of
* the queue.
*
* @return the previous value mapped by {@code key}.
*/
public Bitmap put(String key, Bitmap value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}
Bitmap previous;
synchronized (this) {
putCount++;
size += safeSizeOf(key, value);
previous = map.put(key, value);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
}
String[] args = key.split("@");
if (args.length > 1) {
ArrayList<String> arr = mapFilters.get(args[0]);
if (arr == null) {
arr = new ArrayList<String>();
mapFilters.put(args[0], arr);
}
arr.add(args[1]);
}
if (previous != null) {
entryRemoved(false, key, previous, value);
}
trimToSize(maxSize);
return previous;
}
/**
* @param maxSize the maximum size of the cache before returning. May be -1
* to evict even 0-sized elements.
*/
private void trimToSize(int maxSize) {
while (true) {
String key;
Bitmap value;
synchronized (this) {
if (size < 0 || (map.isEmpty() && size != 0)) {
throw new IllegalStateException(getClass().getName()
+ ".sizeOf() is reporting inconsistent results!");
}
if (size <= maxSize || map.isEmpty()) {
break;
}
Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next();
key = toEvict.getKey();
value = toEvict.getValue();
map.remove(key);
size -= safeSizeOf(key, value);
evictionCount++;
}
String[] args = key.split("$");
if (args.length > 1) {
ArrayList<String> arr = mapFilters.get(args[0]);
if (arr != null) {
arr.remove(key);
if (arr.isEmpty()) {
mapFilters.remove(args[1]);
}
}
}
entryRemoved(true, key, value, null);
}
}
/**
* Removes the entry for {@code key} if it exists.
*
* @return the previous value mapped by {@code key}.
*/
public final Bitmap remove(String key) {
if (key == null) {
throw new NullPointerException("key == null");
}
Bitmap previous;
synchronized (this) {
previous = map.remove(key);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
}
if (previous != null) {
String[] args = key.split("$");
if (args.length > 1) {
ArrayList<String> arr = mapFilters.get(args[0]);
if (arr != null) {
arr.remove(key);
if (arr.isEmpty()) {
mapFilters.remove(args[1]);
}
}
}
entryRemoved(false, key, previous, null);
}
return previous;
}
public boolean contains(String key){
return map.containsKey(key);
}
/**
* Called for entries that have been evicted or removed. This method is
* invoked when a value is evicted to make space, removed by a call to
* {@link #remove}, or replaced by a call to {@link #put}. The default
* implementation does nothing.
*
* <p>The method is called without synchronization: other threads may
* access the cache while this method is executing.
*
* @param evicted true if the entry is being removed to make space, false
* if the removal was caused by a {@link #put} or {@link #remove}.
* @param newValue the new value for {@code key}, if it exists. If non-null,
* this removal was caused by a {@link #put}. Otherwise it was caused by
* an eviction or a {@link #remove}.
*/
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {}
private int safeSizeOf(String key, Bitmap value) {
int result = sizeOf(key, value);
if (result < 0) {
throw new IllegalStateException("Negative size: " + key + "=" + value);
}
return result;
}
/**
* Returns the size of the entry for {@code key} and {@code value} in
* user-defined units. The default implementation returns 1 so that size
* is the number of entries and max size is the maximum number of entries.
*
* <p>An entry's size must not change while it is in the cache.
*/
protected int sizeOf(String key, Bitmap value) {
return 1;
}
/**
* Clear the cache, calling {@link #entryRemoved} on each removed entry.
*/
public final void evictAll() {
trimToSize(-1); // -1 will evict 0-sized elements
}
/**
* For caches that do not override {@link #sizeOf}, this returns the number
* of entries in the cache. For all other caches, this returns the sum of
* the sizes of the entries in this cache.
*/
public synchronized final int size() {
return size;
}
/**
* For caches that do not override {@link #sizeOf}, this returns the maximum
* number of entries in the cache. For all other caches, this returns the
* maximum sum of the sizes of the entries in this cache.
*/
public synchronized final int maxSize() {
return maxSize;
}
/**
* Returns the number of times {@link #get} returned a value.
*/
public synchronized final int hitCount() {
return hitCount;
}
/**
* Returns the number of times {@link #get} returned null or required a new
* value to be created.
*/
public synchronized final int missCount() {
return missCount;
}
/**
* Returns the number of times {@link #put} was called.
*/
public synchronized final int putCount() {
return putCount;
}
/**
* Returns the number of values that have been evicted.
*/
public synchronized final int evictionCount() {
return evictionCount;
}
@Override public synchronized final String toString() {
int accesses = hitCount + missCount;
int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
maxSize, hitCount, missCount, hitPercent);
}
}

View file

@ -0,0 +1,14 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
public class MessageKeyData {
public byte[] aesKey;
public byte[] aesIv;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,17 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import org.telegram.TL.TLRPC;
public class NetworkMessage {
public TLRPC.TL_protoMessage protoMessage;
public Object rawRequest;
public long requestId;
}

View file

@ -0,0 +1,120 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import java.util.ArrayList;
import java.util.HashMap;
public class NotificationCenter {
final private HashMap<Integer, ArrayList<Object>> observers = new HashMap<Integer, ArrayList<Object>>();
final private HashMap<Integer, Object> memCache = new HashMap<Integer, Object>();
final private HashMap<String, Object> memCacheString = new HashMap<String, Object>();
private boolean broadcasting = false;
final private HashMap<Integer, Object> removeAfterBroadcast = new HashMap<Integer, Object>();
public interface NotificationCenterDelegate {
public abstract void didReceivedNotification(int id, Object... args);
}
public static NotificationCenter Instance = new NotificationCenter();
public void addToMemCache(int id, Object object) {
memCache.put(id, object);
}
public void addToMemCache(String id, Object object) {
memCacheString.put(id, object);
}
public Object getFromMemCache(int id) {
Object obj = memCache.get(id);
if (obj != null) {
memCache.remove(id);
}
return obj;
}
public Object getFromMemCache(String id, Object defaultValue) {
Object obj = memCacheString.get(id);
if (obj != null) {
memCacheString.remove(id);
} else {
return defaultValue;
}
return obj;
}
public void postNotificationName(int id, Object... args) {
synchronized (observers) {
broadcasting = true;
ArrayList<Object> objects = observers.get(id);
if (objects != null) {
for (Object obj : objects) {
((NotificationCenterDelegate)obj).didReceivedNotification(id, args);
}
}
broadcasting = false;
if (!removeAfterBroadcast.isEmpty()) {
for (HashMap.Entry<Integer, Object> entry : removeAfterBroadcast.entrySet()) {
removeObserver(entry.getValue(), entry.getKey());
}
removeAfterBroadcast.clear();
}
}
}
public void addObserver(Object observer, int id) {
synchronized (observers) {
ArrayList<Object> objects = observers.get(id);
if (objects == null) {
objects = new ArrayList<Object>();
observers.put(id, objects);
}
if (objects.contains(observer)) {
return;
}
objects.add(observer);
}
}
// public void removeObserver(Object observer) {
// synchronized (observers) {
// if (broadcasting) {
// removeAfterBroadcast.put(-1, observer);
// return;
// }
// Integer[] keyArr = (Integer[])observers.keySet().toArray();
// for (int a = 0; a < observers.size(); a++) {
// Integer id = keyArr[a];
// ArrayList<Object> objects = observers.get(id);
// objects.remove(observer);
// if (objects.size() == 0) {
// observers.remove(id);
// a--;
// }
// }
// }
// }
public void removeObserver(Object observer, int id) {
synchronized (observers) {
if (broadcasting) {
removeAfterBroadcast.put(id, observer);
return;
}
ArrayList<Object> objects = observers.get(id);
if (objects != null) {
objects.remove(observer);
if (objects.size() == 0) {
observers.remove(id);
}
}
}
}
}

View file

@ -0,0 +1,71 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
import java.util.ArrayList;
public class RPCRequest {
public interface RPCRequestDelegate {
void run(TLObject response, TLRPC.TL_error error);
}
public interface RPCProgressDelegate {
void progress(int length, int progress);
}
public interface RPCQuickAckDelegate {
void quickAck();
}
public static int RPCRequestClassGeneric = 1;
public static int RPCRequestClassDownloadMedia = 2;
public static int RPCRequestClassUploadMedia = 4;
public static int RPCRequestClassEnableUnauthorized = 8;
public static int RPCRequestClassFailOnServerErrors = 16;
static int RPCRequestClassTransportMask = (RPCRequestClassGeneric | RPCRequestClassDownloadMedia | RPCRequestClassUploadMedia);
long token;
boolean cancelled;
int serverFailureCount;
int flags;
TLObject rawRequest;
TLObject rpcRequest;
int serializedLength;
RPCRequestDelegate completionBlock;
RPCProgressDelegate progressBlock;
RPCQuickAckDelegate quickAckBlock;
boolean requiresCompletion;
long runningMessageId;
int runningMessageSeqNo;
int runningDatacenterId;
int transportChannelToken;
int runningStartTime;
int runningMinStartTime;
boolean confirmed;
ArrayList<Long> respondsToMessageIds = new ArrayList<Long>();
public void addRespondMessageId(long messageId) {
respondsToMessageIds.add(messageId);
}
boolean respondsToMessageId(long messageId) {
return runningMessageId == messageId || respondsToMessageIds.contains(messageId);
}
}

View file

@ -0,0 +1,293 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class SerializedData {
protected boolean isOut = true;
private ByteArrayOutputStream outbuf;
private DataOutputStream out;
private ByteArrayInputStream inbuf;
private DataInputStream in;
public SerializedData() {
outbuf = new ByteArrayOutputStream();
out = new DataOutputStream(outbuf);
}
public SerializedData(byte[] data){
isOut = false;
inbuf = new ByteArrayInputStream(data);
in = new DataInputStream(inbuf);
}
public SerializedData(File file) throws IOException {
FileInputStream is = new FileInputStream(file);
byte[] data = new byte[(int)file.length()];
new DataInputStream(is).readFully(data);
is.close();
isOut = false;
inbuf = new ByteArrayInputStream(data);
in = new DataInputStream(inbuf);
}
public void writeInt32(int x){
writeInt32(x, out);
}
protected void writeInt32(int x, DataOutputStream out){
try {
for(int i = 0; i < 4; i++){
out.write(x >> (i * 8));
}
} catch(IOException gfdsgd) {
Log.e("tmessages", "write int32 error");
}
}
public void writeInt64(long i) {
writeInt64(i, out);
}
protected void writeInt64(long x, DataOutputStream out){
try {
for(int i = 0; i < 8; i++){
out.write((int)(x >> (i * 8)));
}
} catch(IOException gfdsgd) {
Log.e("tmessages", "write int64 error");
}
}
public boolean readBool() {
int consructor = readInt32();
if (consructor == 0x997275b5) {
return true;
} else if (consructor == 0xbc799737) {
return false;
}
Log.e("tmessages", "Not bool value!");
return false;
}
public void writeBool(boolean value) {
if (value) {
writeInt32(0x997275b5);
} else {
writeInt32(0xbc799737);
}
}
public int readInt32(){
try {
int i = 0;
for(int j = 0; j < 4; j++){
i |= (in.read() << (j * 8));
}
return i;
} catch(IOException x) {
Log.e("tmessages", "read int32 error");
}
return 0;
}
public long readInt64(){
try {
long i = 0;
for(int j = 0; j < 8; j++){
i |= ((long)in.read() << (j * 8));
}
return i;
} catch(IOException x) {
Log.e("tmessages", "read int64 error");
}
return 0;
}
public void writeRaw(byte[] b){
try {
out.write(b);
} catch(Exception x) {
Log.e("tmessages", "write raw error");
}
}
public void writeRaw(byte[] b, int offset, int count) {
try {
out.write(b, offset, count);
} catch(Exception x) {
Log.e("tmessages", "write raw error");
}
}
public void writeByte(int i) {
try {
out.writeByte((byte)i);
} catch (Exception e) {
Log.e("tmessages", "write byte error");
}
}
public void writeByte(byte b) {
try {
out.writeByte(b);
} catch (Exception e) {
Log.e("tmessages", "write byte error");
}
}
public void readRaw(byte[] b){
try {
in.read(b);
} catch(Exception x) {
Log.e("tmessages", "read raw error");
}
}
public byte[] readData(int count) {
byte[] arr = new byte[count];
readRaw(arr);
return arr;
}
public String readString(){
try {
int sl = 1;
int l = in.read();
if(l >= 254){
l = in.read() | (in.read() << 8) | (in.read() << 16);
sl = 4;
}
byte[] b = new byte[l];
in.read(b);
int i=sl;
while((l + i) % 4 != 0) {
in.read();
i++;
}
return new String(b, "UTF-8");
} catch(Exception x) {
Log.e("tmessages", "read string error");
}
return null;
}
public byte[] readByteArray() {
try {
int sl = 1;
int l = in.read();
if (l >= 254){
l = in.read() | (in.read() << 8) | (in.read() << 16);
sl = 4;
}
byte[] b = new byte[l];
in.read(b);
int i = sl;
while((l + i) % 4 != 0){
in.read();
i++;
}
return b;
} catch(Exception x) {
Log.e("tmessages", "read byte array error");
}
return null;
}
public void writeByteArray(byte[] b){
try {
if (b.length <= 253){
out.write(b.length);
} else {
out.write(254);
out.write(b.length);
out.write(b.length >> 8);
out.write(b.length >> 16);
}
out.write(b);
int i = b.length <= 253 ? 1 : 4;
while((b.length + i) % 4 != 0){
out.write(0);
i++;
}
}catch(Exception x) {
Log.e("tmessages", "write byte array error");
}
}
public void writeString(String s){
try {
writeByteArray(s.getBytes("UTF-8"));
} catch(Exception x) {
Log.e("tmessages", "write string error");
}
}
public void writeByteArray(byte[] b, int offset, int count) {
try {
if(count <= 253){
out.write(count);
} else {
out.write(254);
out.write(count);
out.write(count >> 8);
out.write(count >> 16);
}
out.write(b, offset, count);
int i = count <= 253 ? 1 : 4;
while ((count + i) % 4 != 0){
out.write(0);
i++;
}
} catch(Exception x) {
Log.e("tmessages", "write byte array error");
}
}
public double readDouble(){
try {
return Double.longBitsToDouble(readInt64());
} catch(Exception x) {
Log.e("tmessages", "read double error");
}
return 0;
}
public void writeDouble(double d){
try {
writeInt64(Double.doubleToRawLongBits(d));
} catch(Exception x) {
Log.e("tmessages", "write double error");
}
}
public int length() {
return isOut ? outbuf.size() : inbuf.available();
}
protected void set(byte[] newData) {
isOut = false;
inbuf = new ByteArrayInputStream(newData);
in = new DataInputStream(inbuf);
}
public byte[] toByteArray() {
return outbuf.toByteArray();
}
}

View file

@ -0,0 +1,15 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
public class ServerSalt {
public int validSince;
public int validUntil;
public long value;
}

View file

@ -0,0 +1,61 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.telephony.SmsMessage;
import org.telegram.messenger.NotificationCenter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SmsListener extends BroadcastReceiver {
private SharedPreferences preferences;
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras();
SmsMessage[] msgs;
if (bundle != null) {
try {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
String wholeString = "";
for(int i = 0; i < msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
wholeString += msgs[i].getMessageBody();
}
try {
Pattern pattern = Pattern.compile("[0-9]+");
Matcher matcher = pattern.matcher(wholeString);
if (matcher.find()) {
String str = matcher.group(0);
if (str.length() >= 3) {
NotificationCenter.Instance.postNotificationName(998, matcher.group(0));
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
}

View file

@ -0,0 +1,431 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.util.Log;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Timer;
import java.util.TimerTask;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroSelector;
import jawnae.pyronet.events.PyroClientAdapter;
public class TcpConnection extends PyroClientAdapter {
public enum TcpConnectionState {
TcpConnectionStageIdle,
TcpConnectionStageConnecting,
TcpConnectionStageReconnecting,
TcpConnectionStageConnected,
TcpConnectionStageSuspended
}
public abstract static interface TcpConnectionDelegate {
public abstract void tcpConnectionClosed(TcpConnection connection);
public abstract void tcpConnectionConnected(TcpConnection connection);
public abstract void tcpConnectionQuiackAckReceived(TcpConnection connection, int ack);
public abstract void tcpConnectionReceivedData(TcpConnection connection, byte[] data);
}
private static PyroSelector selector;
private PyroClient client;
public TcpConnectionState connectionState;
private Queue<byte[]> packetsQueue;
public volatile int channelToken = 0;
private String hostAddress;
private int hostPort;
public int datacenterId;
private int failedConnectionCount;
public TcpConnectionDelegate delegate;
private ByteBuffer restOfTheData;
public int transportRequestClass;
private boolean firstPacket;
private Timer reconnectTimer;
public TcpConnection(String ip, int port) {
if (selector == null) {
selector = new PyroSelector();
selector.spawnNetworkThread("network thread");
}
packetsQueue = new LinkedList<byte[]>();
hostAddress = ip;
hostPort = port;
connectionState = TcpConnectionState.TcpConnectionStageIdle;
}
static volatile Integer nextChannelToken = 1;
static int generateChannelToken() {
return nextChannelToken++;
}
public void connect() {
selector.scheduleTask(new Runnable() {
@Override
public void run() {
if (connectionState == TcpConnectionState.TcpConnectionStageConnected || connectionState == TcpConnectionState.TcpConnectionStageConnecting) {
return;
}
connectionState = TcpConnectionState.TcpConnectionStageConnecting;
try {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", String.format(this + " Connecting (%s:%d)", hostAddress, hostPort));
}
firstPacket = true;
restOfTheData = null;
if (client != null) {
client.removeListener(TcpConnection.this);
client.dropConnection();
}
client = selector.connect(new InetSocketAddress(hostAddress, hostPort));
client.addListener(TcpConnection.this);
client.setTimeout(35000);
selector.wakeup();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void suspendConnection(boolean task) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "suspend connnection " + this);
}
if (task) {
selector.scheduleTask(new Runnable() {
@Override
public void run() {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
if (connectionState == TcpConnectionState.TcpConnectionStageIdle || connectionState == TcpConnectionState.TcpConnectionStageSuspended) {
return;
}
connectionState = TcpConnectionState.TcpConnectionStageSuspended;
if (client != null) {
client.dropConnection();
client = null;
}
}
});
} else {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
if (connectionState == TcpConnectionState.TcpConnectionStageIdle) {
return;
}
connectionState = TcpConnectionState.TcpConnectionStageSuspended;
if (client != null) {
client.dropConnection();
client = null;
}
}
}
public void resumeConnection() {
}
private void reconnect() {
suspendConnection(false);
connectionState = TcpConnectionState.TcpConnectionStageReconnecting;
connect();
}
public void sendData(final byte[] data, final boolean reportAck, final boolean startResponseTimeout) {
selector.scheduleTask(new Runnable() {
@Override
public void run() {
if (connectionState == TcpConnectionState.TcpConnectionStageIdle ||
connectionState == TcpConnectionState.TcpConnectionStageReconnecting ||
connectionState == TcpConnectionState.TcpConnectionStageSuspended) {
connect();
}
int packetLength = data.length / 4;
SerializedData buffer = new SerializedData();
if (packetLength < 0x7f) {
if (reportAck) {
packetLength |= (1 << 7);
}
buffer.writeByte(packetLength);
} else {
packetLength = (packetLength << 8) + 0x7f;
if (reportAck) {
packetLength |= (1 << 7);
}
buffer.writeInt32(packetLength);
}
buffer.writeRaw(data);
final byte[] packet = buffer.toByteArray();
if (client != null && !client.isDisconnected()) {
ByteBuffer sendBuffer = ByteBuffer.allocate((firstPacket ? 1 : 0) + packet.length);
sendBuffer.rewind();
sendBuffer.order(ByteOrder.LITTLE_ENDIAN);
if (firstPacket) {
sendBuffer.put((byte)0xef);
firstPacket = false;
}
sendBuffer.put(packet);
sendBuffer.rewind();
client.write(sendBuffer);
} else {
packetsQueue.add(packet);
}
}
});
}
private void readData(ByteBuffer buffer) throws Exception {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "received data = " + buffer.limit());
}
if (restOfTheData != null) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "there is rest of data " + restOfTheData.limit());
}
ByteBuffer newBuffer = ByteBuffer.allocate(restOfTheData.limit() + buffer.limit());
newBuffer.put(restOfTheData);
newBuffer.put(buffer);
buffer = newBuffer;
restOfTheData = null;
}
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.rewind();
while (buffer.hasRemaining()) {
int currentPacketLength;
buffer.mark();
byte fByte = buffer.get();
if ((fByte & (1 << 7)) != 0) {
buffer.reset();
if (buffer.remaining() < 4) {
restOfTheData = ByteBuffer.allocate(buffer.remaining());
restOfTheData.put(buffer);
restOfTheData.rewind();
break;
}
buffer.order(ByteOrder.BIG_ENDIAN);
final int ackId = buffer.getInt() & (~(1 << 31));
if (delegate != null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.tcpConnectionQuiackAckReceived(TcpConnection.this, ackId);
}
});
}
buffer.order(ByteOrder.LITTLE_ENDIAN);
continue;
}
if (fByte != 0x7f) {
currentPacketLength = ((int)fByte) * 4;
} else {
buffer.reset();
if (buffer.remaining() < 4) {
restOfTheData = ByteBuffer.allocate(buffer.remaining());
restOfTheData.put(buffer);
restOfTheData.rewind();
break;
}
currentPacketLength = (buffer.getInt() >> 8) * 4;
}
if (currentPacketLength < buffer.remaining()) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", this + " Received message len " + currentPacketLength + " but packet larger " + buffer.remaining());
}
} else if (currentPacketLength == buffer.remaining()) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", this + " Received message len " + currentPacketLength + " equal to packet size");
}
} else {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", this + " Received packet size less(" + buffer.remaining() + ") then message size(" + currentPacketLength + ")");
}
buffer.reset();
restOfTheData = ByteBuffer.allocate(buffer.remaining());
restOfTheData.order(ByteOrder.LITTLE_ENDIAN);
restOfTheData.put(buffer);
restOfTheData.rewind();
return;
}
if (currentPacketLength % 4 != 0 || currentPacketLength > 2 * 1024 * 1024) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.e("tmessages", "Invalid packet length");
}
reconnect();
return;
}
final byte[] packetData = new byte[currentPacketLength];
buffer.get(packetData);
if (delegate != null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.tcpConnectionReceivedData(TcpConnection.this, packetData);
}
});
}
}
}
public void handleDisconnect(PyroClient client, IOException e) {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
if (ConnectionsManager.DEBUG_VERSION) {
if (e != null) {
Log.d("tmessages", "Disconnected " + this + " with error " + e);
} else {
Log.d("tmessages", "Disconnected " + this);
}
}
firstPacket = true;
restOfTheData = null;
packetsQueue.clear();
channelToken = 0;
if (connectionState != TcpConnectionState.TcpConnectionStageSuspended && connectionState != TcpConnectionState.TcpConnectionStageIdle) {
connectionState = TcpConnectionState.TcpConnectionStageIdle;
}
if (delegate != null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.tcpConnectionClosed(TcpConnection.this);
}
});
}
if (connectionState == TcpConnectionState.TcpConnectionStageIdle && (!packetsQueue.isEmpty() ||
(transportRequestClass & RPCRequest.RPCRequestClassGeneric) != 0 && (datacenterId == ConnectionsManager.Instance.currentDatacenterId || datacenterId == ConnectionsManager.Instance.movingToDatacenterId))) {
failedConnectionCount++;
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "Reconnect " + hostAddress + ":" + hostPort + " " + this);
}
try {
reconnectTimer = new Timer();
reconnectTimer.schedule(new TimerTask() {
@Override
public void run() {
selector.scheduleTask(new Runnable() {
@Override
public void run() {
try {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
} catch (Exception e2) {
e2.printStackTrace();
}
connect();
}
});
}
}, failedConnectionCount > 10 ? 500 : 200, failedConnectionCount > 10 ? 500 : 200);
} catch (Exception e3) {
e3.printStackTrace();
}
}
}
@Override
public void connectedClient(PyroClient client) {
//if (!ConnectionsManager.isNetworkOnline()) {
// return;
//}
connectionState = TcpConnectionState.TcpConnectionStageConnected;
channelToken = generateChannelToken();
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", String.format(this + " Connected (%s:%d)", hostAddress, hostPort));
}
if (delegate != null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.tcpConnectionConnected(TcpConnection.this);
}
});
}
while (packetsQueue.size() != 0) {
byte[] packet = packetsQueue.poll();
ByteBuffer sendBuffer = ByteBuffer.allocate((firstPacket ? 1 : 0) + packet.length);
sendBuffer.order(ByteOrder.LITTLE_ENDIAN);
if (firstPacket) {
sendBuffer.put((byte)0xef);
firstPacket = false;
}
sendBuffer.put(packet);
sendBuffer.rewind();
client.write(sendBuffer);
}
}
@Override
public void unconnectableClient(PyroClient client) {
handleDisconnect(client, null);
}
@Override
public void droppedClient(PyroClient client, IOException cause) {
super.droppedClient(client, cause);
handleDisconnect(client, cause);
}
@Override
public void disconnectedClient(PyroClient client) {
handleDisconnect(client, null);
}
@Override
public void receivedData(PyroClient client, ByteBuffer data) {
try {
failedConnectionCount = 0;
readData(data);
} catch (Exception e) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "read data error");
}
reconnect();
}
}
@Override
public void sentData(PyroClient client, int bytes) {
failedConnectionCount = 0;
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", this + " bytes sent " + bytes);
}
}
}

View file

@ -0,0 +1,55 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
import java.util.ArrayList;
import java.util.HashMap;
public class UpdateDatacenterListAction extends Action {
public int datacenterId;
public UpdateDatacenterListAction(int id) {
datacenterId = id;
}
public void execute(HashMap params) {
TLRPC.TL_help_getConfig getConfig = new TLRPC.TL_help_getConfig();
ConnectionsManager.Instance.performRpc(getConfig, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (delegate == null) {
return;
}
if (error == null) {
TLRPC.TL_config config = (TLRPC.TL_config)response;
ArrayList<Datacenter> datacenters = new ArrayList<Datacenter>();
for (TLRPC.TL_dcOption datacenterDesc : config.dc_options) {
Datacenter datacenter = new Datacenter();
datacenter.datacenterId = datacenterDesc.id;
datacenter.authSessionId = (long)(MessagesController.random.nextDouble() * Long.MAX_VALUE);
datacenter.address = datacenterDesc.ip_address;
datacenter.port = datacenterDesc.port;
datacenters.add(datacenter);
}
HashMap<String, Object> result = new HashMap<String, Object>();
result.put("datacenters", datacenters);
delegate.ActionDidFinishExecution(UpdateDatacenterListAction.this, result);
} else {
delegate.ActionDidFailExecution(UpdateDatacenterListAction.this);
}
}
}, null, true, RPCRequest.RPCRequestClassEnableUnauthorized | RPCRequest.RPCRequestClassGeneric);
}
}

View file

@ -0,0 +1,148 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import org.telegram.TL.TLClassStore;
import org.telegram.TL.TLRPC;
import java.io.File;
import java.io.FileOutputStream;
public class UserConfig {
public static TLRPC.User currentUser;
public static int clientUserId = 0;
public static boolean clientActivated = false;
public static int lastDateValue = 0;
public static int lastPtsValue = 0;
public static int lastQtsValue = 0;
public static int lastSeqValue = 0;
public static boolean registeredForPush = false;
public static String pushString = "";
public static int lastSendMessageId = -1;
public static int lastLocalId = -1;
public static int lastSecretVersion = 0;
public static byte[] secretPBytes = null;
public static int secretG = 0;
public static String contactsHash = "";
public static String importHash = "";
private final static Integer sync = 1;
public static boolean saveIncomingPhotos = false;
public static int getNewMessageId() {
int id;
synchronized (sync) {
id = lastSendMessageId;
lastSendMessageId--;
}
return id;
}
public static void saveConfig() {
synchronized (sync) {
SerializedData data = new SerializedData();
if (currentUser != null) {
data.writeInt32(1);
currentUser.serializeToStream(data);
clientUserId = currentUser.id;
clientActivated = true;
data.writeInt32(lastDateValue);
data.writeInt32(lastPtsValue);
data.writeInt32(lastSeqValue);
data.writeBool(registeredForPush);
data.writeString(pushString);
data.writeInt32(lastSendMessageId);
data.writeInt32(lastLocalId);
data.writeString(contactsHash);
data.writeString(importHash);
data.writeBool(saveIncomingPhotos);
data.writeInt32(lastQtsValue);
data.writeInt32(lastSecretVersion);
if (secretPBytes != null) {
data.writeInt32(1);
data.writeByteArray(secretPBytes);
} else {
data.writeInt32(0);
}
data.writeInt32(secretG);
} else {
data.writeInt32(0);
}
try {
File configFile = new File(Utilities.applicationContext.getFilesDir(), "user.dat");
if (!configFile.exists()) {
configFile.createNewFile();
}
FileOutputStream stream = new FileOutputStream(configFile);
stream.write(data.toByteArray());
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void loadConfig() {
synchronized (sync) {
File configFile = new File(Utilities.applicationContext.getFilesDir(), "user.dat");
if (configFile.exists()) {
try {
SerializedData data = new SerializedData(configFile);
if (data.readInt32() != 0) {
int constructor = data.readInt32();
currentUser = (TLRPC.TL_userSelf)TLClassStore.Instance().TLdeserialize(data, constructor);
clientUserId = currentUser.id;
clientActivated = true;
lastDateValue = data.readInt32();
lastPtsValue = data.readInt32();
lastSeqValue = data.readInt32();
registeredForPush = data.readBool();
pushString = data.readString();
lastSendMessageId = data.readInt32();
lastLocalId = data.readInt32();
contactsHash = data.readString();
importHash = data.readString();
saveIncomingPhotos = data.readBool();
if (currentUser.status != null) {
if (currentUser.status.expires != 0) {
currentUser.status.was_online = currentUser.status.expires;
} else {
currentUser.status.expires = currentUser.status.was_online;
}
}
lastQtsValue = data.readInt32();
lastSecretVersion = data.readInt32();
int val = data.readInt32();
if (val == 1) {
secretPBytes = data.readByteArray();
}
secretG = data.readInt32();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void clearConfig() {
clientUserId = 0;
clientActivated = false;
currentUser = null;
lastDateValue = 0;
lastSeqValue = 0;
lastPtsValue = 0;
registeredForPush = false;
contactsHash = "";
lastLocalId = -1;
importHash = "";
lastSendMessageId = -1;
saveIncomingPhotos = false;
saveConfig();
}
}

View file

@ -0,0 +1,598 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import org.telegram.TL.TLClassStore;
import org.telegram.TL.TLObject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.Locale;
import java.util.zip.GZIPInputStream;
import javax.crypto.Cipher;
public class Utilities {
public static Context applicationContext;
public static Handler applicationHandler;
private final static Integer lock = 1;
public static class TPFactorizedValue {
public long p, q;
}
public static DispatchQueue stageQueue = new DispatchQueue("stageQueue");
public static DispatchQueue globalQueue = new DispatchQueue("globalQueue");
public static DispatchQueue cacheOutQueue = new DispatchQueue("cacheOutQueue");
public static DispatchQueue imageLoadQueue = new DispatchQueue("imageLoadQueue");
public static DispatchQueue fileUploadQueue = new DispatchQueue("imageLoadQueue");
public native static long doPQNative(long _what);
public native static byte[] aesIgeEncryption(byte[] _what, byte[] _key, byte[] _iv, boolean encrypt, boolean changeIv);
static {
System.loadLibrary("tmessages");
}
static final Class<?>[] constructorSignature = new Class[] {Context.class, AttributeSet.class};
public static int externalCacheNotAvailableState = 0;
public static File getCacheDir() {
if (externalCacheNotAvailableState == 1 || externalCacheNotAvailableState == 0 && Environment.getExternalStorageState().startsWith(Environment.MEDIA_MOUNTED)) {
externalCacheNotAvailableState = 1;
return applicationContext.getExternalCacheDir();
}
externalCacheNotAvailableState = 2;
return applicationContext.getCacheDir();
}
public static TPFactorizedValue getFactorizedValue(long what) {
long g = doPQNative(what);
if (g > 1 && g < what) {
long p1 = g;
long p2 = what / g;
if (p1 > p2) {
long tmp = p1;
p1 = p2;
p2 = tmp;
}
TPFactorizedValue result = new TPFactorizedValue();
result.p = p1;
result.q = p2;
return result;
} else {
Log.e("tmessages", String.format("**** Factorization failed for %d", what));
TPFactorizedValue result = new TPFactorizedValue();
result.p = 0;
result.q = 0;
return result;
}
}
public static byte[] computeSHA1(byte[] convertme) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
return md.digest(convertme);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
public static byte[] encryptWithRSA(BigInteger[] key, byte[] data) {
try {
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(key[0], key[1]);
PublicKey publicKey = fact.generatePublic(keySpec);
final Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] longToBytes(long x) {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong(x);
return buffer.array();
}
public static long bytesToLong(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put(bytes);
buffer.flip();
return buffer.getLong();
}
public static int bytesToInt(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put(bytes);
buffer.flip();
return buffer.getInt();
}
public static MessageKeyData generateMessageKeyData(byte[] authKey, byte[] messageKey, boolean incoming) {
MessageKeyData keyData = new MessageKeyData();
if (authKey == null || authKey.length == 0) {
keyData.aesIv = null;
keyData.aesKey = null;
return keyData;
}
int x = incoming ? 8 : 0;
SerializedData data = new SerializedData();
data.writeRaw(messageKey);
data.writeRaw(authKey, x, 32);
byte[] sha1_a = Utilities.computeSHA1(data.toByteArray());
data = new SerializedData();
data.writeRaw(authKey, 32 + x, 16);
data.writeRaw(messageKey);
data.writeRaw(authKey, 48 + x, 16);
byte[] sha1_b = Utilities.computeSHA1(data.toByteArray());
data = new SerializedData();
data.writeRaw(authKey, 64 + x, 32);
data.writeRaw(messageKey);
byte[] sha1_c = Utilities.computeSHA1(data.toByteArray());
data = new SerializedData();
data.writeRaw(messageKey);
data.writeRaw(authKey, 96 + x, 32);
byte[] sha1_d = Utilities.computeSHA1(data.toByteArray());
SerializedData aesKey = new SerializedData();
aesKey.writeRaw(sha1_a, 0, 8);
aesKey.writeRaw(sha1_b, 8, 12);
aesKey.writeRaw(sha1_c, 4, 12);
keyData.aesKey = aesKey.toByteArray();
SerializedData aesIv = new SerializedData();
aesIv.writeRaw(sha1_a, 8, 12);
aesIv.writeRaw(sha1_b, 0, 8);
aesIv.writeRaw(sha1_c, 16, 4);
aesIv.writeRaw(sha1_d, 0, 8);
keyData.aesIv = aesIv.toByteArray();
return keyData;
}
public static TLObject decompress(byte[] data, TLObject parentObject) {
final int BUFFER_SIZE = 512;
ByteArrayInputStream is = new ByteArrayInputStream(data);
GZIPInputStream gis;
try {
gis = new GZIPInputStream(is, BUFFER_SIZE);
ByteArrayOutputStream bytesOutput = new ByteArrayOutputStream();
data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
bytesOutput.write(data, 0, bytesRead);
}
gis.close();
is.close();
SerializedData stream = new SerializedData(bytesOutput.toByteArray());
return TLClassStore.Instance().TLdeserialize(stream, stream.readInt32(), parentObject);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static final String TAG = "Typefaces";
private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();
public static Typeface getTypeface(String assetPath) {
synchronized (cache) {
if (!cache.containsKey(assetPath)) {
try {
Typeface t = Typeface.createFromAsset(applicationContext.getAssets(),
assetPath);
cache.put(assetPath, t);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface '" + assetPath
+ "' because " + e.getMessage());
return null;
}
}
return cache.get(assetPath);
}
}
public static void showKeyboard(View view) {
if (view == null) {
return;
}
InputMethodManager inputManager = (InputMethodManager)view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
((InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(view, 0);
}
public static boolean isKeyboardShowed(View view) {
if (view == null) {
return false;
}
InputMethodManager inputManager = (InputMethodManager) view
.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return inputManager.isActive(view);
}
public static void hideKeyboard(View view) {
if (view == null) {
return;
}
InputMethodManager imm = (InputMethodManager) view.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (!imm.isActive())
return;
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
public static ProgressDialog progressDialog;
public static void ShowProgressDialog(final Activity activity, final String message) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog = new ProgressDialog(activity);
if (message != null) {
progressDialog.setMessage(message);
}
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
});
}
public static FastDateFormat formatterDay;
public static FastDateFormat formatterMonth;
public static FastDateFormat formatterYear;
public static FastDateFormat formatterYearMax;
public static FastDateFormat chatDate;
public static FastDateFormat chatFullDate;
static {
Locale locale = Locale.getDefault();
String lang = locale.getLanguage();
formatterMonth = FastDateFormat.getInstance("dd MMM", locale);
formatterYear = FastDateFormat.getInstance("dd.MM.yy", locale);
formatterYearMax = FastDateFormat.getInstance("dd.MM.yyyy", locale);
chatDate = FastDateFormat.getInstance("d MMMM", locale);
chatFullDate = FastDateFormat.getInstance("d MMMM yyyy", locale);
if (lang != null && lang.toLowerCase().equals("ar")) {
formatterDay = FastDateFormat.getInstance("h:mm a", locale);
} else {
formatterDay = FastDateFormat.getInstance("h:mm a", Locale.US);}
}
public static String formatDateChat(long date) {
Calendar rightNow = Calendar.getInstance();
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date * 1000);
int dateYear = rightNow.get(Calendar.YEAR);
if (year == dateYear) {
return chatDate.format(date * 1000);
}
return chatFullDate.format(date * 1000);
}
public static String formatDate(long date) {
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date * 1000);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return formatterDay.format(new Date(date * 1000));
} else if (dateDay + 1 == day && year == dateYear) {
return applicationContext.getResources().getString(R.string.Yesterday);
} else if (year == dateYear) {
return formatterMonth.format(new Date(date * 1000));
} else {
return formatterYear.format(new Date(date * 1000));
}
}
public static String formatDateOnline(long date) {
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date * 1000);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return String.format("%s %s", applicationContext.getResources().getString(R.string.TodayAt), formatterDay.format(new Date(date * 1000)));
} else if (dateDay + 1 == day && year == dateYear) {
return String.format("%s %s", applicationContext.getResources().getString(R.string.YesterdayAt), formatterDay.format(new Date(date * 1000)));
} else if (year == dateYear) {
return String.format("%s %s %s", formatterMonth.format(new Date(date * 1000)), applicationContext.getResources().getString(R.string.OtherAt), formatterDay.format(new Date(date * 1000)));
} else {
return String.format("%s %s %s", formatterYear.format(new Date(date * 1000)), applicationContext.getResources().getString(R.string.OtherAt), formatterDay.format(new Date(date * 1000)));
}
}
public static void HideProgressDialog(Activity activity) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (progressDialog != null) {
progressDialog.dismiss();
}
}
});
}
public static boolean copyFile(File sourceFile, File destFile) throws IOException {
if(!destFile.exists()) {
destFile.createNewFile();
}
FileChannel source = null;
FileChannel destination = null;
boolean result = true;
try {
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destFile).getChannel();
destination.transferFrom(source, 0, source.size());
} catch (Exception e) {
e.printStackTrace();
result = false;
} finally {
if(source != null) {
source.close();
}
if(destination != null) {
destination.close();
}
}
return result;
}
public static void RunOnUIThread(Runnable runnable) {
synchronized (lock) {
if (applicationHandler == null) {
applicationHandler = new Handler(applicationContext.getMainLooper());
}
applicationHandler.post(runnable);
}
}
public static int[] arrColors = {0xffee4928, 0xff41a903, 0xffe09602, 0xff0f94ed, 0xff8f3bf7, 0xfffc4380, 0xff00a1c4, 0xffeb7002};
public static int[] arrUsersAvatars = {
R.drawable.user_placeholder_red,
R.drawable.user_placeholder_green,
R.drawable.user_placeholder_yellow,
R.drawable.user_placeholder_blue,
R.drawable.user_placeholder_purple,
R.drawable.user_placeholder_pink,
R.drawable.user_placeholder_cyan,
R.drawable.user_placeholder_orange};
public static int[] arrGroupsAvatars = {
R.drawable.group_placeholder_red,
R.drawable.group_placeholder_green,
R.drawable.group_placeholder_yellow,
R.drawable.group_placeholder_blue,
R.drawable.group_placeholder_purple,
R.drawable.group_placeholder_pink,
R.drawable.group_placeholder_cyan,
R.drawable.group_placeholder_orange};
public static int getColorIndex(int id) {
try {
String str = String.format(Locale.US, "%d%d", id, UserConfig.clientUserId);
if (str.length() > 15) {
str = str.substring(0, 15);
}
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] digest = md.digest(str.getBytes());
int b = digest[Math.abs(id % 16)];
if (b < 0) {
b += 256;
}
return Math.abs(b) % arrColors.length;
} catch (Exception e) {
e.printStackTrace();
}
return id % arrColors.length;
}
public static int getColorForId(int id) {
if (id == 333000) {
return 0xff0f94ed;
}
return arrColors[getColorIndex(id)];
}
public static int getUserAvatarForId(int id) {
if (id == 333000) {
return R.drawable.telegram_avatar;
}
return arrUsersAvatars[getColorIndex(id)];
}
public static int getGroupAvatarForId(int id) {
return arrGroupsAvatars[getColorIndex(id)];
}
public static String MD5(String md5) {
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] array = md.digest(md5.getBytes());
StringBuilder sb = new StringBuilder();
for (byte anArray : array) {
sb.append(Integer.toHexString((anArray & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static void addMediaToGallery(String fromPath) {
if (fromPath == null) {
return;
}
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(fromPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
applicationContext.sendBroadcast(mediaScanIntent);
}
public static void addMediaToGallery(Uri uri) {
if (uri == null) {
return;
}
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(uri);
applicationContext.sendBroadcast(mediaScanIntent);
}
private static File getAlbumDir() {
File storageDir = null;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), applicationContext.getResources().getString(R.string.AppName));
if (storageDir != null) {
if (! storageDir.mkdirs()) {
if (! storageDir.exists()){
Log.d("tmessages", "failed to create directory");
return null;
}
}
}
} else {
Log.v("tmessages", "External storage is not mounted READ/WRITE.");
}
return storageDir;
}
public static File generatePicturePath() {
try {
File storageDir = getAlbumDir();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp + "_";
return File.createTempFile(imageFileName, ".jpg", storageDir);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static CharSequence generateSearchName(String name, String name2, String q) {
if (name == null && name2 == null) {
return "";
}
int index;
SpannableStringBuilder builder = new SpannableStringBuilder();
String wholeString = name;
if (wholeString == null || wholeString.length() == 0) {
wholeString = name2;
} else if (name2 != null && name2.length() != 0) {
wholeString += " " + name2;
}
String[] args = wholeString.split(" ");
for (String arg : args) {
String str = arg;
if (str != null) {
String lower = str.toLowerCase();
if (lower.startsWith(q)) {
if (builder.length() != 0) {
builder.append(" ");
}
String query = str.substring(0, q.length());
builder.append(Html.fromHtml("<font color=\"#1274c9\">" + query + "</font>"));
str = str.substring(q.length());
builder.append(str);
} else {
if (builder.length() != 0) {
builder.append(" ");
}
builder.append(str);
}
}
}
return builder;
}
public static File generateVideoPath() {
try {
File storageDir = getAlbumDir();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "VID_" + timeStamp + "_";
return File.createTempFile(imageFileName, ".mp4", storageDir);
/*
String fileName = "VID" + id + ".mp4";
return new File(Utilities.applicationContext.getCacheDir(), fileName);
*/
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String formatName(String firstName, String lastName) {
String result = firstName;
if (result == null || result.length() == 0) {
result = lastName;
} else if (result.length() != 0 && lastName.length() != 0) {
result += " " + lastName;
}
return result;
}
}

View file

@ -0,0 +1,183 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.objects;
import android.graphics.Bitmap;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class MessageObject {
public TLRPC.Message messageOwner;
public CharSequence messageText;
public int type;
public ArrayList<PhotoObject> photoThumbs;
public Bitmap imagePreview;
public PhotoObject previewPhoto;
public String dateKey;
public boolean deleted = false;
public MessageObject(TLRPC.Message message, AbstractMap<Integer, TLRPC.User> users) {
messageOwner = message;
if (message instanceof TLRPC.TL_messageService) {
if (message.action != null) {
TLRPC.User fromUser = users.get(message.from_id);
if (fromUser == null) {
fromUser = MessagesController.Instance.users.get(message.from_id);
}
if (message.action instanceof TLRPC.TL_messageActionChatCreate) {
messageText = Utilities.applicationContext.getResources().getString(R.string.ActionCreateGroup).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else if (message.action instanceof TLRPC.TL_messageActionChatDeleteUser) {
if (message.action.user_id == message.from_id) {
messageText = Utilities.applicationContext.getResources().getString(R.string.ActionLeftUser).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
TLRPC.User who = users.get(message.action.user_id);
String str = Utilities.applicationContext.getResources().getString(R.string.ActionKickUser);
messageText = str.replace("un2", Utilities.formatName(who.first_name, who.last_name)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
}
} else if (message.action instanceof TLRPC.TL_messageActionChatAddUser) {
TLRPC.User whoUser = users.get(message.action.user_id);
String str = Utilities.applicationContext.getResources().getString(R.string.ActionAddUser);
messageText = str.replace("un2", Utilities.formatName(whoUser.first_name, whoUser.last_name)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
photoThumbs = new ArrayList<PhotoObject>();
for (TLRPC.PhotoSize size : message.action.photo.sizes) {
photoThumbs.add(new PhotoObject(size));
}
messageText = Utilities.applicationContext.getResources().getString(R.string.ActionChangedPhoto).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else if (message.action instanceof TLRPC.TL_messageActionChatEditTitle) {
messageText = Utilities.applicationContext.getResources().getString(R.string.ActionChangedTitle).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name)).replace("un2", message.action.title);
} else if (message.action instanceof TLRPC.TL_messageActionChatDeletePhoto) {
messageText = Utilities.applicationContext.getResources().getString(R.string.ActionRemovedPhoto).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else if (message.action instanceof TLRPC.TL_messageActionTTLChange) {
if (message.action.ttl != 0) {
String timeString;
if (message.action.ttl == 2) {
timeString = Utilities.applicationContext.getResources().getString(R.string.MessageLifetime2s);
} else if (message.action.ttl == 5) {
timeString = Utilities.applicationContext.getResources().getString(R.string.MessageLifetime5s);
} else if (message.action.ttl == 60) {
timeString = Utilities.applicationContext.getResources().getString(R.string.MessageLifetime1m);
} else if (message.action.ttl == 60 * 60) {
timeString = Utilities.applicationContext.getResources().getString(R.string.MessageLifetime1h);
} else if (message.action.ttl == 60 * 60 * 24) {
timeString = Utilities.applicationContext.getResources().getString(R.string.MessageLifetime1d);
} else if (message.action.ttl == 60 * 60 * 24 * 7) {
timeString = Utilities.applicationContext.getResources().getString(R.string.MessageLifetime1w);
} else {
timeString = String.format("%d", message.action.ttl);
}
if (message.from_id == UserConfig.clientUserId) {
messageText = String.format(Utilities.applicationContext.getResources().getString(R.string.MessageLifetimeChangedOutgoing), timeString);
} else {
messageText = String.format(Utilities.applicationContext.getResources().getString(R.string.MessageLifetimeChanged), fromUser.first_name, timeString);
}
} else {
if (message.from_id == UserConfig.clientUserId) {
messageText = String.format(Utilities.applicationContext.getResources().getString(R.string.MessageLifetimeRemoved), Utilities.applicationContext.getResources().getString(R.string.FromYou));
} else {
messageText = String.format(Utilities.applicationContext.getResources().getString(R.string.MessageLifetimeRemoved), fromUser.first_name);
}
}
}
}
} else if (message.media != null && !(message.media instanceof TLRPC.TL_messageMediaEmpty)) {
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
photoThumbs = new ArrayList<PhotoObject>();
for (TLRPC.PhotoSize size : message.media.photo.sizes) {
PhotoObject obj = new PhotoObject(size);
photoThumbs.add(obj);
if (imagePreview == null && obj.image != null) {
imagePreview = obj.image;
}
}
messageText = Utilities.applicationContext.getResources().getString(R.string.AttachPhoto);
} else if (message.media instanceof TLRPC.TL_messageMediaVideo) {
photoThumbs = new ArrayList<PhotoObject>();
PhotoObject obj = new PhotoObject(message.media.video.thumb);
photoThumbs.add(obj);
if (imagePreview == null && obj.image != null) {
imagePreview = obj.image;
}
messageText = Utilities.applicationContext.getResources().getString(R.string.AttachVideo);
} else if (message.media instanceof TLRPC.TL_messageMediaGeo) {
messageText = Utilities.applicationContext.getResources().getString(R.string.AttachLocation);
} else if (message.media instanceof TLRPC.TL_messageMediaContact) {
messageText = Utilities.applicationContext.getResources().getString(R.string.AttachContact);
}
} else {
messageText = message.message;
}
messageText = Emoji.replaceEmoji(messageText);
if (message instanceof TLRPC.TL_message || (message instanceof TLRPC.TL_messageForwarded && (message.media == null || !(message.media instanceof TLRPC.TL_messageMediaEmpty)))) {
if (message.media == null || message.media instanceof TLRPC.TL_messageMediaEmpty) {
if (message.from_id == UserConfig.clientUserId) {
type = 0;
} else {
type = 1;
}
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaPhoto) {
if (message.from_id == UserConfig.clientUserId) {
type = 2;
} else {
type = 3;
}
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaGeo) {
if (message.from_id == UserConfig.clientUserId) {
type = 4;
} else {
type = 5;
}
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaVideo) {
if (message.from_id == UserConfig.clientUserId) {
type = 6;
} else {
type = 7;
}
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaContact) {
if (message.from_id == UserConfig.clientUserId) {
type = 12;
} else {
type = 13;
}
}
} else if (message instanceof TLRPC.TL_messageService) {
if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
type = 11;
} else {
type = 10;
}
} else if (message instanceof TLRPC.TL_messageForwarded) {
if (message.from_id == UserConfig.clientUserId) {
type = 8;
} else {
type = 9;
}
}
Calendar rightNow = new GregorianCalendar();
rightNow.setTimeInMillis((long)(messageOwner.date) * 1000);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
int dateMonth = rightNow.get(Calendar.MONTH);
dateKey = String.format("%d_%02d_%02d", dateYear, dateMonth, dateDay);
}
}

View file

@ -0,0 +1,70 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.objects;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.FileLoader;
import java.util.ArrayList;
public class PhotoObject {
public TLRPC.PhotoSize photoOwner;
public Bitmap image;
public PhotoObject(TLRPC.PhotoSize photo) {
photoOwner = photo;
if (photo instanceof TLRPC.TL_photoCachedSize) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inPreferredConfig = Bitmap.Config.RGB_565;
opts.inDither = false;
opts.outWidth = photo.w;
opts.outHeight = photo.h;
image = BitmapFactory.decodeByteArray(photoOwner.bytes, 0, photoOwner.bytes.length, opts);
if (FileLoader.Instance.runtimeHack != null) {
FileLoader.Instance.runtimeHack.trackFree(image.getRowBytes() * image.getHeight());
}
}
}
public static PhotoObject getClosestImageWithSize(ArrayList<PhotoObject> arr, int width, int height) {
int closestWidth = 9999;
int closestHeight = 9999;
PhotoObject closestObject = null;
for (PhotoObject obj : arr) {
int diffW = Math.abs(obj.photoOwner.w - width);
int diffH = Math.abs(obj.photoOwner.h - height);
if (closestObject == null || closestWidth > diffW && closestHeight > diffH || closestObject.photoOwner instanceof TLRPC.TL_photoCachedSize) {
closestObject = obj;
closestWidth = diffW;
closestHeight = diffH;
}
}
return closestObject;
}
public static TLRPC.PhotoSize getClosestPhotoSizeWithSize(ArrayList<TLRPC.PhotoSize> sizes, int width, int height) {
int closestWidth = 9999;
int closestHeight = 9999;
TLRPC.PhotoSize closestObject = null;
for (TLRPC.PhotoSize obj : sizes) {
int diffW = Math.abs(obj.w - width);
int diffH = Math.abs(obj.h - height);
if (closestObject == null || closestWidth > diffW && closestHeight > diffH) {
closestObject = obj;
closestWidth = diffW;
closestHeight = diffH;
}
}
return closestObject;
}
}

View file

@ -0,0 +1,647 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.ui;
import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Html;
import android.view.Display;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.internal.app.ActionBarImpl;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.objects.MessageObject;
import org.telegram.ui.Views.BaseFragment;
import org.telegram.ui.Views.NotificationView;
import net.hockeyapp.android.CrashManager;
import net.hockeyapp.android.UpdateManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ApplicationActivity extends SherlockFragmentActivity implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate {
private View shadowView;
private boolean finished = false;
private NotificationView notificationView;
String photoPath = null;
String videoPath = null;
String sendingText = null;
private int currentConnectionState;
private View statusView;
private View backStatusButton;
private View statusBackground;
private TextView statusText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NotificationCenter.Instance.postNotificationName(702, this);
currentConnectionState = ConnectionsManager.Instance.connectionState;
for (BaseFragment fragment : ApplicationLoader.fragmentsStack) {
if (fragment.fragmentView != null) {
ViewGroup parent = (ViewGroup)fragment.fragmentView.getParent();
if (parent != null) {
parent.removeView(fragment.fragmentView);
}
fragment.parentActivity = null;
fragment.fragmentView = null;
}
}
setContentView(R.layout.application_layout);
notificationView = (NotificationView) getLayoutInflater().inflate(R.layout.notification_layout, null);
shadowView = findViewById(R.id.shadow);
NotificationCenter.Instance.addObserver(this, 1234);
NotificationCenter.Instance.addObserver(this, 658);
NotificationCenter.Instance.addObserver(this, 701);
NotificationCenter.Instance.addObserver(this, 702);
NotificationCenter.Instance.addObserver(this, 703);
NotificationCenter.Instance.addObserver(this, GalleryImageViewer.needShowAllMedia);
getSupportActionBar().setLogo(R.drawable.ab_icon_fixed2);
statusView = getLayoutInflater().inflate(R.layout.updating_state_layout, null);
statusBackground = statusView.findViewById(R.id.back_button_background);
backStatusButton = statusView.findViewById(R.id.back_button);
statusText = (TextView)statusView.findViewById(R.id.status_text);
statusBackground.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (ApplicationLoader.fragmentsStack.size() > 1) {
onBackPressed();
}
}
});
if (ApplicationLoader.fragmentsStack.isEmpty()) {
MessagesActivity fragment = new MessagesActivity();
fragment.onFragmentCreate();
ApplicationLoader.fragmentsStack.add(fragment);
}
boolean pushOpened = false;
Integer push_user_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_user_id", 0);
Integer push_chat_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_chat_id", 0);
Integer push_enc_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_enc_id", 0);
Integer open_settings = (Integer)NotificationCenter.Instance.getFromMemCache("open_settings", 0);
photoPath = (String)NotificationCenter.Instance.getFromMemCache(533);
videoPath = (String)NotificationCenter.Instance.getFromMemCache(534);
sendingText = (String)NotificationCenter.Instance.getFromMemCache(535);
if (push_user_id != 0) {
if (push_user_id == UserConfig.clientUserId) {
open_settings = 1;
} else {
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("user_id", push_user_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
pushOpened = true;
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_user_" + push_user_id).commitAllowingStateLoss();
}
}
} else if (push_chat_id != 0) {
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("chat_id", push_chat_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
pushOpened = true;
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_group_" + push_chat_id).commitAllowingStateLoss();
}
} else if (push_enc_id != 0) {
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("enc_id", push_enc_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
pushOpened = true;
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_enc_" + push_enc_id).commitAllowingStateLoss();
}
}
if (videoPath != null || photoPath != null || sendingText != null) {
MessagesActivity fragment = new MessagesActivity();
fragment.selectAlertString = R.string.ForwardMessagesTo;
fragment.animationType = 1;
Bundle args = new Bundle();
args.putBoolean("onlySelect", true);
fragment.setArguments(args);
fragment.delegate = this;
ApplicationLoader.fragmentsStack.add(fragment);
fragment.onFragmentCreate();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, fragment.getTag()).commitAllowingStateLoss();
pushOpened = true;
}
if (open_settings != 0) {
SettingsActivity fragment = new SettingsActivity();
ApplicationLoader.fragmentsStack.add(fragment);
fragment.onFragmentCreate();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "settings").commitAllowingStateLoss();
pushOpened = true;
}
if (!pushOpened) {
BaseFragment fragment = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 1);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, fragment.getTag()).commitAllowingStateLoss();
}
getWindow().setBackgroundDrawableResource(R.drawable.transparent);
}
@SuppressWarnings("unchecked")
private void prepareForHideShowActionBar() {
try {
Class aClass = getSupportActionBar().getClass();
if (aClass == ActionBarImpl.class) {
Method method = aClass.getDeclaredMethod("setShowHideAnimationEnabled", boolean.class);
method.invoke(getSupportActionBar(), false);
} else {
Field field = aClass.getDeclaredField("mActionBar");
field.setAccessible(true);
Method method = field.get(getSupportActionBar()).getClass().getDeclaredMethod("setShowHideAnimationEnabled", boolean.class);
method.invoke(field.get(getSupportActionBar()), false);
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
public void showActionBar() {
prepareForHideShowActionBar();
shadowView.setVisibility(View.VISIBLE);
getSupportActionBar().show();
}
public void hideActionBar() {
prepareForHideShowActionBar();
shadowView.setVisibility(View.INVISIBLE);
getSupportActionBar().hide();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
photoPath = (String)NotificationCenter.Instance.getFromMemCache(533);
videoPath = (String)NotificationCenter.Instance.getFromMemCache(534);
sendingText = (String)NotificationCenter.Instance.getFromMemCache(535);
if (videoPath != null || photoPath != null || sendingText != null) {
MessagesActivity fragment = new MessagesActivity();
fragment.selectAlertString = R.string.ForwardMessagesTo;
fragment.animationType = 1;
Bundle args = new Bundle();
args.putBoolean("onlySelect", true);
fragment.setArguments(args);
fragment.delegate = this;
ApplicationLoader.fragmentsStack.add(fragment);
fragment.onFragmentCreate();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, fragment.getTag()).commitAllowingStateLoss();
}
Integer push_user_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_user_id", 0);
Integer push_chat_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_chat_id", 0);
Integer push_enc_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_enc_id", 0);
Integer open_settings = (Integer)NotificationCenter.Instance.getFromMemCache("open_settings", 0);
if (push_user_id != 0) {
if (push_user_id == UserConfig.clientUserId) {
open_settings = 1;
} else {
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("user_id", push_user_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_user_" + push_user_id).commitAllowingStateLoss();
}
}
} else if (push_chat_id != 0) {
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("chat_id", push_chat_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_group_" + push_chat_id).commitAllowingStateLoss();
}
} else if (push_enc_id != 0) {
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("enc_id", push_enc_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_enc_" + push_enc_id).commitAllowingStateLoss();
}
}
if (open_settings != 0) {
SettingsActivity fragment = new SettingsActivity();
ApplicationLoader.fragmentsStack.add(fragment);
fragment.onFragmentCreate();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "settings").commitAllowingStateLoss();
}
}
@Override
public void didSelectDialog(MessagesActivity messageFragment, long dialog_id) {
if (dialog_id != 0) {
int lower_part = (int)dialog_id;
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
if (lower_part != 0) {
if (lower_part > 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
bundle.putInt("user_id", lower_part);
fragment.setArguments(bundle);
fragment.scrollToTopOnResume = true;
presentFragment(fragment, "chat_user_" + lower_part, true, false);
} else if (lower_part < 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
bundle.putInt("chat_id", -lower_part);
fragment.setArguments(bundle);
fragment.scrollToTopOnResume = true;
presentFragment(fragment, "chat_group_" + -lower_part, true, false);
}
} else {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
int chat_id = (int)(dialog_id >> 32);
bundle.putInt("enc_id", chat_id);
fragment.setArguments(bundle);
fragment.scrollToTopOnResume = true;
presentFragment(fragment, "chat_enc_" + chat_id, true, false);
}
if (photoPath != null) {
fragment.processSendingPhoto(photoPath);
} else if (videoPath != null) {
fragment.processSendingVideo(videoPath);
} else if (sendingText != null) {
fragment.processSendingText(sendingText);
}
photoPath = null;
videoPath = null;
sendingText = null;
}
}
private void checkForCrashes() {
CrashManager.register(this, "your-hockeyapp-api-key-here");
}
private void checkForUpdates() {
if (ConnectionsManager.DEBUG_VERSION) {
UpdateManager.register(this, "your-hockeyapp-api-key-here");
}
}
@Override
protected void onPause() {
super.onPause();
ApplicationLoader.lastPauseTime = System.currentTimeMillis();
if (notificationView != null) {
notificationView.hide(false);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
processOnFinish();
}
@Override
protected void onResume() {
super.onResume();
fixLayout();
checkForCrashes();
checkForUpdates();
ApplicationLoader.lastPauseTime = 0;
invalidateOptionsMenu();
updateActionBar();
try {
NotificationManager mNotificationManager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(1);
} catch (Exception e) {
e.printStackTrace();
}
}
private void processOnFinish() {
if (finished) {
return;
}
finished = true;
NotificationCenter.Instance.removeObserver(this, 1234);
NotificationCenter.Instance.removeObserver(this, 658);
NotificationCenter.Instance.removeObserver(this, 701);
NotificationCenter.Instance.removeObserver(this, 702);
NotificationCenter.Instance.removeObserver(this, 703);
NotificationCenter.Instance.removeObserver(this, GalleryImageViewer.needShowAllMedia);
if (notificationView != null) {
notificationView.hide(false);
notificationView.destroy();
notificationView = null;
}
}
@Override
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
private void fixLayout() {
if (shadowView != null) {
ViewTreeObserver obs = shadowView.getViewTreeObserver();
obs.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
float density = Utilities.applicationContext.getResources().getDisplayMetrics().density;
int height;
int currentActionBarHeight = getSupportActionBar().getHeight();
if (currentActionBarHeight != 48 * density && currentActionBarHeight != 40 * density) {
height = currentActionBarHeight;
} else {
height = (int) (48.0f * density);
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
height = (int) (40.0f * density);
}
}
if (notificationView != null) {
notificationView.applyOrientationPaddings(rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90, density, height);
}
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) shadowView.getLayoutParams();
params.setMargins(0, height, 0, 0);
shadowView.setLayoutParams(params);
if (Build.VERSION.SDK_INT < 16) {
shadowView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
shadowView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
}
}
@Override
@SuppressWarnings("unchecked")
public void didReceivedNotification(int id, Object... args) {
if (id == 1234) {
for (BaseFragment fragment : ApplicationLoader.fragmentsStack) {
fragment.onFragmentDestroy();
}
ApplicationLoader.fragmentsStack.clear();
Intent intent2 = new Intent(this, LaunchActivity.class);
startActivity(intent2);
processOnFinish();
finish();
} else if (id == GalleryImageViewer.needShowAllMedia) {
long dialog_id = (Long)args[0];
MediaActivity fragment = new MediaActivity();
Bundle bundle = new Bundle();
if (dialog_id != 0) {
bundle.putLong("dialog_id", dialog_id);
fragment.setArguments(bundle);
presentFragment(fragment, "media_" + dialog_id, false);
}
} else if (id == 658) {
Integer push_user_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_user_id", 0);
Integer push_chat_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_chat_id", 0);
Integer push_enc_id = (Integer)NotificationCenter.Instance.getFromMemCache("push_enc_id", 0);
if (push_user_id != 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("user_id", push_user_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
if (ApplicationLoader.fragmentsStack.size() > 0) {
BaseFragment lastFragment = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 1);
lastFragment.willBeHidden();
}
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_user_" + push_user_id).commitAllowingStateLoss();
}
} else if (push_chat_id != 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("chat_id", push_chat_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
if (ApplicationLoader.fragmentsStack.size() > 0) {
BaseFragment lastFragment = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 1);
lastFragment.willBeHidden();
}
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_group_" + push_chat_id).commitAllowingStateLoss();
}
} else if (push_enc_id != 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
ChatActivity fragment = new ChatActivity();
Bundle bundle = new Bundle();
bundle.putInt("enc_id", push_enc_id);
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
if (ApplicationLoader.fragmentsStack.size() > 0) {
BaseFragment lastFragment = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 1);
lastFragment.willBeHidden();
}
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_enc_" + push_enc_id).commitAllowingStateLoss();
}
}
} else if (id == 701) {
if (notificationView != null) {
MessageObject message = (MessageObject)args[0];
notificationView.show(message);
}
} else if (id == 702) {
if (args[0] != this) {
processOnFinish();
}
} else if (id == 703) {
int state = (Integer)args[0];
if (currentConnectionState != state) {
currentConnectionState = state;
updateActionBar();
}
}
}
public void updateActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar == null) {
return;
}
BaseFragment currentFragment = null;
if (!ApplicationLoader.fragmentsStack.isEmpty()) {
currentFragment = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 1);
}
boolean canApplyLoading = true;
if (currentFragment != null && (currentConnectionState == 0 || !currentFragment.canApplyUpdateStatus() || statusView == null)) {
currentFragment.applySelfActionBar();
canApplyLoading = false;
}
if (canApplyLoading) {
if (statusView != null) {
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setSubtitle(null);
if (ApplicationLoader.fragmentsStack.size() > 1) {
backStatusButton.setVisibility(View.VISIBLE);
statusBackground.setEnabled(true);
} else {
backStatusButton.setVisibility(View.GONE);
statusBackground.setEnabled(false);
}
if (currentConnectionState == 1) {
statusText.setText(Html.fromHtml("<font color='#006fc8'>" + getString(R.string.WaitingForNetwork) + "</font>"));
} else if (currentConnectionState == 2) {
statusText.setText(Html.fromHtml("<font color='#006fc8'>" + getString(R.string.Connecting) + "</font>"));
} else if (currentConnectionState == 3) {
statusText.setText(Html.fromHtml("<font color='#006fc8'>" + getString(R.string.Updating) + "</font>"));
}
if (actionBar.getCustomView() != statusView) {
actionBar.setCustomView(statusView);
}
}
}
}
public void presentFragment(BaseFragment fragment, String tag, boolean bySwipe) {
presentFragment(fragment, tag, false, bySwipe);
}
public void presentFragment(BaseFragment fragment, String tag, boolean removeLast, boolean bySwipe) {
if (getCurrentFocus() != null) {
Utilities.hideKeyboard(getCurrentFocus());
}
if (!fragment.onFragmentCreate()) {
return;
}
BaseFragment current = null;
if (!ApplicationLoader.fragmentsStack.isEmpty()) {
current = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 1);
}
if (current != null) {
current.willBeHidden();
}
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction fTrans = fm.beginTransaction();
if (removeLast && current != null) {
ApplicationLoader.fragmentsStack.remove(ApplicationLoader.fragmentsStack.size() - 1);
current.onFragmentDestroy();
}
SharedPreferences preferences = Utilities.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
boolean animations = preferences.getBoolean("view_animations", true);
if (animations) {
if (bySwipe) {
fTrans.setCustomAnimations(R.anim.slide_left, R.anim.no_anim);
} else {
fTrans.setCustomAnimations(R.anim.scale_in, R.anim.no_anim);
}
}
fTrans.replace(R.id.container, fragment, tag);
fTrans.commitAllowingStateLoss();
ApplicationLoader.fragmentsStack.add(fragment);
}
public void removeFromStack(BaseFragment fragment) {
ApplicationLoader.fragmentsStack.remove(fragment);
fragment.onFragmentDestroy();
}
public void finishFragment(boolean bySwipe) {
if (getCurrentFocus() != null) {
Utilities.hideKeyboard(getCurrentFocus());
}
if (ApplicationLoader.fragmentsStack.size() < 2) {
for (BaseFragment fragment : ApplicationLoader.fragmentsStack) {
fragment.onFragmentDestroy();
}
ApplicationLoader.fragmentsStack.clear();
MessagesActivity fragment = new MessagesActivity();
fragment.onFragmentCreate();
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chats").commitAllowingStateLoss();
return;
}
BaseFragment fragment = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 1);
fragment.onFragmentDestroy();
BaseFragment prev = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 2);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction fTrans = fm.beginTransaction();
SharedPreferences preferences = Utilities.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
boolean animations = preferences.getBoolean("view_animations", true);
if (animations) {
if (bySwipe) {
fTrans.setCustomAnimations(R.anim.no_anim_show, R.anim.slide_right_away);
} else {
fTrans.setCustomAnimations(R.anim.no_anim_show, R.anim.scale_out);
}
}
fTrans.replace(R.id.container, prev, prev.getTag());
fTrans.commitAllowingStateLoss();
ApplicationLoader.fragmentsStack.remove(ApplicationLoader.fragmentsStack.size() - 1);
}
@Override
public void onBackPressed() {
if (ApplicationLoader.fragmentsStack.size() == 1) {
ApplicationLoader.fragmentsStack.get(0).onFragmentDestroy();
ApplicationLoader.fragmentsStack.clear();
processOnFinish();
finish();
return;
}
if (!ApplicationLoader.fragmentsStack.isEmpty()) {
BaseFragment lastFragment = ApplicationLoader.fragmentsStack.get(ApplicationLoader.fragmentsStack.size() - 1);
if (lastFragment.onBackPressed()) {
finishFragment(false);
}
}
}
}

View file

@ -0,0 +1,209 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.ui;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.util.Log;
import android.view.ViewConfiguration;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.BaseFragment;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
public class ApplicationLoader extends Application {
private GoogleCloudMessaging gcm;
private AtomicInteger msgId = new AtomicInteger();
private String regid;
private String SENDER_ID = "760348033672";
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
public static long lastPauseTime;
public static Bitmap cachedWallpaper = null;
public static ApplicationLoader Instance = null;
public static ArrayList<BaseFragment> fragmentsStack = new ArrayList<BaseFragment>();
@Override
public void onCreate() {
super.onCreate();
Instance = this;
java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
Utilities.applicationContext = getApplicationContext();
UserConfig.loadConfig();
SharedPreferences preferences = getSharedPreferences("Notifications", MODE_PRIVATE);
if (UserConfig.currentUser != null) {
int value = preferences.getInt("version", 0);
if (value != 15) {
UserConfig.contactsHash = "";
UserConfig.lastDateValue = 0;
UserConfig.lastPtsValue = 0;
UserConfig.lastSeqValue = 0;
UserConfig.lastQtsValue = 0;
UserConfig.saveConfig();
MessagesStorage.Instance.cleanUp();
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
users.add(UserConfig.currentUser);
MessagesStorage.Instance.putUsersAndChats(users, null, true, true);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("version", 15);
editor.commit();
}
MessagesController.Instance.users.put(UserConfig.clientUserId, UserConfig.currentUser);
} else {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("version", 15);
editor.commit();
}
MessagesController.Instance.checkAppAccount();
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if(menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
}
if (checkPlayServices()) {
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(Utilities.applicationContext);
if (regid.length() == 0) {
registerInBackground();
} else {
sendRegistrationIdToBackend(false);
}
} else {
Log.i("tmessages", "No valid Google Play Services APK found.");
}
PhoneFormat format = PhoneFormat.Instance;
lastPauseTime = System.currentTimeMillis() - 5000;
if (ConnectionsManager.DEBUG_VERSION) {
Log.e("tmessages", "start application with time " + lastPauseTime);
}
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
return resultCode == ConnectionResult.SUCCESS;
/*if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Log.i("tmessages", "This device is not supported.");
}
return false;
}
return true;*/
}
private String getRegistrationId(Context context) {
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.length() == 0) {
Log.i("tmessages", "Registration not found.");
return "";
}
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
Log.i("tmessages", "App version changed.");
return "";
}
return registrationId;
}
private SharedPreferences getGCMPreferences(Context context) {
return getSharedPreferences(ApplicationLoader.class.getSimpleName(), Context.MODE_PRIVATE);
}
private static int getAppVersion(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException("Could not get package name: " + e);
}
}
private void registerInBackground() {
AsyncTask<String, String, Boolean> task = new AsyncTask<String, String, Boolean>() {
@Override
protected Boolean doInBackground(String... objects) {
String msg;
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(Utilities.applicationContext);
}
regid = gcm.register(SENDER_ID);
sendRegistrationIdToBackend(true);
storeRegistrationId(Utilities.applicationContext, regid);
return true;
} catch (IOException ex) {
ex.printStackTrace();
}
return false;
}
}.execute(null, null, null);
}
private void sendRegistrationIdToBackend(final boolean isNew) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
UserConfig.pushString = regid;
UserConfig.registeredForPush = !isNew;
UserConfig.saveConfig();
MessagesController.Instance.registerForPush(regid);
}
});
}
private void storeRegistrationId(Context context, String regId) {
final SharedPreferences prefs = getGCMPreferences(context);
int appVersion = getAppVersion(context);
Log.i("tmessages", "Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.putInt(PROPERTY_APP_VERSION, appVersion);
editor.commit();
}
}

Some files were not shown because too many files have changed in this diff Show more