Compare commits

...

308 Commits

Author SHA1 Message Date
Moxie Marlinspike
da03b38c84 Bump version to 2.10.0
// FREEBIE
2015-04-03 08:47:22 -07:00
Moxie Marlinspike
1d71a32b41 Update language translations.
// FREEBIE
2015-04-03 08:30:47 -07:00
Moxie Marlinspike
0efdada928 Prompt user to rate app
Closes #2841

// FREEBIE
2015-04-02 17:30:30 -07:00
Jake McGinty
0c7dba6d43 Pass MasterSecret into pref fragments
Fixes #2868
Closes #2870

// FREEBIE
2015-04-02 17:22:33 -07:00
Jake McGinty
c50658a4f5 Revert "Fix re-registering missing MasterSecret"
This reverts commit beceee846a.
2015-04-02 17:22:31 -07:00
McLoo
afd6ab75f8 Close keyboard when entering message detail view
Fixes #2598
Close #2802

//FREEBIE
2015-04-02 14:52:22 -07:00
Jake McGinty
597f7bbafd refactor proguard rules
// FREEBIE
2015-04-02 14:49:45 -07:00
Rhodey Orbits
87760a795d Add "new message to <number>" always.
Fixes #2660
Closes #2854

// FREEBIE
2015-04-02 14:32:25 -07:00
Rhodey Orbits
f4fe024e50 Correct default value of 'pref_key_ringtone'.
Fixes #2793
Closes #2831

// FREEBIE
2015-04-02 14:31:19 -07:00
Moxie Marlinspike
797b296f3a Break long filter thread id calls up into chunks of 900.
// FREEBIE

Fixes #2462
Closes #2860
2015-04-02 14:27:00 -07:00
Moxie Marlinspike
b8a231c40f Remove dynamicLanguage/dynamicTheme from VerifyIdentityActivity
This already happens in the parent.

Fixes #2853

// FREEBIE
2015-04-02 14:08:10 -07:00
Jake McGinty
5cb94f02b3 Fix failed SMIL generation when part name is null
Fixes #2851
Closes #2866

// FREEBIE
2015-04-02 13:43:44 -07:00
Rhodey Orbits
db7a657001 fix LoaderManager inefficiencies
Redundant calls in ConversationActivity and ConversationListActivity
was causing unnecessary view invalidations.

Closes #2592
2015-04-02 13:33:23 -07:00
Jake McGinty
ca2c8b961e Fix sharing text via ShareActivity intents
Fixes #2855
Closes #2865

// FREEBIE
2015-04-02 12:04:39 -07:00
Rhodey Orbits
4e4538f4e8 Remove broken tests
1) removed old, unused, and broken MmsReceiverTest.
2) removed RegistrationActivityTest which got entirely broken
   when 8573316fdf removed the
   Class it inherited from (RoutedInstrumentationTestCase).

all tests in connectedCheck target now passing on Nexus One
 GB test device.

Closes #2864

// FREEBIE
2015-04-02 11:37:02 -07:00
Jake McGinty
796c5de5d5 Fix crash when username is null in mms auth
Fixes #2850
Closes #2863

// FREEBIE
2015-04-02 11:35:27 -07:00
Jake McGinty
beceee846a Fix re-registering missing MasterSecret
// FREEBIE

Closes #2861
2015-04-02 11:33:30 -07:00
Carey Metcalfe
8573316fdf Remove obsolete RoutingActivity test
Closes #2857
2015-04-01 17:11:28 -07:00
Jake McGinty
6c59eb052e Prevent crash from strange SQLite error
Full fix may require packaging and using our own SQLite via JNI. Needs
further investigation.

Fixes #2506
Closes #2843

// FREEBIE
2015-04-01 10:23:05 -07:00
Jake McGinty
0ff99258ac move routing logic to all activities
Fixes #2239
Closes #27923

// FREEBIE
2015-04-01 10:23:05 -07:00
Jake McGinty
141ee6565d add @Nullable annotation to outoging mms api
Closes #2830

// FREEBIE
2015-04-01 10:23:05 -07:00
xrazvan
38fa4e91fa Update arrays.xml - Fixed misspeling for Romanian language
Closes #2826
2015-04-01 10:20:31 -07:00
Jake McGinty
2f20bb89f3 use internal emoji pane for all android versions
1) Enter key by default (remove as option), still
   keeping "Enter key sends" option

2) New material assets for emoji and keyboard icons,
   inc a xxhdpi version finally

fixes #2300, fixes #2251, fixes #2183

Closes #2302

// FREEBIE
2015-04-01 10:20:31 -07:00
Jake McGinty
c04b675a1a Fix null-response NPE in outgoing MMS
Fixes #2839
Closes #2840

// FREEBIE
2015-03-31 10:53:20 -07:00
Moxie Marlinspike
e70298e624 Catch malformed NOTIFY-IND
Fixes #2508

// FREEBIE
2015-03-31 09:12:22 -07:00
Poly
6181dc4037 Fixed Typo in README
Closes #2822

// FREEBIE
2015-03-30 15:37:37 -07:00
Moxie Marlinspike
9b0cae1d45 Bump version to 2.9.3
// FREEBIE
2015-03-30 11:35:49 -07:00
Jake McGinty
491440094b Fix NPE when RetrieveConf is null
Fixes #2828
Closes #2829
// FREEBIE
2015-03-30 10:50:55 -07:00
agrajaghh
e6b2d31db7 add Code style Guidlines to contributing.md
Closes #2472

//FREEBIE
2015-03-27 16:09:19 -07:00
Moxie Marlinspike
0ca8a480c5 Bump version to 2.9.2
// FREEBIE
2015-03-27 15:29:54 -07:00
Jake McGinty
349faf18fa Fix missing timestamp in SendReq
// FREEBIE
2015-03-27 15:02:01 -07:00
Moxie Marlinspike
88ed8f3887 Bump version to 2.9.1
// FREEBIE
2015-03-27 11:19:20 -07:00
Jake McGinty
6a6f900b7d Fix NPE when 'from' missing in NotificationInd
Fixes #2806
// FREEBIE
2015-03-27 10:59:04 -07:00
Jake McGinty
17383ddfe0 fix NPE for incoming failed messages
Fixes #2807
// FREEBIE
2015-03-27 10:37:59 -07:00
agrajaghh
1b846c0842 remove unused resources
Closes #2594

//FREEBIE
2015-03-26 16:29:32 -07:00
Sam Whited
dbda758841 Add pref to change MMS user agent
Closes #2363

// FREEBIE
2015-03-26 15:48:53 -07:00
Moxie Marlinspike
c6b3bb9f13 Bump version to 2.9.0
// FREEBIE
2015-03-26 11:28:39 -07:00
Moxie Marlinspike
bdeeea2e46 Update language translations.
// FREEBIE
2015-03-26 11:13:55 -07:00
Jake McGinty
427c9a6b21 Use new MMS APIs in Lollipop onwards
Fixes #1937
Closes #2727
2015-03-26 11:05:41 -07:00
Moxie Marlinspike
dfda2f733c Upgrade to libtextsecure 1.2.4
Fixes #2790

// FREEBIE
2015-03-25 14:13:53 -07:00
agrajaghh
6f600a80b8 fix merge conflict between #2743 and #2746
Closes #2789

//FREEBIE
2015-03-25 13:28:57 -07:00
agrajaghh
62181a3d7f migrate AlertDialog to material-dialogs
Closes #2743
2015-03-25 11:50:52 -07:00
Moxie Marlinspike
6c386d3fc9 Add http to invite url.
// FREEBIE
2015-03-25 11:18:38 -07:00
Moxie Marlinspike
b9e6cff20c Fix the build
Fixes #2787
2015-03-25 10:55:47 -07:00
Moxie Marlinspike
d65a7f1a25 Update invite strings.
// FREEBIE

Closes #2735
2015-03-25 10:49:52 -07:00
Rhodey Orbits
76d0f45b9b append invite link to message draft instead of overwrite it.
Fixes #2583
// FREEBIE
2015-03-25 10:36:36 -07:00
agrajaghh
3a19ac432b Display the phone number in the confirm dialog during registration
Closes #2746
2015-03-25 09:24:28 -07:00
NorthwestBased
6ec9ee89a7 Disallow zero-length passphrases.
Fixes #2751
Closes #2762
2015-03-25 09:19:53 -07:00
Moxie Marlinspike
472179b550 Ignores MMS WAP_PUSH_DELIVER_ACTION if we're not the default app.
Apparently some ROMs have a bug where they broadcast
WAP_PUSH_DELIVER_ACTION even when you're not the system's default
SMS/MMS app.

Fixes #2777
2015-03-25 08:57:08 -07:00
Rhodey Orbits
f38bd7b187 fix initialization of emoji cache
Fixes #2700
Closes #2719

// FREEBIE
2015-03-23 15:02:31 -07:00
Jake McGinty
b73143d7a7 fix send button assets
Closes #2757

// FREEBIE
2015-03-23 13:54:37 -07:00
Jake McGinty
9a2c372c23 fix crash on android contact weirdness
Fixes #2722
Closes #2758

// FREEBIE
2015-03-23 13:53:22 -07:00
Moxie Marlinspike
b21369b7bc Bump version to 2.8.0
// FREEBIE
2015-03-19 12:55:41 -07:00
Moxie Marlinspike
5939a1f995 Upgrade libtextsecure to 1.2.3
// FREEBIE
2015-03-19 12:41:07 -07:00
Moxie Marlinspike
e4b73e90e1 Update language translations
// FREEBIE
2015-03-19 12:02:58 -07:00
Jake McGinty
073d019103 Fix SMIL regression
Closes #2654

// FREEBIE
2015-03-19 11:56:45 -07:00
Jake McGinty
761ccf4b3f Fix for inconsistent thumbnail aspect ratio
Problems arose from any app that targets below API 19 and uses
views that rely on RelativeLayouts giving correct measurement specs to
their onMeasure().

Resolves #2676
Closes #2712
// FREEBIE
2015-03-19 11:21:40 -07:00
Moxie Marlinspike
7a023b9fdc Acquire wakelocks for incoming messages.
Closes #2717

// FREEBIE
2015-03-19 11:19:53 -07:00
Jake McGinty
9f804047f5 lazily initialize emoji drawer
Saves a good amount of inflation time in onCreate for new conversations.

Closes #2585
Closes #2636

// FREEBIE
2015-03-19 11:16:52 -07:00
Rhodey Orbits
a625727853 String should not be compared with an Optional in DeliveryReceiptJobTest.testDelivery().
Closes #2713

// FREEBIE
2015-03-18 14:28:29 -07:00
Moxie Marlinspike
e0737451db Bump version to 2.7.1
// FREEBIE
2015-03-17 10:21:12 -07:00
agrajaghh
0f572d1e5d adapt SMS strings in preferences
Fixes #2672
Closes #2682

//FREEBIE
2015-03-16 11:02:22 -07:00
Moxie Marlinspike
142f84703b Make clickable conversation items batch selectable
Fixes #2679

// FREEBIE
2015-03-16 10:32:39 -07:00
Jake McGinty
b47bd97e9e fix message details 12-hour time formatting
Resolves #2695
// FREEBIE
2015-03-15 20:28:23 -07:00
Jake McGinty
4099303d1f make dark theme go less wild
Resolves #2675
Closes #2693

// FREEBIE
2015-03-15 09:33:10 -07:00
Jake McGinty
71eeb7ca83 Fix ClassCastException for notifications
Resolves #2691
Closes #2692

// FREEBIE
2015-03-15 09:31:21 -07:00
Jake McGinty
186a5e4dfc update libpastelog to 1.0.6
adds memory information to debug output
// FREEBIE
2015-03-13 17:52:31 -07:00
Moxie Marlinspike
0d84ec51a8 Update README with beta instructions.
// FREEBIE
2015-03-13 12:16:13 -07:00
Moxie Marlinspike
6c9ed77e5f Bump version to 2.7.0-B1
// FREEBIE
2015-03-13 12:09:56 -07:00
Moxie Marlinspike
fc3aaed8a8 Remove unused layouts and strings.
// FREEBIE
2015-03-13 11:58:49 -07:00
Moxie Marlinspike
c72cc1b49c Updated language translations.
// FREEBIE
2015-03-13 11:43:49 -07:00
Jake McGinty
13227b6aa5 disable fancy new thumbnail preview
It was causing OOMEs on old devices.
// FREEBIE
2015-03-13 11:30:15 -07:00
Moxie Marlinspike
cc65fab226 Update message details activity display when resending SMS/MMS
// FREEBIE
2015-03-13 11:29:44 -07:00
agrajaghh
dee2e0906e remove "Complete key exchanges" from advanced options
Closes #2664

//FREEBIE
2015-03-13 12:09:37 +01:00
Moxie Marlinspike
e142cb6d26 Prompt for registration on install until successful.
Closes #2657

// FREEBIE
2015-03-12 18:36:34 -07:00
Jake McGinty
4185006147 add borderless thumbnails, "bubble" refactor
Closes #2430

// FREEBIE
2015-03-12 18:23:08 -07:00
Moxie Marlinspike
a4e18c515c Remove encrypted SMS transport, simplify transport options.
Closes #2647

// FREEBIE
2015-03-12 17:53:38 -07:00
Rhodey Orbits
2011391e65 Fix notifications for media messages without text.
They now read 'media message' in italics.

Closes #2649
2015-03-12 17:30:23 -07:00
Jake McGinty
96896bf8f1 disconnect radio regardless of MMS exception
Fixes #2498
Closes #2544
// FREEBIE
2015-03-12 12:29:32 -07:00
agrajaghh
ac312ff5d5 change FAB icon to ic_create and add more resolutions to ic_add
Closes #2634

//FREEBIE
2015-03-12 11:31:03 -07:00
agrajaghh
b3552ee347 add dynamicTheme and dynamicLanguage to MessageDetailsActivity
Closes #2640

//FREEBIE
2015-03-12 11:22:12 -07:00
Jake McGinty
b998c5f86c Add missing MSISDN headers to MMS send request
Fixes #1935
Fixes #2451
Closes #2605

// FREEBIE
2015-03-12 11:18:20 -07:00
Jake McGinty
0b8430ff43 update APN list, fix MMSC issues
Fixes #2413
Closes #2606

// FREEBIE
2015-03-12 11:15:14 -07:00
Moxie Marlinspike
3e80032c18 Bump version to 2.6.4
// FREEBIE
2015-03-11 09:24:28 -07:00
Moxie Marlinspike
41fadc3437 Use libtextsecure 1.2.2
// FREEBIE
2015-03-10 18:59:12 -07:00
Moxie Marlinspike
c1fe585ffb Bump version to 2.6.3
// FREEBIE
2015-03-09 13:32:11 -07:00
Moxie Marlinspike
078df0f029 Update key conflict message in place.
// FREEBIE
2015-03-09 13:15:24 -07:00
Moxie Marlinspike
9f9293cd61 Pending indicator was not cleared on recycled views.
// FREEBIE
2015-03-09 13:14:39 -07:00
Moxie Marlinspike
4e87513867 Bump version to 2.6.2
// FREEBIE
2015-03-08 11:45:56 -07:00
Moxie Marlinspike
c05aca19ae Minimal-diff change to fix NPE.
Fixes #2623

// FREEBIE
2015-03-08 11:37:18 -07:00
Moxie Marlinspike
db2c7fabe1 Bump version to 2.6.1
// FREEBIE
2015-03-07 09:28:28 -08:00
Moxie Marlinspike
e7eb0ec2b3 Fix for missing messages bug
Fixes #2609

// FREEBIE
2015-03-07 09:02:59 -08:00
Moxie Marlinspike
da75268545 Temporary fix until jake fixes this shit
// FREEBIE
2015-03-07 09:02:38 -08:00
Moxie Marlinspike
49ab1e7bd5 Bump version to 2.6.0
// FREEBIE
2015-03-06 11:07:53 -08:00
Moxie Marlinspike
b5a2d7882a Updated language translations.
// FREEBIE
2015-03-06 10:10:34 -08:00
Moxie Marlinspike
534df06794 Support granular "custom" MMS preferences.
1) Make each MMS preference an individual choice between custom
   and default.

2) Display default values.

Closes #2487

// FREEBIE
2015-03-05 18:42:34 -08:00
agrajaghh
e31ddf0599 remove unused icons
Closes #2575

//FREEBIE
2015-03-05 18:36:10 -08:00
Rhodey Orbits
ce22e54359 Update message timesamps on resume.
Fixes #2519.
Closes #2593

// FREEBIE
2015-03-05 18:20:39 -08:00
Rhodey Orbits
7ce7ec56eb 1) created a new string constant for 'Passphrase'.
2) modified 'App protection' preference group summary to be more verbose.
3) dropped the colons from 'Appearance' preference group summary.
4) dropped the colons from and 'SMS and MMS' preference group summary.
2015-03-05 18:20:39 -08:00
agrajaghh
2b39728ea0 fix icons in import/export dialog
Closes #2574

//FREEBIE
2015-03-05 17:35:25 -08:00
Jake McGinty
2af5c7f02e fix "verify" button spacing in details
Fixes #2566
// FREEBIE
2015-03-05 17:07:07 -08:00
Jake McGinty
d6e0199e05 fix MessageDetailsActivity home button
// FREEBIE
2015-03-05 17:07:07 -08:00
Moxie Marlinspike
301ed0b255 Move passphrase disabled preference set to after secret generation.
Fixes #2588
2015-03-05 13:09:18 -08:00
Moxie Marlinspike
ac5306be5b Fix locale names
// FREEBIE

Closes #2564
2015-03-05 11:45:09 -08:00
agrajaghh
9de62d0286 replace icons in the add attachment dialog
Closes #2535
2015-03-03 17:14:31 -08:00
agrajaghh
067b14d551 make some strings translateable
closes #2567

//FREEBIE
2015-03-03 17:09:07 -08:00
agrajaghh
03110c9870 remove ConfirmIdentityActivity
Closes #2571

//FREEBIE
2015-03-03 17:06:24 -08:00
agrajaghh
a2b5bf54c8 remove PassphraseTimeoutPreference since its no longer used
closes #2565

//FREEBIE
2015-03-03 17:03:17 -08:00
Moxie Marlinspike
5602a3dfc0 Update to latest version of libtextsecure for simplified interface.
1) Switch to new TextSecureAddress addressing, rather than mixing
   long-based recipient IDs into libtextsecure.

2) Get rid of RecipientFormattingException throws in calls to
   RecipientFactory.

Closes #2570
2015-03-03 12:25:09 -08:00
Moxie Marlinspike
ed5b3f8679 Break out libtextsecure
// FREEBIE

Closes #2542
2015-03-02 08:25:19 -08:00
Moxie Marlinspike
7bf7acb1ff Dependency verification.
// FREEBIE

Closes #2546
2015-02-28 09:40:52 -08:00
Moxie Marlinspike
ffa5dc549b Add libtextsecure README
// FREEBIE
2015-02-27 16:58:19 -08:00
Moxie Marlinspike
a59feb7ad4 Rename PushAddress to TextSecureAddress
// FREEBIE
2015-02-27 16:57:51 -08:00
Jake McGinty
753a1c7219 add FAB content description
// FREEBIE
2015-02-27 16:31:01 -08:00
Moxie Marlinspike
004f050741 libtextsecure javadoc and minor API refactoring
// FREEBIE
2015-02-27 15:35:18 -08:00
Jake McGinty
fcde642563 Fix invalid transportation options
1) Accounts in the directory that don't have supports_sms can't
   get encrypted SMS.
2) Push groups can't receive insecure SMS

// FREEBIE

Closes #2521
2015-02-27 13:00:18 -08:00
Jake McGinty
ac0a1c0bc1 Conflicts UI touch-ups:
1) Fix i18n and layout naming.
2) Error header for message details.
3) Add back button to message details.

// FREEBIE

Closes #2593
2015-02-27 12:26:35 -08:00
Moxie Marlinspike
3f93731300 Adapt Conflicts UI to work with single-recipient failures. 2015-02-27 12:26:09 -08:00
Moxie Marlinspike
00d7b5c284 Better UX handling on identity key mismatches.
1) Migrate from GSON to Jackson everywhere.

2) Add support for storing identity key conflicts on message rows.

3) Add limited support for surfacing identity key conflicts in UI.
2015-02-27 12:26:09 -08:00
Jake McGinty
4397b55ceb fix padding problem in compose text
// FREEBIE
2015-02-25 14:53:32 -08:00
Martin Stone
b87abcc2c1 Update lockscreen image to new (blue) logo.
Fixes #2426
Closes #2502
2015-02-24 16:45:12 -08:00
Sebastian Kürten
79dbf2746f Added new media icons for audio/video
Added icons new icons, deleted an old one.
Using new icons in AudioSlide/VideoSlide.

Closes #2304
2015-02-23 13:13:39 -08:00
agrajaghh
a4bd9fae9a make "repeat alerts" setting translatable
Fixes #2511
Closes #2516

 //FREEBIE
2015-02-23 09:54:28 -08:00
Moxie Marlinspike
d4493e700e Add GroupId for received messages.
// FREEBIE
2015-02-23 09:53:32 -08:00
Moxie Marlinspike
83d65228e9 Fix for race conditioned caused by OkHttpClient NPE.
We catch OkHttpClient exceptions to deal with bugs in their code,
but in some cases that was leaving our state information in a
bad situation.

// FREEBIE
2015-02-23 09:53:19 -08:00
Moxie Marlinspike
8a2caeef3d Fix for OKH IllegalStateException.
// FREEBIE

Fixes #2501
2015-02-20 12:45:42 -08:00
Jake McGinty
6280ef4ab8 Revert "set appcompat menu class to obfuscate-only in PG"
This reverts commit 899afa2092.

Was able to reproduce a crash with this in second test that was actually
resolved in the previous proguard. Reverting.
2015-02-19 16:27:39 -08:00
Jake McGinty
899afa2092 set appcompat menu class to obfuscate-only in PG
keeping it on the safe side - tested on problematic samsung devices, and
it looks like it works fine.
// FREEBIE
2015-02-19 15:36:57 -08:00
Moxie Marlinspike
7c6b965969 Shrink some SC classes for Gingerbread dexopt limit.
// FREEBIE
2015-02-19 12:32:54 -08:00
Jake McGinty
5fac189736 "All images" view for conversations
// FREEBIE
2015-02-18 15:47:47 -08:00
Moxie Marlinspike
d3271f548c Support for retrieving stored messages via websocket.
1) When registering with server, indicate that the server should
   store messages and send notifications.

2) Process notification GCM messages, and connect to the server
   to retrieve actual message content.
2015-02-18 11:09:01 -08:00
Jake McGinty
023195dd4b make send button focusable
Fixes #2494
// FREEBIE
2015-02-17 17:55:18 -08:00
Moxie Marlinspike
299dd86c77 Support matching to account for telcos inserting SMS prefixes.
// FREEBIE

Fixes #1944
2015-02-16 20:25:19 -08:00
Jake McGinty
f818cfa32b Unjank character count indicators
Fixes #1841
// FREEBIE
2015-02-16 13:25:44 -08:00
Jake McGinty
fc21d2038f Add first Espresso interaction test
// FREEBIE
2015-02-16 13:08:28 -08:00
Jake McGinty
8277e4e102 Fix NPE when InetAddress.getByName() is null
Resolves #2189
// FREEBIE
2015-02-16 13:07:59 -08:00
Jake McGinty
242dbef54e Prevent NPE when MMS's FROM PduHeader is missing
Fixes #1448
// FREEBIE
2015-02-16 13:07:30 -08:00
Jake McGinty
9ffd84ce05 Increase readability of recv date in dark theme
Fixes #1483
// FREEBIE
2015-02-15 22:09:02 -08:00
Moxie Marlinspike
cb37ce0f5f Fix README typo
// FREEBIE

Closes #2396
2015-02-15 14:41:36 -08:00
Andy Martin
7ab739b22b clear the current text box when deleting a draft-only thread.
otherwise the draft will be immediately re-saved (preventing
thread deletion).

// FREEBIE

Closes #2474
Fixes #2473
2015-02-15 09:41:55 -08:00
Moxie Marlinspike
224b06f05a Theme the HMS picker.
// FREEBIE

Closes #2353
2015-02-13 15:06:50 -08:00
McLoo
d36d33f837 Stop crash on pasting long numbers as country code
//FREEBIE

Closes #2311
2015-02-13 14:38:35 -08:00
Moxie Marlinspike
724dced820 Define a max message length to display.
// FREEBIE

Closes #2294
2015-02-13 14:32:11 -08:00
Sam Lanning
b8ca0e57ad Only initialise EmojiGrid when not in edit mode
Suppress initialisation of the emoji_grid_layout.xml when the
EmojiDrawer is being used in a layout where the editor is shown,
 to prevent an NPE when an editor is being used.

// FREEBIE

Closes #2288
2015-02-13 14:23:05 -08:00
AsamK
fe5fc411a7 Save drafts for recipients without an existing thread
- Save drafts without thread in draft database
- Clear drafts when deleting conversation(s), otherwise
  the drafts stay in the database and will reappear when a thread
  with the same threadId is created

Closes #1510
2015-02-13 14:16:19 -08:00
agrajaghh
20d43bbfcb add icons to the preference categories
Closes #2361
2015-02-13 11:18:04 -08:00
Jake McGinty
442f56cdc3 prevent NPE in GroupCreateActivity
Occurs when a returned Recipient is null when returning from contact
selection activity.

Fixes #2466
// FREEBIE
2015-02-12 13:36:47 -08:00
Moxie Marlinspike
35dabaf1e5 Bump version to 2.5.3
// FREEBIE
2015-02-12 13:23:53 -08:00
Jake McGinty
1aec794a34 widen LGE menu workaround constraints
// FREEBIE
2015-02-12 13:16:03 -08:00
Jake McGinty
5bd8d6c69d Check the part stream is non-null before decoding
// FREEBIE

Closes #2459
2015-02-12 10:32:53 -08:00
Moxie Marlinspike
aa26785c00 Reinclude SC provider for consistency.
// FREEBIE

Fixes #2461
2015-02-12 10:30:45 -08:00
Moxie Marlinspike
f450b37cfd Bump version to 2.5.2
// FREEBIE
2015-02-11 23:24:10 -08:00
Jake McGinty
b88e470594 prevent recipient listener Activity context leak
Resolves #2372
Resolves #2425
// FREEBIE
2015-02-11 12:50:20 -08:00
Jake McGinty
f38677794a stop giving long-living static objects Activity contexts
// FREEBIE
2015-02-11 12:50:19 -08:00
Jake McGinty
ac4db41435 lower memory consumption from previews
// FREEBIE
2015-02-11 12:50:19 -08:00
Jake McGinty
3a9d521ffe Workaround LG-related menu issues, pt. 2
fixes #2444
// FREEBIE
2015-02-11 12:44:40 -08:00
Jake McGinty
b1bf33b13b Fix SaveAttachmentTask NPE
resolves #2454
// FREEBIE
2015-02-11 11:42:36 -08:00
Moxie Marlinspike
352418d2d7 Don't notify on MMS delivery failure if message has been deleted.
// FREEBIE

Fixes #2453
2015-02-11 10:29:05 -08:00
Moxie Marlinspike
fb523985ed Bump version to 2.5.1
// FREEBIE
2015-02-09 13:45:41 -08:00
Moxie Marlinspike
7ffe6f053c Merge pull request #2435 from mcginty/dark-actionmode-popup
Fix white-on-white ActionMode popup in dark theme
2015-02-09 12:07:54 -08:00
Jake McGinty
ea77191b70 Fix white-on-white ActionMode popup
// FREEBIE
2015-02-09 12:00:52 -08:00
Moxie Marlinspike
e0b882d4d2 Merge pull request #2434 from mcginty/plurals
move plurals to strings.xml
2015-02-09 11:24:58 -08:00
Jake McGinty
10a74d6d08 move plurals to strings.xml
Resolves #2421
// FREEBIE
2015-02-09 11:19:30 -08:00
Jake McGinty
f092e85b62 Workaround for LGE-related NPEs
See: https://code.google.com/p/android/issues/detail?id=78154

Fixes #2424
Closes #2428

// FREEBIE
2015-02-09 09:15:44 -08:00
Moxie Marlinspike
8aa0f15740 Bump version to 2.5.0
// FREEBIE
2015-02-06 16:42:04 -08:00
Moxie Marlinspike
18d4d4de24 Update language translations
// FREEBIE
2015-02-06 16:21:16 -08:00
Moxie Marlinspike
b3c42dee7e Merge pull request #2416 from mcginty/better-relative-dates
more succinct relative dates
2015-02-06 16:20:23 -08:00
Moxie Marlinspike
5836f35291 Merge pull request #2400 from mcginty/mms-bad-base64-fix
Fix NPE when encrypted MMS has bad base64 encoding
2015-02-06 16:19:20 -08:00
Jake McGinty
dbd8a4083c Fix NPE when encrypted MMS has bad base64 encoding
// FREEBIE
2015-02-06 13:01:36 -08:00
Jake McGinty
0fd52ad1fe more succinct relative dates
// FREEBIE
2015-02-06 13:00:21 -08:00
Moxie Marlinspike
8031c788d9 Merge pull request #2415 from mcginty/empty-group-updates
fix empty group update messages
2015-02-05 19:49:09 -08:00
Moxie Marlinspike
10a29db93d Merge pull request #2414 from mcginty/unread-readability
increase unread visibility in conv list
2015-02-05 19:46:31 -08:00
Jake McGinty
8f3f2e6921 fix empty group update messages
// FREEBIE
2015-02-05 19:38:08 -08:00
Jake McGinty
65c262acef increase unread visibility in conv list
// FREEBIE
2015-02-05 18:41:54 -08:00
AsamK
d586893402 Also crop contact photos in ShareList
// FREEBIE
2015-02-05 14:14:48 -08:00
Jake McGinty
ba62e018db Refine icon
1) fix glow
2) improve shadows
3) fix density-inconsistent assets
2015-01-28 12:52:51 -10:00
Moxie Marlinspike
57c17e705f Fix provisioning dialog strings.
// FREEBIE

Closes #2368
2015-01-24 10:16:33 -08:00
Jake McGinty
2e253fb6a8 provisioning dialog rework
// FREEBIE
2015-01-24 10:15:47 -08:00
Moxie Marlinspike
0c32001fe4 Support for multi-device provisioning flow.
// FREEBIE
2015-01-24 10:15:47 -08:00
Jake McGinty
48f6c2c526 Fix 'indicator tab' coloring
Was previously white-on-near-white
// FREEBIE
2015-01-23 10:59:22 -10:00
Jake McGinty
39fd1e8f46 fix incoming lock asset
// FREEBIE
2015-01-21 20:06:05 -10:00
Jake McGinty
810abe0275 material actionbar and fab
// FREEBIE
2015-01-21 19:01:23 -10:00
Jake McGinty
62816ee51a rounded ImageView instead of Bitmap, crop-select
// FREEBIE
2015-01-21 17:39:54 -10:00
Calvin Hu
a0599c1639 add theme to import/export activity
closes #2359
2015-01-16 10:41:01 -10:00
Jake McGinty
8a4a1b385d libpastelog 1.0.4
// FREEBIE
2015-01-15 13:06:42 -10:00
Moxie Marlinspike
5def8ba78d Bump version to 2.4.2
// FREEBIE
2015-01-14 13:51:53 -08:00
Jake McGinty
42da687602 Revert "add theme to import/export activity"
This reverts commit e64c067636.
2015-01-14 10:23:10 -10:00
Calvin Hu
e64c067636 add theme to import/export activity 2015-01-14 10:03:02 -10:00
Calvin Hu
c89fbabbf3 refresh contacts database on new db query 2015-01-13 15:16:30 -10:00
Moxie Marlinspike
778b8b490c Merge pull request #2346 from mcginty/thumbnail-early-recycle
fix early recycling of thumbnail
2015-01-13 16:21:15 -08:00
Jake McGinty
bade52d748 fix early recycling of thumbnail
// FREEBIE
2015-01-13 14:17:03 -10:00
Moxie Marlinspike
abc322b075 Bump version to 2.4.1
// FREEBIE
2015-01-13 16:01:58 -08:00
Moxie Marlinspike
9a31c5961a Merge pull request #2341 from mcginty/mms-recv-null-text
don't fail on null received text parts
2015-01-13 12:35:22 -08:00
Jake McGinty
f536e45378 don't fail on null received text parts
Fixes #2340
// FREEBIE
2015-01-13 10:15:18 -10:00
Moxie Marlinspike
18961e6369 Merge pull request #2339 from mcginty/content-security-exception
catch content security exception
2015-01-13 12:02:24 -08:00
Jake McGinty
1505ec8c35 catch ContentProvider SecurityExceptions to avoid crashes
// FREEBIE
2015-01-13 10:00:19 -10:00
Jake McGinty
d41efdbd1c prepareMessageMedia before we encrypt
and fail more nicely when pdu composition fails

// FREEBIE

Closes #2338
2015-01-13 11:59:03 -08:00
Jake McGinty
156cb4034e don't copy data when no dataUri
Fixes #2336
// FREEBIE
2015-01-13 11:57:46 -08:00
Moxie Marlinspike
d2e188ee62 Bump version to 2.4.0
// FREEBIE
2015-01-13 11:54:36 -08:00
Moxie Marlinspike
1de16de55b Update language translations.
// FREEBIE
2015-01-12 13:40:00 -08:00
Moxie Marlinspike
ac3b3673b9 Merge pull request #2330 from mcginty/dexmaker-workaround
workaround dexmaker bug in test cases
2015-01-12 13:38:57 -08:00
Jake McGinty
91bf5532b2 workaround dexmaker bug in test cases
// FREEBIE
2015-01-12 11:34:41 -10:00
Jake McGinty
b25b95f933 media constraints model
// FREEBIE
2015-01-12 13:20:25 -08:00
Moxie Marlinspike
a0ed0842a0 Add expiration check on build freshness.
// FREEBIE
2015-01-12 09:12:10 -08:00
Jake McGinty
12845da91a use PartDatabase to look up thumbnails async
// FREEBIE

Closes #2286
2015-01-11 18:10:53 -08:00
Jake McGinty
3e6e28e688 remove unused activities and fragments
// FREEBIE
2015-01-08 19:16:43 -08:00
Jake McGinty
9fed60628d fix temp file permission denied
// FREEBIE
2015-01-05 17:01:32 -08:00
Jake McGinty
e67dafe9c8 set conversation actionbar statelessly
// FREEBIE
2015-01-04 13:14:09 -08:00
Jake McGinty
5e5531805b disable android's landscape keyboard fullscreen
in composition, it stops the custom send icon from appearing, and
doesn't pay attention to theming.

// FREEBIE
2015-01-04 02:30:16 -08:00
Jake McGinty
b6822b310e don't populate data from uri when there is none
Fixes #2282
Closes #2283

// FREEBIE
2014-12-31 16:00:28 -08:00
Jake McGinty
3e8d2a557e Merge pull request #2281 from jonboulle/building
Remove native components from build instructions
2014-12-31 03:15:07 -08:00
Jonathan Boulle
23caf2b14d Remove native components from build instructions
Native components were split out into the libaxolotl-android repository
in 1833e57, so these instructions are no longer relevant.
2014-12-30 21:47:59 -08:00
Moxie Marlinspike
562520a4bb Remove empty strings.
// FREEBIE
2014-12-29 18:20:50 -08:00
Moxie Marlinspike
75d882e945 Updated language translations
// FREEBIE
2014-12-29 17:02:16 -08:00
Jake McGinty
b39e41c803 media preview orientation
// FREEBIE
2014-12-29 16:50:19 -08:00
Jake McGinty
348352cc71 Bitmap OOM and rotation fixes
// FREEBIE
2014-12-29 16:42:22 -08:00
Moxie Marlinspike
bec5e45605 Fix for old-skool SMS key exchange UI behavior.
Also fixes SMS "end session" messages failing to end session.

// FREEBIE
2014-12-29 15:09:13 -08:00
Moxie Marlinspike
4d8004ab21 Merge pull request #2276 from mcginty/group-meta-colors
group visual fixes
2014-12-29 14:37:45 -08:00
Jake McGinty
2e141b2a90 group visual fixes
// FREEBIE
2014-12-29 14:34:09 -08:00
Moxie Marlinspike
ed556fbd3a Support for multi-select in the conversation list.
// FREEBIE

Closes #1601
Closes #2214

Fixes #2188
Fixes #786
2014-12-29 13:54:59 -08:00
Jake McGinty
ebf6a2d833 remove pointless Bitmap allocation for ImageSlides
Fixes #2248
// FREEBIE
2014-12-29 13:49:37 -08:00
Moxie Marlinspike
25028b7178 Update to jobmanager 0.10.0
// FREEBIE
2014-12-29 13:32:37 -08:00
Jake McGinty
389128d1a3 fix edit-group intent extras
// FREEBIE
2014-12-29 12:58:54 -08:00
Moxie Marlinspike
6e85677c52 Support 'WiFi calling' devices.
// FREEBIE

Fixes #2254
Fixes #2240
Fixes #2160

Closes #2263
2014-12-29 12:51:39 -08:00
Moxie Marlinspike
1443d846c4 Use "singleTask" to ensure a single ConversationActivity instance.
1) Mark the Activity as singleTask.

2) Process onNewIntent for updates.

3) Propagate onNewIntent to the ConversationFragment.

Fixes #2232
Fixes #1532
Fixes #146
Fixes #851
Closes #2266
2014-12-29 12:49:15 -08:00
guiweber
d7419caa4b Moved several hard-coded UI strings to strings.xml
Closes #2203
2014-12-29 12:29:48 -08:00
Jake McGinty
e277f9f6d1 fix some missing recipient parcel bugs
// FREEBIE
2014-12-29 11:43:10 -08:00
McLoo
3f0932ff7b replace unlocalized 'at' in message details date
Making this a string resource has the potential for crashes.
Leaving it out completely is a little confusing.
The dash is the perfect solution - until a better date formatter is used.
Closes #2215
2014-12-26 11:05:34 -08:00
Jake McGinty
0a61534e03 fix recipient handling for media preview
// FREEBIE
2014-12-24 15:11:13 -08:00
Jake McGinty
121b1493cc thumbnail generation and disk caching
// FREEBIE
2014-12-24 14:46:50 -08:00
Moxie Marlinspike
a57c7c3e09 Merge pull request #2264 from mcginty/write-part-data-fix
use PartAuthority when fetching part streams
2014-12-24 14:07:42 -08:00
Jake McGinty
b89b986a9e use PartAuthority when fetching part streams
resolves the self-send case

Fixes #2259
// FREEBIE
2014-12-24 13:27:53 -08:00
Jake McGinty
1bb882ac96 fix bithub payment link and image 2014-12-24 13:22:31 -08:00
Jake McGinty
9e7928873b properly update transport options location
// FREEBIE
2014-12-24 13:17:41 -08:00
Moxie Marlinspike
21591dc6b1 Fix build.
// FREEBIE
2014-12-23 15:42:32 -08:00
McLoo
3ec95f7a8e More l10n - for decrypting errors
//FREEBIE

Closes #2231
2014-12-23 12:53:38 -08:00
Oliver Gasser
33d466a5cc Include group titles in search
When searching for messages only simple threads matching the
contact names are returned as search results. With this commit
also group converstations where the group title matches the search
term are displayed in the result. This makes search results more
consistent with the conversation list as now all conversation
titles (i.e. contact names and group titles) are searched through.

Fixes #1954
Closes #2216
2014-12-23 12:40:30 -08:00
Jake McGinty
e8b947dfde Pass recipient ids, not recipient objects
Fixes #2233
// FREEBIE
2014-12-22 14:53:28 -08:00
Moxie Marlinspike
60a343120d Merge pull request #2230 from mcginty/manual-mms-pref-validation
Catch issues with bad MMSC URIs, add validation
2014-12-16 18:00:52 -08:00
McLoo
8af74e93a2 Replace button text to cancel TS registration
in RegistrationActivity from "skip" to "cancel", when coming from the reminder

Closes #2219
2014-12-16 16:09:26 -08:00
Jake McGinty
e650349bb7 Catch issues with bad MMSC URIs, add validation
Fixes #2202
// FREEBIE
2014-12-16 16:01:22 -08:00
agrajaghh
44a4570870 remove double rotation of group avatars
//FREEBIE
2014-12-16 14:33:46 -08:00
Moxie Marlinspike
f1572774f2 Merge pull request #2227 from mcginty/circle-crop-oom
memory-friendly resize for circle cropping
2014-12-15 20:42:53 -08:00
Jake McGinty
ec18da8aa9 memory-friendly resize for circle cropping
Fixes #2224
// FREEBIE
2014-12-15 19:57:51 -08:00
Moxie Marlinspike
199c28dad6 Merge pull request #2218 from McLoo/fix_av_draft_2
Enabled audio and video drafts
2014-12-14 11:19:21 -08:00
McLoo
4a8a939f64 Enabled audio and video drafts
All slide types do have an "image", changing the check order enables audio and video drafts.
//FREEBIE
2014-12-14 20:16:35 +01:00
agrajaghh
cef203f261 rotate images based on exif information
Closes #1847
2014-12-13 16:45:39 -08:00
Moxie Marlinspike
d7de5415b5 Skip drafts and outbox messages during imports.
// FREEBIE

Closes #1468
Fixes #892
2014-12-12 19:35:52 -08:00
McLoo
188d11bc23 Added l10n for ZXing intent message box
Closes #2147
2014-12-12 19:05:31 -08:00
Tal Hacohen
990902845a Change creation of drafts to onStop method.
Drafts were created only on destroy of the conversation activity.
Moved it to be on stop for the activity.

Closes #1985
2014-12-12 18:51:52 -08:00
Jake McGinty
07bb07c342 streaming media
// FREEBIE
2014-12-12 18:49:32 -08:00
Aaron M Brown
a09e0afbd6 Explain size limit for large attachments in toasts.
// FREEBIE

Fixes #2100
Closes #2172
2014-12-12 18:45:06 -08:00
Aaron M Brown
bbea017d5a Make message details reflect 24-hour system preference.
Fixes #2150
Closes #2163
2014-12-12 18:37:40 -08:00
Moxie Marlinspike
426c56c77d Support install link
Closes #2001
Fixes #1722
2014-12-12 18:31:20 -08:00
Moxie Marlinspike
642334da1f Merge pull request #2212 from agrajaghh/betterpicker_translateable
make summary of passphrase timeout translatable
2014-12-12 17:04:29 -08:00
McLoo
b44acd82e6 Added l10n for message details
//FREEBIE

Closes #2173
2014-12-12 16:43:45 -08:00
agrajaghh
62d0de2ee6 remove double include of betterpicker in build.gradle
//FREEBIE
2014-12-13 01:38:03 +01:00
agrajaghh
3c7e319029 make summary of passphrase timeout translatable
//FREEBIE
2014-12-13 01:37:06 +01:00
Lukas Barth
715b1ea10d Reset query string when search is collapsed
Closes #2041
2014-12-12 16:30:17 -08:00
ultrasandwich
6980a32628 Fix user-facing helping term 'insecure' to 'unsecured'.
Insecure implies an uncertainty of intention or confidence.
Unsecured is more specifically addressing the protocol which
wraps the message delivered.

Closes #1811
2014-12-12 16:17:34 -08:00
Moxie Marlinspike
15f44a78a9 Update min/max fix in shortcutbadger
// FREEBIE
2014-12-12 16:12:49 -08:00
Moxie Marlinspike
6b05f7905b Use betterpicker for HMS timeout.
// FREEBIE

Closes #1890
2014-12-12 16:07:02 -08:00
McLoo
9beb51bd77 Enabled audio and video drafts
//FREEBIE

Closes #1799
2014-12-12 14:44:21 -08:00
agrajaghh
0b62cf372b whitespace cleanup
//FREEBIE

Closes #1779
2014-12-12 14:39:51 -08:00
Moxie Marlinspike
b7badec752 Switch to forked ShortcutBadger.
// FREEBIE
2014-12-12 11:49:48 -08:00
Jake McGinty
a5e5a4c37f update build tools
// FREEBIE
2014-12-12 10:06:15 -08:00
Jake McGinty
c448a833f5 another minor pref tweak for mms fallback
1) fix summary for outgoing sms/mms
2) disable mms option when TS-users is unselected, same as the fallback
   approval option.

// FREEBIE
2014-12-11 22:46:59 -08:00
Jake McGinty
761049d6f8 minor preferences tweaks
1) shorten some summaries
2) add summaries to appearance subscreen
3) move common summary functions to common parent class

// FREEBIE
2014-12-11 22:12:12 -08:00
Moxie Marlinspike
df12174458 Add support for notification reminders.
// FREEBIE

Closes #1623
Fixes #323
2014-12-11 19:38:46 -08:00
agrajaghh
6e7566f781 remove workaround for nested PreferenceScreen's
Closes #2208
//FREEBIE
2014-12-11 19:36:15 -08:00
Jake McGinty
30232c1635 transport selection refactor
Closes #1724
// FREEBIE
2014-12-11 19:27:24 -08:00
Bastian Köcher
4a088410ae "add contact" button for unknown contacts
Closes #1551
2014-12-11 18:59:29 -08:00
Jake McGinty
b05967f2c9 Show drafts in conversation list snippets
// FREEBIE
2014-12-11 18:27:54 -08:00
Jabro
1d0c9536fc Support for ShortcutBadger
// FREEBIE

Closes #1574
Closes #1952

Fixes #1526
Fixes #321
2014-12-11 17:23:21 -08:00
Moxie Marlinspike
3c4ac4b105 Add option that allows disabling MMS fallback with TS users.
// FREEBIE

Closes #1444
2014-12-11 16:12:36 -08:00
3xo
ff05642f3e Enable progress indicator on group update
Closes #1165
2014-12-11 16:05:07 -08:00
Moxie Marlinspike
4e98c350a5 Support localization in passphrase activity and lock notification.
// FREEBIE

Closes #1328
2014-12-11 15:04:32 -08:00
Lukas Barth
e5e5b93884 Add k-9 style avatars to group conversations
Closes #1107
2014-12-11 14:40:44 -08:00
agrajaghh
2f6cefca8a refactor preferences into multiple PreferenceFragments 2014-12-11 14:02:28 -08:00
Sam Lanning
8149af22ec Open Keyboard When NewConversationActivity opened
// FREEBIE
2014-12-11 12:40:21 -08:00
agrajaghh
55ee288c36 Refactor notification for encrypted messages.
Closes #1184
2014-12-11 12:13:08 -08:00
Moxie Marlinspike
1833e57c38 Break libaxolotl out into an external project.
// FREEBIE
2014-12-08 16:07:16 -08:00
Moxie Marlinspike
c14945791c gradle tools 1.0.0
// FREEBIE
2014-12-08 14:17:09 -08:00
Moxie Marlinspike
b914d5ca25 Bump version to 2.3.3
// FREEBIE
2014-12-04 17:35:03 -08:00
Moxie Marlinspike
7411a49572 Updated language translations.
// FREEBIE
2014-12-04 16:44:31 -08:00
Mladen Pejaković
3fcd2bb88d Add Croatian language to list
// FREEBIE

Closes #2167
Fixes #2026
2014-12-04 16:02:42 -08:00
Moxie Marlinspike
978f769d6d Notify on incoming messages when locked.
// FREEBIE

Fixes #2149
2014-12-04 15:49:09 -08:00
Moxie Marlinspike
9d693eef30 Fix for fallback behavior.
// FREEBIE
2014-12-03 14:16:34 -08:00
Moxie Marlinspike
8f79ba1dd1 Merge pull request #2178 from mcginty/async-media-preview
media preview fixes
2014-12-03 09:09:43 -08:00
Jake McGinty
15613894f0 load image previews asynchronously
// FREEBIE
2014-12-03 13:03:03 +00:00
Jake McGinty
a88fbba49f use Loader when conversation is updated instead of requery
// FREEBIE
2014-12-03 04:47:38 +00:00
Jake McGinty
f3f173f653 support mms basic auth
// FREEBIE
2014-12-02 08:59:43 +00:00
Moxie Marlinspike
5002a749cf Merge pull request #2166 from agrajaghh/building.md_ndk_path
Building.md: library -> libaxolotl
2014-12-01 09:06:32 -08:00
agrajaghh
4a107483c1 path changed: library -> libaxolotl 2014-12-01 16:09:55 +01:00
Tal Hacohen
9ef1ea283b Fix notification display order.
Messages in notifications were showing in reverse order,
that is newest on top instead of newest at the bottom making
multiple messages hard to read.

Closes #1984
2014-11-30 08:35:51 -08:00
christian mock
32153ec379 Use "sms_body" extra from Intent
Closes #2071
2014-11-29 19:31:25 -08:00
Mladen Pejaković
ceb82a05ca Add Serbian language to the list
Closes #2008
2014-11-29 13:43:51 -08:00
McLoo
899bf8160d Cleanup of unused strings in strings.xml
//FREEBIE

Closes #2139
2014-11-29 13:35:36 -08:00
McLoo
49f77c9c06 Added l10n for message trimmer
//FREEBIE

Closes #2079
Closes #1868
2014-11-29 13:31:44 -08:00
McLoo
cd5feccdbf Fix selection for hungarian
// FREEBIE

Closes #2025
2014-11-29 13:19:49 -08:00
Moxie Marlinspike
a1da22cee9 Use constant.
// FREEBIE

Closes #1988
2014-11-29 13:12:53 -08:00
Jakob
a950db74c0 add dependencies to BUILDING.md
// FREEBIE

Closes #1809
2014-11-29 11:54:30 -08:00
Jake McGinty
b0891fa986 move log submission to new library
// FREEBIE

Closes #1655
2014-11-29 11:42:25 -08:00
Moxie Marlinspike
b57763f397 Display 'me' for device's local number in group membership list.
// FREEBIE

Fixes #1494
Closes #1505
2014-11-28 10:46:50 -08:00
Moxie Marlinspike
de75a98093 Move JobManager to external project and dependency.
// FREEBIE
2014-11-28 10:10:47 -08:00
Moxie Marlinspike
0d01feebc3 Move directory refresh from a service over to a job.
// FREEBIE
2014-11-27 15:24:26 -08:00
Moxie Marlinspike
0fb7f3b970 Minor cleanup.
// FREEBIE
2014-11-26 10:05:30 -08:00
agrajaghh
a9637baddf PushNetworkException for network errors on external downloads.
Closes #2112
Fixes #1264

// FREEBIE
2014-11-25 09:07:49 -08:00
1163 changed files with 23514 additions and 102659 deletions

View File

@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
lang_map = fr_CA:fr-rCA,pt_BR:pt-rBR,pt_PT:pt,zh_CN:zh-rCN,zh_HK:zh-rHK,zh_TW:zh-rTW,da_DK:da-rDK,de_DE:de,tr_TR:tr,fr_FR:fr,es_ES:es,hu_HU:hu,sv_SE:sv-rSE,bg_BG:bg,el_GR:el,kn_IN:kn-rIN,cs_CZ:cs
lang_map = fr_CA:fr-rCA,pt_BR:pt-rBR,pt_PT:pt,zh_CN:zh-rCN,zh_HK:zh-rHK,zh_TW:zh-rTW,da_DK:da-rDK,de_DE:de,tr_TR:tr,fr_FR:fr,es_ES:es,hu_HU:hu,sv_SE:sv-rSE,bg_BG:bg,el_GR:el,kn_IN:kn-rIN,cs_CZ:cs,sr:sr,he:iw,id:in
[textsecure-official.master]

View File

@@ -2,14 +2,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.thoughtcrime.securesms"
android:versionCode="86"
android:versionName="2.3.2">
android:versionCode="107"
android:versionName="2.10.0">
<permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"
android:label="Access to TextSecure Secrets"
android:protectionLevel="signature" />
<uses-permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"/>
<uses-permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"/>
<uses-permission android:name="android.permission.READ_PROFILE"/>
<uses-permission android:name="android.permission.WRITE_PROFILE"/>
<uses-permission android:name="android.permission.BROADCAST_WAP_PUSH"
@@ -42,38 +42,8 @@
android:label="@string/app_name"
android:theme="@style/TextSecure.LightTheme">
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity android:name=".RoutingActivity"
android:theme="@style/NoAnimation.Theme.BlackScreen"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|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.SENDTO"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="audio/*" />
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
<data android:mimeType="video/*" />
</intent-filter>
</activity>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity android:name=".RegistrationProblemsActivity"
android:theme="@style/TextSecure.Light.Dialog"
@@ -90,7 +60,18 @@
android:windowSoftInputMode="stateUnchanged"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".MmsPreferencesActivity"
<activity android:name=".DeviceProvisioningActivity"
android:theme="@style/TextSecure.DialogActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="tsdevice"/>
</intent-filter>
</activity>
<activity android:name=".preferences.MmsPreferencesActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ShareActivity"
@@ -98,20 +79,45 @@
android:launchMode="singleTask"
android:noHistory="true"
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="audio/*" />
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
<data android:mimeType="video/*" />
</intent-filter>
</activity>
<activity android:name=".ConversationListActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ConversationActivity"
android:windowSoftInputMode="stateUnchanged"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
<activity android:name=".MessageDetailsActivity"
android:label="Message Details"
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".GroupCreateActivity"
android:windowSoftInputMode="stateVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
android:windowSoftInputMode="stateVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".DatabaseMigrationActivity"
android:theme="@style/NoAnimation.Theme.AppCompat.Light.DarkActionBar"
@@ -127,24 +133,19 @@
android:label="@string/AndroidManifest__create_passphrase"
android:windowSoftInputMode="stateUnchanged"
android:theme="@style/TextSecure.IntroTheme"
android:launchMode="singleTop"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".PassphrasePromptActivity"
android:label="@string/AndroidManifest__enter_passphrase"
android:launchMode="singleTop"
android:launchMode="singleTask"
android:theme="@style/TextSecure.IntroTheme"
android:windowSoftInputMode="stateAlwaysVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ContactSelectionActivity"
android:label="@string/AndroidManifest__select_contacts"
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".NewConversationActivity"
android:label="@string/AndroidManifest__select_contacts"
android:windowSoftInputMode="stateHidden"
android:windowSoftInputMode="stateVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".PushContactSelectionActivity"
@@ -152,11 +153,6 @@
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".AutoInitiateActivity"
android:theme="@style/TextSecure.Light.Dialog"
android:label="@string/AndroidManifest__textsecure_detected"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ViewIdentityActivity"
android:label="@string/AndroidManifest__public_identity_key"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@@ -173,7 +169,6 @@
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ReceiveKeyActivity"
android:label="@string/AndroidManifest__complete_key_exchange"
android:theme="@style/TextSecure.Light.Dialog"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@@ -194,6 +189,11 @@
<activity android:name=".MediaPreviewActivity"
android:label="@string/AndroidManifest__media_preview"
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".MediaOverviewActivity"
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@@ -212,10 +212,23 @@
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".SmsSendtoActivity">
<intent-filter>
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
<service android:enabled="true" android:name=".service.KeyCachingService"/>
<service android:enabled="true" android:name=".service.RegistrationService"/>
<service android:enabled="true" android:name=".service.DirectoryRefreshService"/>
<service android:enabled="true" android:name=".service.MessageRetrievalService"/>
<service android:name=".service.QuickResponseService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
@@ -231,14 +244,6 @@
</service>
<!-- <receiver android:name=".service.BootListener" -->
<!-- android:enabled="true" -->
<!-- android:exported="false">-->
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.BOOT_COMPLETED" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<receiver android:name=".gcm.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
@@ -291,6 +296,10 @@
android:grantUriPermissions="true"
android:authorities="org.thoughtcrime.provider.securesms" />
<provider android:name=".providers.MmsBodyProvider"
android:grantUriPermissions="true"
android:authorities="org.thoughtcrime.provider.securesms.mms" />
<receiver android:name=".service.RegistrationNotifier"
android:exported="false">
<intent-filter>
@@ -305,6 +314,17 @@
</intent-filter>
</receiver>
<uses-library android:name="android.test.runner" />
<receiver android:name=".notifications.MessageNotifier$ReminderReceiver">
<intent-filter>
<action android:name="org.thoughtcrime.securesms.MessageNotifier.REMINDER_ACTION"/>
</intent-filter>
</receiver>
<receiver android:name=".notifications.MessageNotifier$DeleteReceiver">
<intent-filter>
<action android:name="org.thoughtcrime.securesms.MessageNotifier.DELETE_REMINDER_ACTION"/>
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -17,7 +17,11 @@ The following steps should help you (re)build TextSecure from the command line.
git clone https://github.com/WhisperSystems/TextSecure.git
2. Make sure you have the [Android SDK](https://developer.android.com/sdk/index.html) installed somewhere on your system.
3. Ensure the "Android Support Repository" and "Android SDK Build-tools" are installed from the Android SDK manager.
3. Ensure that the following packages are installed from the Android SDK manager:
* Android SDK Build Tools
* SDK Platform
* Android Support Repository
* Google Repository
4. Create a local.properties file at the root of your source checkout and add an sdk.dir entry to it.
sdk.dir=\<path to your sdk installation\>
@@ -26,19 +30,17 @@ The following steps should help you (re)build TextSecure from the command line.
./gradlew build
Re-building native components
-----------------------------
Visual assets
----------------------
Note: This step is optional; native components are contained as binaries (see [library/libs](library/libs)).
Source assets tend to be large binary blobs, which are best stored outside of git repositories. We host ours in a [Pixelapse repository](https://www.pixelapse.com/openwhispersystems/projects/signal-android/). Some source files are SVGs that can be auto-colored and sized using a tool like [android-res-utils](https://github.com/sebkur/android-res-utils).
1. Ensure that the Android NDK is installed.
Sample command for generating our audio placeholder image:
Execute ndk-build:
cd library
ndk-build
Afterwards, execute Gradle as above to re-create the APK.
```bash
pngs_from_svg.py ic_audio.svg /path/to/TextSecure/res/ 150 "#000" 0.54 _light
pngs_from_svg.py ic_audio.svg /path/to/TextSecure/res/ 150 "#fff" 1.0 _dark
```
Setting up a development environment
------------------------------------

View File

@@ -1,6 +1,6 @@
# TextSecure [![Build Status](https://travis-ci.org/WhisperSystems/TextSecure.svg?branch=master)](https://travis-ci.org/WhisperSystems/TextSecure)
TextSecure is a messaging app for easy private communicate with friends.
TextSecure is a messaging app for simple private communication with friends.
TextSecure can use either data (WiFi/3G/4G) or SMS to communicate securely, and all TextSecure
messages can also be encrypted locally on your device.
@@ -14,6 +14,16 @@ We use GitHub for bug tracking. Please search the existing issues for your bug a
https://github.com/WhisperSystems/TextSecure/issues
## Joining the Beta
Want to live life on the bleeding edge and help out with testing?
You can subscribe to TextSecure Beta releases in two steps:
1. Join the [TextSecure Beta Google+ Community](https://plus.google.com/communities/114424213916773497091).
1. After you've joined the community, [subscribe to the beta](https://play.google.com/apps/testing/org.thoughtcrime.securesms).
If you're interested in a life of peace and tranquility, stick with the standard releases.
## Contributing Translations
Interested in helping to translate TextSecure? Contribute here:
@@ -38,7 +48,7 @@ whispersystems@lists.riseup.net
https://lists.riseup.net/www/info/whispersystems
## Contributing Funds
[![Donate](https://coinbase.com/assets/buttons/donation_large-6ec72b1a9eec516944e50a22aca7db35.png)](https://whispersystems.org/blog/bithub/)
[![Donate](https://www.coinbase.com/assets/buttons/donation_large-36ee936185fdf9a88e3a28cc685fb9b7.png)](https://coinbase.com/checkouts/d29fd4c37ca442393e32fdcb95304701)
You can add funds to BitHub to directly help further development efforts.

View File

@@ -0,0 +1,16 @@
package org.thoughtcrime.securesms;
import android.content.Context;
import android.test.InstrumentationTestCase;
public class TextSecureTestCase extends InstrumentationTestCase {
@Override
public void setUp() throws Exception {
System.setProperty("dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath());
}
protected Context getContext() {
return getInstrumentation().getContext();
}
}

View File

@@ -1,10 +1,10 @@
package org.thoughtcrime.securesms.database;
import android.test.InstrumentationTestCase;
import org.thoughtcrime.securesms.TextSecureTestCase;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
public class CanonicalAddressDatabaseTest extends InstrumentationTestCase {
public class CanonicalAddressDatabaseTest extends TextSecureTestCase {
private static final String AMBIGUOUS_NUMBER = "222-3333";
private static final String SPECIFIC_NUMBER = "+49 444 222 3333";
private static final String EMAIL = "a@b.fom";

View File

@@ -0,0 +1,63 @@
package org.thoughtcrime.securesms.database;
import android.net.Uri;
import org.thoughtcrime.securesms.TextSecureTestCase;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import java.io.FileNotFoundException;
import java.io.InputStream;
import ws.com.google.android.mms.pdu.PduPart;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyFloat;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class PartDatabaseTest extends TextSecureTestCase {
private static final long PART_ID = 1L;
private PartDatabase database;
@Override
public void setUp() {
database = spy(DatabaseFactory.getPartDatabase(getInstrumentation().getTargetContext()));
}
public void testTaskNotRunWhenThumbnailExists() throws Exception {
when(database.getPart(eq(PART_ID))).thenReturn(getPduPartSkeleton("x/x"));
doReturn(mock(InputStream.class)).when(database).getDataStream(any(MasterSecret.class), anyLong(), eq("thumbnail"));
database.getThumbnailStream(null, PART_ID);
verify(database, never()).updatePartThumbnail(any(MasterSecret.class), anyLong(), any(PduPart.class), any(InputStream.class), anyFloat());
}
public void testTaskRunWhenThumbnailMissing() throws Exception {
when(database.getPart(eq(PART_ID))).thenReturn(getPduPartSkeleton("image/png"));
doReturn(null).when(database).getDataStream(any(MasterSecret.class), anyLong(), eq("thumbnail"));
doNothing().when(database).updatePartThumbnail(any(MasterSecret.class), anyLong(), any(PduPart.class), any(InputStream.class), anyFloat());
try {
database.new ThumbnailFetchCallable(mock(MasterSecret.class), PART_ID).call();
throw new AssertionError("didn't try to generate thumbnail");
} catch (FileNotFoundException fnfe) {
// success
}
}
private PduPart getPduPartSkeleton(String contentType) {
PduPart part = new PduPart();
part.setContentType(contentType.getBytes());
part.setDataUri(Uri.EMPTY);
return part;
}
}

View File

@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.jobs;
import android.test.AndroidTestCase;
import org.thoughtcrime.securesms.TextSecureTestCase;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule;
import org.whispersystems.libaxolotl.ecc.Curve;
@@ -28,7 +29,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
public class CleanPreKeysJobTest extends AndroidTestCase {
public class CleanPreKeysJobTest extends TextSecureTestCase {
public void testSignedPreKeyRotationNotRegistered() throws IOException, MasterSecretJob.RequirementNotMetException {
TextSecureAccountManager accountManager = mock(TextSecureAccountManager.class);

View File

@@ -1,12 +1,11 @@
package org.thoughtcrime.securesms.jobs;
import android.test.AndroidTestCase;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.thoughtcrime.securesms.TextSecureTestCase;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.whispersystems.textsecure.api.TextSecureMessageSender;
import org.whispersystems.textsecure.api.push.PushAddress;
import org.whispersystems.textsecure.api.push.TextSecureAddress;
import org.whispersystems.textsecure.api.push.exceptions.NotFoundException;
import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException;
@@ -22,7 +21,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory;
public class DeliveryReceiptJobTest extends AndroidTestCase {
public class DeliveryReceiptJobTest extends TextSecureTestCase {
public void testDelivery() throws IOException {
TextSecureMessageSender textSecureMessageSender = mock(TextSecureMessageSender.class);
@@ -37,10 +36,10 @@ public class DeliveryReceiptJobTest extends AndroidTestCase {
deliveryReceiptJob.onRun();
ArgumentCaptor<PushAddress> captor = ArgumentCaptor.forClass(PushAddress.class);
ArgumentCaptor<TextSecureAddress> captor = ArgumentCaptor.forClass(TextSecureAddress.class);
verify(textSecureMessageSender).sendDeliveryReceipt(captor.capture(), eq(timestamp));
assertTrue(captor.getValue().getRelay().equals("foo"));
assertTrue(captor.getValue().getRelay().get().equals("foo"));
assertTrue(captor.getValue().getNumber().equals("+14152222222"));
}
@@ -50,7 +49,7 @@ public class DeliveryReceiptJobTest extends AndroidTestCase {
Mockito.doThrow(new PushNetworkException("network error"))
.when(textSecureMessageSender)
.sendDeliveryReceipt(any(PushAddress.class), eq(timestamp));
.sendDeliveryReceipt(any(TextSecureAddress.class), eq(timestamp));
DeliveryReceiptJob deliveryReceiptJob = new DeliveryReceiptJob(getContext(),
@@ -69,7 +68,7 @@ public class DeliveryReceiptJobTest extends AndroidTestCase {
Mockito.doThrow(new NotFoundException("not found"))
.when(textSecureMessageSender)
.sendDeliveryReceipt(any(PushAddress.class), eq(timestamp));
.sendDeliveryReceipt(any(TextSecureAddress.class), eq(timestamp));
try {
deliveryReceiptJob.onRun();

View File

@@ -4,11 +4,13 @@ import android.test.AndroidTestCase;
import junit.framework.AssertionFailedError;
import org.thoughtcrime.securesms.TextSecureTestCase;
import org.whispersystems.textsecure.api.util.InvalidNumberException;
import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
import static org.fest.assertions.api.Assertions.assertThat;
public class PhoneNumberFormatterTest extends AndroidTestCase {
import static org.assertj.core.api.Assertions.assertThat;
public class PhoneNumberFormatterTest extends TextSecureTestCase {
private static final String LOCAL_NUMBER = "+15555555555";
public void testFormatNumberE164() throws Exception, InvalidNumberException {

View File

@@ -1,9 +0,0 @@
package org.thoughtcrime.securesms.util;
import android.test.AndroidTestCase;
import static org.fest.assertions.api.Assertions.assertThat;
public class UtilTest extends AndroidTestCase {
}

View File

@@ -1,28 +0,0 @@
package org.thoughtcrime.securesms.service;
import android.content.Intent;
import android.test.InstrumentationTestCase;
import static org.fest.assertions.api.Assertions.*;
public class MmsReceiverTest extends InstrumentationTestCase {
private MmsReceiver mmsReceiver;
public void setUp() throws Exception {
super.setUp();
mmsReceiver = new MmsReceiver(getInstrumentation().getContext());
}
public void tearDown() throws Exception {
}
public void testProcessMalformedData() throws Exception {
Intent intent = new Intent();
intent.setAction(SendReceiveService.RECEIVE_MMS_ACTION);
intent.putExtra("data", new byte[]{0x00});
mmsReceiver.process(null, intent);
}
}

View File

@@ -122,10 +122,13 @@
<apn carrier="Orange MMS" mcc="214" mnc="03" apn="orangemms" proxy="172.22.188.25" port="8080" user="orange" password="orange" mmsc="http://mms.orange.es" mmsproxy="172.22.188.25" mmsport="8080" authtype="2" type="mms" />
<apn carrier="Yoigo" mcc="214" mnc="04" apn="internet" proxy="010.008.000.036" port="8080" type="default,supl" />
<apn carrier="Yoigo MMS" mcc="214" mnc="04" apn="mms" mmsc="http://mms" mmsproxy="193.209.134.141" mmsport="80" type="mms" />
<apn carrier="Pepephone 4G Internet" mcc="214" mnc="05" apn="gprsmov.pepephone.com" type="default,supl" />
<apn carrier="Pepephone 4G MMS" mcc="214" mnc="05" apn="gprs.pepephone.com" mmsc="http://www.pepephone.com" mmsproxy="10.138.255.43" mmsport="8080" authtype="1" type="mms" />
<apn carrier="Pepephone 4G (Public)" mcc="214" mnc="05" apn="gprs.pepephone.com" type="default,supl" />
<apn carrier="Tuenti" mcc="214" mnc="05" apn="tuenti.com" user="tuenti" password="tuenti" mmsc="http://tuenti.com" mmsproxy="10.138.255.43" mmsport="8080" type="default,supl,mms" />
<apn carrier="Pepephone Internet" mcc="214" mnc="06" apn="gprsmov.pepephone.com" type="default,supl" />
<apn carrier="Pepephone MMS" mcc="214" mnc="06" apn="mms.pepephone.com" user="wap@wap" password="wap125" mmsproxy="212.073.032.010" mmsport="80" type="mms" />
<apn carrier="Pepephone (Public)" mcc="214" mnc="06" apn="gprs.pepephone.com" type="default,supl" />
<apn carrier="Pepephone 3G Internet" mcc="214" mnc="06" apn="gprsmov.pepephone.com" type="default,supl" />
<apn carrier="Pepephone 3G MMS" mcc="214" mnc="06" apn="mms.pepephone.com" user="wap@wap" password="wap125" mmsproxy="212.073.032.010" mmsport="80" type="mms" />
<apn carrier="Pepephone 3G (Public)" mcc="214" mnc="06" apn="gprs.pepephone.com" type="default,supl" />
<apn carrier="Vodafone GPRS" mcc="214" mnc="06" apn="airtelnet.es" user="vodafone" password="vodafone" type="default,supl" />
<apn carrier="Vodafone MMS" mcc="214" mnc="06" apn="mms.vodafone.net" user="wap@wap" password="wap125" mmsc="http://mmsc.vodafone.es/servlets/mms" mmsproxy="212.73.32.10" mmsport="80" type="mms" />
<apn carrier="Movistar ES" mcc="214" mnc="07" apn="movistar.es" user="MOVISTAR" password="MOVISTAR" type="default,supl" />
@@ -141,6 +144,7 @@
<apn carrier="Jazztel MMS" mcc="214" mnc="21" apn="jazzmms" mmsc="http://jazztelmms.com:8081" mmsproxy="217.18.32.183" mmsport="8081" type="mms" />
<apn carrier="Lycamobile ES" mcc="214" mnc="25" apn="data.lycamobile.es" user="lmes" password="plus" type="default,supl" />
<apn carrier="Truphone ES" mcc="214" mnc="27" apn="truphone.com" type="default,supl" />
<apn carrier="Tuenti" mcc="214" mnc="32" apn="tuenti.com" user="tuenti" password="tuenti" type="default,supl" />
<apn carrier="Pannon MMS" mcc="216" mnc="01" apn="mms" mmsc="http://mmsc.pgsm.hu/" mmsproxy="193.225.154.22" mmsport="8080" type="mms" />
<apn carrier="Pannon" mcc="216" mnc="01" apn="net" type="default,supl" />
<apn carrier="Telenor Net" mcc="216" mnc="01" apn="net" type="default,supl" />
@@ -169,7 +173,8 @@
<apn carrier="VIPnet MMS" mcc="219" mnc="10" apn="mms.vipnet.hr" mmsc="http://mms.vipnet.hr/servlets/mms" mmsproxy="212.91.99.91" mmsport="8080" type="mms" />
<apn carrier="Telenor RS" mcc="220" mnc="01" apn="internet" user="telenor" password="gprs" proxy="217.65.192.33" port="8080" type="default,supl" />
<apn carrier="Telenor RS MMS" mcc="220" mnc="01" apn="mms" mmsc="http://mms.telenor.rs/servlets/mms" mmsproxy="217.65.192.33" mmsport="8080" type="mms" />
<apn carrier="MTS RS" mcc="220" mnc="03" apn="gprswap" user="mts" password="064" proxy="172.017.088.198" port="8080" type="default,supl" />
<apn carrier="MTS RS INTERNET" mcc="220" mnc="03" apn="gprsinternet" user="mts" password="064" proxy="" port="" type="default,supl" />
<apn carrier="MTS RS WAP" mcc="220" mnc="03" apn="gprswap" user="mts" password="064" server="http://m.mondo.rs" proxy="172.017.088.198" port="8080" type="default,supl" />
<apn carrier="MTS RS MMS" mcc="220" mnc="03" apn="mms" user="mts" password="064" mmsc="http://mms.mts064.telekom.rs/mms/wapenc" mmsproxy="172.017.085.131" mmsport="8080" type="mms" />
<apn carrier="VIP MMS" mcc="220" mnc="05" apn="vipmobile.mms" user="vipmobile" password="vipmobile" mmsc="http://mmsc.vipmobile.rs/" mmsproxy="212.15.182.82" mmsport="8080" type="mms" />
<apn carrier="VIP" mcc="220" mnc="05" apn="vipmobile" user="vipmobile" password="vipmobile" proxy="212.15.182.82" port="8080" type="default,supl" />
@@ -181,6 +186,7 @@
<apn carrier="Tiscali MMS" mcc="222" mnc="01" apn="tiscalimobilemms" mmsc="http://mms.tiscali.mobi/servlets/mms" mmsproxy="213.230.130.89" mmsport="80" type="mms" />
<apn carrier="iTIM" mcc="222" mnc="01" apn="unico.tim.it" proxy="213.230.130.89" port="80" mmsc="http://mms.tim.it/servlets/mms" mmsproxy="213.230.130.89" mmsport="80" type="mms" />
<apn carrier="NOVERCA WEB" mcc="222" mnc="01" apn="web.noverca.it" type="default,supl" />
<apn carrier="COOPVOCE" mcc="222" mnc="01" apn="web.coopvoce.it" type="default,supl" />
<apn carrier="Vodafone IT MMS" mcc="222" mnc="10" apn="mms.vodafone.it" mmsc="http://mms.vodafone.it/servlets/mms" mmsproxy="10.128.224.10" mmsport="80" type="mms" />
<apn carrier="Vodafone IT" mcc="222" mnc="10" apn="mobile.vodafone.it" type="default,supl" />
<apn carrier="Vodafone WEB" mcc="222" mnc="10" apn="web.omnitel.it" type="default,supl" />
@@ -245,7 +251,7 @@
<apn carrier="UBIQUISYS" mcc="234" mnc="01" apn="internet" type="default,supl,mms" />
<apn carrier="Tesco UK" mcc="234" mnc="01" apn="prepay.tesco-mobile.com" user="tescowap" password="password" server="http://wap.tesco-mobile.com/" proxy="193.113.200.195" port="9201" type="default,supl,mms" />
<apn carrier="O2 UK" mcc="234" mnc="10" apn="mobile.o2.co.uk" user="o2web" password="password" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="193.113.200.195" mmsport="8080" authtype="1" type="default,supl,mms" />
<apn carrier="Giffgaff" mcc="234" mnc="10" apn="giffgaff.com" user="giffgaff" password="password" mmsc="http://mmsc.mediamessaging.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="default,supl,mms" />
<apn carrier="giffgaff" mcc="234" mnc="10" apn="giffgaff.com" user="giffgaff" password="password" mmsc="http://mmsc.mediamessaging.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="default,supl,mms" />
<apn carrier="Tesco" mcc="234" mnc="10" apn="prepay.tesco-mobile.com" user="tescowap" password="tescowap" proxy="193.113.200.195" port="8080" mmsc="http://mmsc.mms.02.co.uk:8002" mmsproxy="193.113.200.195" mmsport="8080" type="default,supl,mms" />
<apn carrier="Vodafone UK Contract Internet" mcc="234" mnc="15" apn="Internet" user="web" password="web" server="*" mmsc="http://mms.vodafone.co.uk/servlets/mms" mmsproxy="212.183.137.012" mmsport="8799" type="default,supl,mms" />
<apn carrier="Vodafone Post-pay ISP" mcc="234" mnc="15" apn="internet" user="web" password="web" type="default,supl" />
@@ -282,26 +288,24 @@
<apn carrier="Sure Mobile" mcc="234" mnc="55" apn="internet" type="default,supl" />
<apn carrier="Sure Picture Messaging" mcc="234" mnc="55" apn="mms" mmsc="http://mmsc.gprs.cw.com/" mmsproxy="10.0.3.101" mmsport="80" type="mms" />
<apn carrier="Manx Telecom" mcc="234" mnc="58" apn="3gpronto" proxy="195.010.099.046" port="8080" mmsc="http://mms.manxpronto.net:8002" type="default,supl,mms" />
<apn carrier="3G HSDPA" mcc="234" mnc="58" apn="3gpronto" type="default,supl" />
<apn carrier="Manx Telecom Contract MMS" mcc="234" mnc="58" apn="mms.manxpronto.net" user="mms" password="mms" mmsc="http://mms.manxpronto.net:8002" mmsproxy="195.10.99.46" mmsport="8080" type="mms" />
<apn carrier="Manx Telecom Prepay MMS" mcc="234" mnc="58" apn="mms.prontogo.net" user="mmsgo" password="mmsgo" mmsc="http://mms.manxpronto.net:8002" mmsproxy="195.10.99.41" mmsport="8080" type="mms" />
<apn carrier="Manx Telecom Contract WEB" mcc="234" mnc="58" apn="web.manxpronto.net" user="gprs" password="gprs" type="default,supl" />
<apn carrier="EE Internet" mcc="234" mnc="86" apn="everywhere" user="eesecure" password="secure" authtype="1" type="default,supl,dun" />
<apn carrier="EE MMS" mcc="234" mnc="86" apn="eezone" user="eesecure" password="secure" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" authtype="1" type="mms" />
<apn carrier="TDC Internet" mcc="238" mnc="01" apn="internet" proxy="62.135.173.214" authtype="1" type="default,supl" />
<apn carrier="TDC MMS" mcc="238" mnc="01" apn="mms" mmsc="http://mmsc.tdc.dk:8002" mmsproxy="194.182.251.15" mmsport="8080" authtype="1" type="mms" />
<apn carrier="TDC Internet" mcc="238" mnc="01" apn="internet" proxy="62.135.173.214" authtype="1" mvno_match_data="2380101xxxxxxxx" mvno_type="imsi" type="default,supl" />
<apn carrier="TDC MMS" mcc="238" mnc="01" apn="mms" mmsc="http://mmsc.tdc.dk:8002" mmsproxy="194.182.251.15" mmsport="8080" authtype="1" mvno_match_data="2380101xxxxxxxx" mvno_type="imsi" type="mms" />
<apn carrier="coop mobil MMS" mcc="238" mnc="01" apn="mms" mmsc="http://192.168.241.114:8002" mmsproxy="194.182.251.15" mmsport="8080" type="mms" />
<apn carrier="Telenor Internet" mcc="238" mnc="02" apn="Internet" type="default,supl" />
<apn carrier="Bibob internet DK" mcc="238" mnc="02" apn="internet.bibob.dk" port="8080" type="default,supl,mms" />
<apn carrier="Bibob MMS DK" mcc="238" mnc="02" apn="mms.bibob.dk" proxy="212.88.64.8" port="8080" mmsc="http://mms.telenor.dk" mmsport="8080" type="mms" />
<apn carrier="Telenor DK MMS" mcc="238" mnc="02" apn="telenor" mmsc="http://mms.telenor.dk" mmsproxy="212.88.64.8" mmsport="8080" authtype="1" type="mms" />
<apn carrier="Bibob internet DK" mcc="238" mnc="02" apn="internet.bibob.dk" port="8080" mvno_match_data="BiBoB" mvno_type="spn" type="default,supl,mms" />
<apn carrier="Bibob MMS DK" mcc="238" mnc="02" apn="mms.bibob.dk" proxy="212.88.64.8" port="8080" mmsc="http://mms.telenor.dk" mmsport="8080" mvno_match_data="BiBoB" mvno_type="spn" type="mms" />
<apn carrier="Telenor Internet" mcc="238" mnc="02" apn="Internet" mvno_match_data="TELMORE" mvno_type="spn" type="default,supl" />
<apn carrier="Telenor DK MMS" mcc="238" mnc="02" apn="telenor" mmsc="http://mms.telenor.dk" mmsproxy="212.88.64.8" mmsport="8080" authtype="1" mvno_match_data="TELMORE" mvno_type="spn" type="mms" />
<apn carrier="3 DK" mcc="238" mnc="06" apn="data.tre.dk" mmsc="http://mms.3.dk" mmsproxy="mmsproxy.3.dk" mmsport="8799" type="default,supl,mms" />
<apn carrier="3 Danmark" mcc="238" mnc="06" apn="data.tre.dk" mmsc="http://mms.3.dk/" mmsproxy="172.16.1.25" mmsport="8799" type="default,supl,mms" />
<apn carrier="Lycamobile DK" mcc="238" mnc="12" apn="data.lycamobile.dk" user="lmdk" password="plus" type="default,supl" />
<apn carrier="Telia DK" mcc="238" mnc="20" apn="www.internet.mtelia.dk" type="default,supl" />
<apn carrier="Telia DK MMS" mcc="238" mnc="20" apn="www.mms.mtelia.dk" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" type="mms" />
<apn carrier="Call me Internet" mcc="238" mnc="20" apn="websp" authtype="2" type="default,supl" />
<apn carrier="Call me MMS" mcc="238" mnc="20" apn="mmssp" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" authtype="2" type="mms" />
<apn carrier="Telia DK" mcc="238" mnc="20" apn="www.internet.mtelia.dk" mvno_match_data="2382010x" mvno_type="imsi" type="default,supl" />
<apn carrier="Telia DK MMS" mcc="238" mnc="20" apn="www.mms.mtelia.dk" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" mvno_match_data="2382010x" mvno_type="imsi" type="mms" />
<apn carrier="Call me Internet" mcc="238" mnc="20" apn="websp" authtype="2" mvno_match_data="Call me" mvno_type="spn" type="default,supl" />
<apn carrier="Call me MMS" mcc="238" mnc="20" apn="mmssp" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" authtype="2" mvno_match_data="Call me" mvno_type="spn" type="mms" />
<apn carrier="Telenor Internet" mcc="238" mnc="77" apn="Internet" type="default,supl" />
<apn carrier="Telenor MMS" mcc="238" mnc="77" apn="telenor" mmsc="http://mms.telenor.dk" mmsproxy="212.88.64.8" mmsport="8080" type="mms" />
<apn carrier="Halebop Internet" mcc="240" mnc="01" apn="halebop.telia.se" type="default,supl" />
@@ -329,7 +333,7 @@
<apn carrier="Lycamobile SE" mcc="240" mnc="12" apn="data.lycamobile.se" user="lmse" password="plus" type="default,supl" />
<apn carrier="Ventelo Internet" mcc="242" mnc="01" apn="internet.ventelo.no" type="default,supl" />
<apn carrier="Ventelo MMS" mcc="242" mnc="01" apn="mms.ventelo.no" user="ventelo" password="1111" mmsc="http://mmsc/" mmsproxy="10.10.10.11" mmsport="8080" type="mms" />
<apn carrier="Telenor" mcc="242" mnc="01" apn="telenor" proxy="10.10.10.10" port="8080" mmsc="http://mmsc/" mmsproxy="10.10.10.11" mmsport="8080" authtype="1" type="default,supl,mms" />
<apn carrier="Telenor" mcc="242" mnc="01" apn="telenor" proxy="10.10.10.10" port="8080" mmsc="http://mmsc/" mmsproxy="10.10.10.11" mmsport="8080" type="default,supl,mms" />
<apn carrier="Mobitalk" mcc="242" mnc="01" apn="telenor" user="dj" password="dj" proxy="10.10.10.10" port="8080" mmsc="http://mmsc/" mmsproxy="10.10.10.11" mmsport="8080" type="default,supl,mms" />
<apn carrier="Talkmore" mcc="242" mnc="01" apn="telenor" type="default,supl,mms" />
<apn carrier="NetCom MMS" mcc="242" mnc="02" apn="mms.netcom.no" mmsc="http://mm/" mmsproxy="212.169.66.4" mmsport="8080" type="mms" />
@@ -367,10 +371,8 @@
<apn carrier="Bite LT Internet" mcc="246" mnc="02" apn="banga" type="default,supl" />
<apn carrier="Bite MMS" mcc="246" mnc="02" apn="mms" user="mms@mms" password="mms" mmsc="http://mmsc" mmsproxy="192.168.150.2" mmsport="8080" type="mms" />
<apn carrier="Bite" mcc="246" mnc="02" apn="wap" server="213.226.131.133" type="default,supl" />
<apn carrier="Tele2 Internet LT" mcc="246" mnc="03" apn="internet.tele2.lt" proxy="130.244.196.090" port="8080" type="default,supl" />
<apn carrier="Tele2 LT" mcc="246" mnc="03" apn="internet.vodafone.net" type="default,supl" />
<apn carrier="Tele2 MMS LT" mcc="246" mnc="03" apn="mms.tele2.lt" mmsc="http://mmsc.tele2.lt/" mmsproxy="193.012.040.029" mmsport="8080" type="mms" />
<apn carrier="Tele2 LT MMS" mcc="246" mnc="03" apn="wap.tele2.lt" mmsc="http://mmsc.tele2.lt" mmsproxy="193.12.40.29" mmsport="8080" type="mms" />
<apn carrier="Tele2 Internetas" mcc="246" mnc="03" apn="internet.tele2.lt" proxy="" port="" type="default,supl" />
<apn carrier="Tele2 LT MMS" mcc="246" mnc="03" apn="mms.tele2.lt" user="wap" password="wap" mmsc="http://mmsc.tele2.lt" mmsproxy="193.12.40.29" mmsport="8080" type="mms" />
<apn carrier="VZW Test Internet" mcc="246" mnc="81" apn="VZWINTERNET" type="default,dun,supl" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="VZW Test FOTA" mcc="246" mnc="81" apn="VZWADMIN" type="fota" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="VZW Test IMS" mcc="246" mnc="81" apn="VZWIMS" type="ims" protocol="IPV4V6" roaming_protocol="IPV4V6" />
@@ -576,8 +578,9 @@
<apn carrier="M-Tel MMS" mcc="284" mnc="01" apn="mms-gprs.mtel.bg" user="mtel" password="mtel" mmsc="http://mmsc/" mmsproxy="10.150.0.33" mmsport="8080" type="mms" />
<apn carrier="VIVACOM Internet" mcc="284" mnc="03" apn="internet.vivacom.bg" user="VIVACOM" password="VIVACOM" authtype="0" type="default,supl" />
<apn carrier="VIVACOM MMS" mcc="284" mnc="03" apn="mms.vivacom.bg" user="mms" password="mms" mmsc="http://mmsc.vivacom.bg" mmsproxy="192.168.123.123" mmsport="8080" authtype="0" type="mms" />
<apn carrier="GLOBUL Internet" mcc="284" mnc="05" apn="globul" user="globul" type="default,supl" />
<apn carrier="GLOBUL MMS" mcc="284" mnc="05" apn="mms.globul.bg" user="mms" mmsc="http://mmsc1.mms.globul.bg:8002" mmsproxy="192.168.87.11" mmsport="8004" type="mms" />
<apn carrier="Telenor Internet" mcc="284" mnc="05" apn="telenor" user="telenor" type="default,supl" />
<apn carrier="Telenor MMS" mcc="284" mnc="05" apn="mms.telenor.bg" user="mms" mmsc="http://mmsc1.mms.telenor.bg:8002" mmsproxy="192.168.87.11" mmsport="8004" type="mms" />
<apn carrier="Bulsatcom" mcc="284" mnc="11" apn="bulsat.com" type="default,supl" />
<apn carrier="Turkcell" mcc="286" mnc="01" apn="internet" type="default,supl" />
<apn carrier="Turkcell MMS" mcc="286" mnc="01" apn="mms" user="mms" password="mms" mmsc="http://mms.turkcell.com.tr/servlets/mms" mmsproxy="212.252.169.217" mmsport="8080" type="mms" />
<apn carrier="Vodafone TR" mcc="286" mnc="02" apn="internet" user="vodafone" password="vodafone" type="default,supl" />
@@ -600,10 +603,10 @@
<apn carrier="ProMonte MMS" mcc="297" mnc="01" apn="mms.promonte.com" user="mms" password="mms" mmsc=" http://mm.vor.promonte.com" mmsproxy="192.168.246.005" mmsport="8080" type="mms" />
<apn carrier="T-Mobile CG MMS" mcc="297" mnc="02" apn="mms" user="38267" password="38267" mmsc="http://192.168.180.100/servlets/mms" mmsproxy="10.0.5.19" mmsport="8080" type="mms" />
<apn carrier="T-Mobile CG" mcc="297" mnc="02" apn="tmcg-wnw" user="38267" password="38267" type="default,supl" />
<apn carrier="Telus SP" mcc="302" mnc="220" apn="sp.telus.com" mmsc="http://aliasredirect.net/proxy/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,supl,mms" />
<apn carrier="Telus SP" mcc="302" mnc="220" apn="sp.telus.com" mmsc="http://aliasredirect.net/proxy/mmsc" mmsproxy="74.49.0.18" mmsport="80" mvno_match_data="54" mvno_type="gid" type="default,supl,mms" />
<apn carrier="Telus SP Tether" mcc="302" mnc="220" apn="isp.telus.com" mmsc="http://aliasredirect.net/proxy/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,supl,mms" />
<apn carrier="Koodo SP" mcc="302" mnc="220" apn="sp.koodo.com" proxy="74.49.0.18" port="80" mmsc="http://aliasredirect.net/proxy/koodo/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,supl,mms" />
<apn carrier="Public Mobile" mcc="302" mnc="220" apn="sp.mb.com" mmsc="http://aliasredirect.net/proxy/mb/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,supl,mms" />
<apn carrier="Koodo SP" mcc="302" mnc="220" apn="sp.koodo.com" proxy="74.49.0.18" port="80" mmsc="http://aliasredirect.net/proxy/koodo/mmsc" mmsproxy="74.49.0.18" mmsport="80" mvno_match_data="4B" mvno_type="gid" type="default,supl,mms" />
<apn carrier="Public Mobile" mcc="302" mnc="220" apn="sp.mb.com" mmsc="http://aliasredirect.net/proxy/mb/mmsc" mmsproxy="74.49.0.18" mmsport="80" mvno_match_data="50" mvno_type="gid" type="default,supl,mms" />
<apn carrier="Eastlink Internet" mcc="302" mnc="270" apn="wisp.mobi.eastlink.ca" type="default,supl" />
<apn carrier="Eastlink MMS" mcc="302" mnc="270" apn="mms.mobi.eastlink.ca" mmsc="http://mmss.mobi.eastlink.ca" mmsproxy="10.232.12.49" mmsport="8080" type="mms" />
<apn carrier="Mobilicity MMS" mcc="302" mnc="320" apn="mms.davewireless.com" mmsc="http://mms.mobilicity.net" mmsproxy="10.100.3.4" mmsport="8080" type="mms" />
@@ -683,12 +686,11 @@
<apn carrier="Sprint EHRPD ota" mcc="310" mnc="120" apn="otasn" type="fota" protocol="IPV4V6" roaming_protocol="IPV4V6" bearer="13" />
<apn carrier="Sprint LTE internet" mcc="310" mnc="120" apn="n.ispsn" type="default,mms,supl,hipri" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" bearer="14" />
<apn carrier="Sprint EHRPD internet" mcc="310" mnc="120" apn="n.ispsn" type="default,mms,supl,hipri" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" bearer="13" />
<apn carrier="Sprint internet" mcc="310" mnc="120" apn="n.ispsn" type="default,mms,supl,hipri" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="Boost" mcc="310" mnc="120" apn="cinet.spcs" type="default,supl,mms,dun,fota" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="Credo Mobile" mcc="310" mnc="120" apn="n.w1.ispsn" type="default,mms" mmsc="http://mms.plspictures.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="Ting" mcc="310" mnc="120" apn="n.t8.ispsn" type="default,mms" mmsc="http://mms.plspictures.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="FreedomPop" mcc="310" mnc="120" apn="n.f6.ispsn" type="default,mms" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="Virgin Mobile" mcc="310" mnc="120" apn="n.vmu.ispsn" user="Sprint" password="*" mmsproxy="68.28.31.7" mmsport="80" mmsc="http://mmsc.vmobl.com:8088/mms?" type="default,supl,mms,fota,dun" />
<apn carrier="Sprint internet" mcc="310" mnc="120" apn="n.ispsn" type="mms,supl,hipri" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="Boost" mcc="310" mnc="120" apn="cinet.spcs" type="supl,mms,dun,fota" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="Credo Mobile" mcc="310" mnc="120" apn="n.w1.ispsn" type="mms" mmsc="http://mms.plspictures.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="Ting" mcc="310" mnc="120" apn="n.t8.ispsn" type="mms" mmsc="http://mms.plspictures.com" mmsproxy="68.28.31.7" mmsport="80" protocol="IPV4V6" roaming_protocol="IPV4V6" />
<apn carrier="Virgin Mobile" mcc="310" mnc="120" apn="n.vmu.ispsn" user="Sprint" password="*" mmsproxy="68.28.31.7" mmsport="80" mmsc="http://mmsc.vmobl.com:8088/mms?" type="supl,mms,fota,dun" />
<apn carrier="My Multi Media" mcc="310" mnc="130" apn="mms.c1.ama" user="cell1mms" password="cell1" mmsc="http://mms.iot1.com/amarillo/mms.php" type="mms" />
<apn carrier="Cricket AIO" mcc="310" mnc="150" apn="ndo" mmsc="http://mmsc.aiowireless.net" mmsproxy="proxy.aiowireless.net" mmsport="80" type="default,mms,fota,supl" />
<apn carrier="T-Mobile US 160" mcc="310" mnc="160" apn="epc.tmobile.com" user="none" password="none" server="*" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" />
@@ -706,6 +708,7 @@
<apn carrier="Simple" mcc="310" mnc="260" apn="simple" mmsc="http://smpl.mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" />
<apn carrier="StraightTalk T-Mobile" mcc="310" mnc="260" apn="wap.tracfone" port="8080" mmsc="http://mms.tracfone.com" type="default,supl,mms" />
<apn carrier="Walmart Family Mobile" mcc="310" mnc="260" apn="web.omwtoday.com" mmsproxy="216.155.165.50" mmsport="8080" mmsc="http://wirelessfour.mmsmvno.com/mms/wapenc" type="default,supl,mms" />
<apn carrier="Wholesale" mcc="310" mnc="260" apn="wholesale" mmsc="http://wholesale.mmsmvno.com/mms/wapenc" type="default,supl,mms" />
<apn carrier="T-Mobile US 270" mcc="310" mnc="270" apn="epc.tmobile.com" user="none" password="none" server="*" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" />
<apn carrier="T-Mobile US 310" mcc="310" mnc="310" apn="epc.tmobile.com" user="none" password="none" server="*" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" />
<apn carrier="Cingular 380 ATT" mcc="310" mnc="380" apn="proxy" proxy="wireless.cingular.com" port="80" mmsc="http://mmsc.cingular.com/" mmsproxy="wireless.cingular.com" type="default,supl,mms" />
@@ -830,7 +833,7 @@
<apn carrier="LIME" mcc="344" mnc="920" apn="internet" type="default,supl" />
<apn carrier="Digicel VC" mcc="360" mnc="070" apn="wap.digiceloecs.com" user="wapoecs" password="wap03oecs" type="default,supl" />
<apn carrier="Setar MMS" mcc="363" mnc="01" apn="mms.setar.aw" mmsc="http://mms.setar.aw" mmsproxy="209.88.130.210" mmsport="8081" type="mms" />
<apn carrier="Setar" mcc="363" mnc="01" apn="wap.setar.aw" type="default,supl" />
<apn carrier="Setar" mcc="363" mnc="01" apn="internet.setar.aw" type="default,supl" />
<apn carrier="BATELCO BS" mcc="364" mnc="390" apn="internet.btcbahamas.com" type="default,supl" />
<apn carrier="Orange net" mcc="370" mnc="01" apn="orangenet.com.do" user="" password="" authtype="1" type="default,supl,dun" />
<apn carrier="Orange MMS" mcc="370" mnc="01" apn="orangeworld" user="orange" password="orange" mmsproxy="172.16.126.70" mmsport="8080" mmsc="http://mms.orange.com.do/servlets/mms" authtype="1" type="mms" />
@@ -841,6 +844,7 @@
<apn carrier="BMobile Prepaid" mcc="374" mnc="12" apn="bconnected" type="default" port="8080" />
<apn carrier="BMobile MMS" mcc="374" mnc="12" apn="mms" type="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080"/>
<apn carrier="BMobile Buzz" mcc="374" mnc="12" apn="buzz" type="default,mms" proxy="192.168.210.104" port="8080" mmsc="http://192.168.210.103/operator/wap" />
<apn carrier="Digicel TT" mcc="374" mnc="13" apn="web.digiceltt.com" type="default,supl" />
<apn carrier="Azercell" mcc="400" mnc="01" apn="internet" type="default,supl" />
<apn carrier="Azercell MMS" mcc="400" mnc="01" apn="mms" mmsc="http://mms.azercell.com/cMMSC/post" mmsproxy="10.0.154.101" mmsport="8080" type="mms" />
<apn carrier="Bakcell" mcc="400" mnc="02" apn="mms" mmsc="http://mms.bakcell.com/mms/wapenc" mmsproxy="213.172.091.046" mmsport="8080" type="default,supl,mms" />
@@ -850,17 +854,27 @@
<apn carrier="Kcell MMS" mcc="401" mnc="02" apn="mms" mmsc="http://mms.kcell.kz/post" mmsproxy="195.047.255.007" mmsport="8080" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="01" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="01" apn="www" type="default,supl" />
<apn carrier="Airtel" mcc="404" mnc="02" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="404" mnc="03" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="02" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="02" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="02" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="03" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="03" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="03" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="IDEA" mcc="404" mnc="04" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="404" mnc="04" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="05" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="05" apn="www" type="default,supl" />
<apn carrier="Airtel GPRS" mcc="404" mnc="06" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="06" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="06" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="IDEA" mcc="404" mnc="07" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="404" mnc="07" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="09" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="404" mnc="09" apn="rcomnet" type="default,supl" />
<apn carrier="Airtel" mcc="404" mnc="10" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Reliance RTel MMS" mcc="404" mnc="09" apn="MMS" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" />
<apn carrier="Reliance RTel" mcc="404" mnc="09" apn="SMARTNET" type="default,supl" />
<apn carrier="Reliance WAP" mcc="404" mnc="09" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Airtel GPRS" mcc="404" mnc="10" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="10" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="10" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="11" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="11" apn="www" type="default,supl" />
<apn carrier="IDEA" mcc="404" mnc="12" apn="internet" type="default,supl" />
@@ -874,11 +888,14 @@
<apn carrier="SPICE MMS" mcc="404" mnc="14" apn="spicemms" user="User Mobile number" password="spice" mmsc="http://10.200.200.3:8514" mmsproxy="10.200.200.3" mmsport="8080" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="15" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="15" apn="www" type="default,supl" />
<apn carrier="Airtel" mcc="404" mnc="16" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="16" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="16" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="16" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Aircel" mcc="404" mnc="17" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="17" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="18" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="17" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="18" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="404" mnc="18" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance WAP" mcc="404" mnc="18" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="IDEA" mcc="404" mnc="19" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="404" mnc="19" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="20" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
@@ -890,49 +907,60 @@
<apn carrier="IDEA" mcc="404" mnc="24" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="404" mnc="24" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="404" mnc="25" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="25" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="25" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="27" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="27" apn="www" type="default,supl" />
<apn carrier="Aircel" mcc="404" mnc="28" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="28" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="28" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="404" mnc="29" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="29" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="29" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="30" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="30" apn="www" type="default,supl" />
<apn carrier="Airtel" mcc="404" mnc="31" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="31" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="31" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="31" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Aircel" mcc="404" mnc="33" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="33" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="33" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="BSNL" mcc="404" mnc="34" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
<apn carrier="BSNL MMS" mcc="404" mnc="34" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="404" mnc="35" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="35" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="36" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="35" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="36" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="404" mnc="36" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance WAP" mcc="404" mnc="36" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Aircel" mcc="404" mnc="37" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="37" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="37" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="BSNL" mcc="404" mnc="38" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
<apn carrier="BSNL MMS" mcc="404" mnc="38" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="Airtel" mcc="404" mnc="40" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="40" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="40" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="40" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Aircel" mcc="404" mnc="41" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="41" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="41" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="404" mnc="42" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="42" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="42" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="43" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="43" apn="www" type="default,supl" />
<apn carrier="IDEA" mcc="404" mnc="44" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="404" mnc="44" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="SPICE" mcc="404" mnc="44" apn="spicegprs" type="default,supl" />
<apn carrier="SPICE MMS" mcc="404" mnc="44" apn="spicemms" user="User Mobile number" password="spice" mmsc="http://10.200.200.3:8514" mmsproxy="10.200.200.3" mmsport="8080" type="mms" />
<apn carrier="Airtel" mcc="404" mnc="45" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="45" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="45" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="45" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="BPL MMS" mcc="404" mnc="46" apn="mizone" user="MSISDN" password="bplmmsc" mmsc="http://mms.bplmobile.com:8080" mmsproxy="10.0.0.10" mmsport="8080" type="mms" />
<apn carrier="BPL" mcc="404" mnc="46" apn="www" user="MSISDN" password="bplmmsc" type="default,supl" />
<apn carrier="Airtel" mcc="404" mnc="49" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="50" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="49" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="49" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="49" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="50" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="404" mnc="50" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance WAP" mcc="404" mnc="50" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="BSNL" mcc="404" mnc="51" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
<apn carrier="BSNL MMS" mcc="404" mnc="51" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="52" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="52" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="404" mnc="52" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance WAP" mcc="404" mnc="52" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="BSNL" mcc="404" mnc="53" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
<apn carrier="BSNL MMS" mcc="404" mnc="53" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="BSNL" mcc="404" mnc="54" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
@@ -949,19 +977,25 @@
<apn carrier="BSNL MMS" mcc="404" mnc="59" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="60" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="60" apn="www" type="default,supl" />
<apn carrier="Airtel GPRS" mcc="404" mnc="61" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="61" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="61" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.001.201.172" mmsport="8799" type="mms" />
<apn carrier="BSNL" mcc="404" mnc="62" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
<apn carrier="BSNL MMS" mcc="404" mnc="62" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="BSNL" mcc="404" mnc="64" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
<apn carrier="BSNL MMS" mcc="404" mnc="64" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="BSNL" mcc="404" mnc="66" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
<apn carrier="BSNL MMS" mcc="404" mnc="66" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="67" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="67" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="404" mnc="67" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance WAP" mcc="404" mnc="67" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="MTNL" mcc="404" mnc="68" apn="mtnl.net" user="mtnl" password="mtnl123" proxy="10.10.10.10" port="9401" type="default,supl" />
<apn carrier="MTNL MMS" mcc="404" mnc="68" apn="mtnl.net" user="mtnl" password="mtnl123" mmsc="http://mtnlmms/" mmsproxy="10.10.10.10" mmsport="9401" type="mms" />
<apn carrier="MTNL" mcc="404" mnc="69" apn="mtnl.net" user="mtnl" password="mtnl123" proxy="10.10.10.10" port="9401" type="default,supl" />
<apn carrier="MTNL MMS" mcc="404" mnc="69" apn="mtnl.net" user="mtnl" password="mtnl123" mmsc="http://mtnlmms/" mmsproxy="10.10.10.10" mmsport="9401" type="mms" />
<apn carrier="Airtel" mcc="404" mnc="70" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="70" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="70" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="70" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="BSNL" mcc="404" mnc="71" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
<apn carrier="BSNL MMS" mcc="404" mnc="71" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="BSNL" mcc="404" mnc="72" apn="bsnlnet" user="MSISDN" password="MSISDN" type="default,supl" />
@@ -984,13 +1018,14 @@
<apn carrier="BSNL MMS" mcc="404" mnc="81" apn="mmssouth.cellone.in" user="MSISDN" password="mmsc" mmsc="http://10.7.236.11:8514" mmsproxy="10.7.236.11" mmsport="8080" type="mms" />
<apn carrier="IDEA" mcc="404" mnc="82" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="404" mnc="82" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="83" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="83" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="404" mnc="83" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance WAP" mcc="404" mnc="83" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="84" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="84" apn="www" type="default,supl" />
<apn carrier="Reliance MMS" mcc="404" mnc="85" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance MMS" mcc="404" mnc="85" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="404" mnc="85" apn="rcomnet" type="default,supl" />
<apn carrier="India Hutch" mcc="404" mnc="86" apn="portalnmms" proxy="10.10.1.100" port="9401" mmsc="http://mms1.hutchworld.co.in/mms/" type="default,supl,mms" />
<apn carrier="Reliance WAP" mcc="404" mnc="85" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="86" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="404" mnc="86" apn="www" type="default,supl" />
<apn carrier="IDEA" mcc="404" mnc="87" apn="internet" type="default,supl" />
@@ -999,57 +1034,92 @@
<apn carrier="Vodafone IN" mcc="404" mnc="88" apn="www" type="default,supl" />
<apn carrier="IDEA" mcc="404" mnc="89" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="404" mnc="89" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="Airtel" mcc="404" mnc="90" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="90" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="90" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="90" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Aircel" mcc="404" mnc="91" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="404" mnc="91" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Airtel" mcc="404" mnc="92" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="404" mnc="93" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="404" mnc="94" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="404" mnc="95" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="404" mnc="96" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="404" mnc="97" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="404" mnc="98" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Vodafone IN MMS" mcc="404" mnc="751" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Reliance MMS" mcc="405" mnc="01" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Aircel MMS" mcc="404" mnc="91" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="92" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="92" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="92" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="93" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="93" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="93" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="94" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="94" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="94" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="95" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="95" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="95" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="96" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="96" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="96" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="97" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="97" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="97" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="404" mnc="98" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="404" mnc="98" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="404" mnc="98" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Reliance MMS" mcc="405" mnc="01" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://10.239.221.47/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="01" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="03" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="01" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="03" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="03" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="05" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="03" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="05" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="05" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="06" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="05" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="06" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="06" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="07" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="06" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="07" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="07" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="08" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="07" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="08" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="08" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="09" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="08" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="09" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="09" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="10" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="09" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="10" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="10" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="11" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="10" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="11" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="11" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="12" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="11" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="12" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="12" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="13" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="12" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="13" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="13" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="14" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="13" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="14" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="14" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="15" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="14" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="15" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="15" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="17" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="15" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="17" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="17" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="18" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="17" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="18" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="18" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="19" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="18" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="19" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="19" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="20" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="19" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="20" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="20" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="21" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="20" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="21" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="21" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="22" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="21" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="22" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="22" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="23" apn="rcommms" mmsc="http://mms.rcom.co.in:6081/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance WAP" mcc="405" mnc="22" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="Reliance MMS" mcc="405" mnc="23" apn="rcommms" proxy="10.239.221.5" port="8080" mmsc="http://mms.rcom.co.in/mms" mmsproxy="10.239.221.5" mmsport="8080" type="mms" />
<apn carrier="Reliance" mcc="405" mnc="23" apn="rcomnet" type="default,supl" />
<apn carrier="Reliance WAP" mcc="405" mnc="23" apn="rcomwap" proxy="10.239.221.5" port="8080" type="default,supl" />
<apn carrier="TA TA DoCoMo" mcc="405" mnc="025" apn="TATA.DOCOMO.INTERNET" type="default,supl" />
<apn carrier="TA TA DoCoMo MMS" mcc="405" mnc="025" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" />
<apn carrier="TA TA DoCoMo" mcc="405" mnc="026" apn="TATA.DOCOMO.INTERNET" type="default,supl" />
@@ -1094,12 +1164,24 @@
<apn carrier="TA TA DoCoMo MMS" mcc="405" mnc="046" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" />
<apn carrier="TA TA DoCoMo" mcc="405" mnc="047" apn="TATA.DOCOMO.INTERNET" type="default,supl" />
<apn carrier="TA TA DoCoMo MMS" mcc="405" mnc="047" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" />
<apn carrier="Airtel" mcc="405" mnc="51" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="405" mnc="52" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="405" mnc="53" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="405" mnc="54" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="405" mnc="55" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel" mcc="405" mnc="56" apn="airtelgprs.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="default,supl,mms" />
<apn carrier="Airtel GPRS" mcc="405" mnc="51" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="405" mnc="51" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="405" mnc="51" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="405" mnc="52" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="405" mnc="52" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="405" mnc="52" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="405" mnc="53" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="405" mnc="53" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="405" mnc="53" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="405" mnc="54" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="405" mnc="54" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="405" mnc="54" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="405" mnc="55" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="405" mnc="55" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="405" mnc="55" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Airtel GPRS" mcc="405" mnc="56" apn="airtelgprs.com" type="default,supl" />
<apn carrier="Airtel Live" mcc="405" mnc="56" apn="airtelfun.com" proxy="100.1.200.99" port="8080" type="default,supl" />
<apn carrier="Airtel MMS" mcc="405" mnc="56" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" />
<apn carrier="Vodafone IN MMS" mcc="405" mnc="66" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
<apn carrier="Vodafone IN" mcc="405" mnc="66" apn="www" type="default,supl" />
<apn carrier="Vodafone IN MMS" mcc="405" mnc="67" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" />
@@ -1122,29 +1204,31 @@
<apn carrier="IDEA" mcc="405" mnc="799" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="405" mnc="799" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="800" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="800" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="800" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="801" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="801" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="801" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="802" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="802" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="802" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="803" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="803" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="803" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="804" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="804" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="804" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="805" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="805" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="805" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="806" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="806" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="807" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="807" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="807" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="808" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="808" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="808" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="809" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="809" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="809" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="810" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="810" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="810" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="811" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="811" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="811" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="Aircel" mcc="405" mnc="812" apn="aircelgprs" type="default,supl" />
<apn carrier="Aircel MMS" mcc="405" mnc="812" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" />
<apn carrier="Aircel MMS" mcc="405" mnc="812" apn="aircelmms" proxy="172.17.83.69" port="8080" mmsc="http://172.17.83.67//servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" />
<apn carrier="IDEA" mcc="405" mnc="845" apn="internet" type="default,supl" />
<apn carrier="IDEA MMS" mcc="405" mnc="845" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" />
<apn carrier="IDEA" mcc="405" mnc="846" apn="internet" type="default,supl" />
@@ -1193,11 +1277,24 @@
<apn carrier="Etisalat MMS" mcc="412" mnc="50" apn="etisalat.af.mms" proxy="10.0.0.172" port="80" type="mms" />
<apn carrier="Mobitel" mcc="413" mnc="01" apn="mobitel3g" type="default,supl" />
<apn carrier="Mobitel MMS" mcc="413" mnc="01" apn="wapmms" mmsc="http://192.168.50.165" mmsproxy="192.168.50.163" mmsport="8080" type="mms" />
<apn carrier="Mobitel WAP" mcc="413" mnc="01" apn="mobitel3g" proxy="192.168.050.163" port="8080" type="default,supl" />
<apn carrier="Dialog Mobile Broadband" mcc="413" mnc="02" apn="dialogbb" server="dialog" mmsc="http://mms.dialog.lk:3130/mmsc" mmsproxy="192.168.122.2" mmsport="8080" type="default,supl,mms" />
<apn carrier="Dialog WAP Prepaid" mcc="413" mnc="02" apn="ppwap" proxy="192.168.122.2" mmsport="8080" type="default,supl" />
<apn carrier="Dialog Internet Prepaid" mcc="413" mnc="02" apn="www.dialogsl.com" proxy="192.168.122.2" port="8080" type="default,supl" />
<apn carrier="Dialog Internet Postpaid" mcc="413" mnc="02" apn="dialogbb" type="default,supl" />
<apn carrier="Dialog MMS Prepaid" mcc="413" mnc="02" apn="ppwap" mmsc="http://mms.dialog.lk:3130/mmsc" mmsproxy="192.168.122.2" type="mms" />
<apn carrier="Dialog MMS Postpaid" mcc="413" mnc="02" apn="www.dialogsl.com" mmsc="http://mms.dialog.lk:3130/mmsc" mmsproxy="192.168.122.2" type="mms" />
<apn carrier="Etisalat" mcc="413" mnc="03" apn="ebb" type="default,supl" />
<apn carrier="Etisalat MMS" mcc="413" mnc="03" apn="mms" mmsc="http://mms.etisalt.lk:8085" mmsproxy="192.168.104.4" mmsport="9401" type="mms" />
<apn carrier="Etisalat Internet Prepaid" mcc="413" mnc="03" apn="web" type="default,supl" />
<apn carrier="Etisalat Internet Postpaid" mcc="413" mnc="03" apn="internet" type="default,supl" />
<apn carrier="Etisalat WAP" mcc="413" mnc="03" apn="wap" proxy="192.168.104.4" port="9401" type="default,supl" />
<apn carrier="Airtel Postpaid" mcc="413" mnc="05" apn="airteldata" type="default,supl" />
<apn carrier="Airtel MMS" mcc="413" mnc="05" apn="airtellive" mmsc="http://mms.airtel.lk" mmsproxy="10.200.184.86" mmsport="8080" type="mms" />
<apn carrier="Airtel Prepaid" mcc="413" mnc="05" apn="airtellive" type="default,supl" />
<apn carrier="Airtel" mcc="413" mnc="05" apn="default" type="default,supl" />
<apn carrier="Hutch3G" mcc="413" mnc="08" apn="hutch3g" type="default,supl" />
<apn carrier="Hutch WAP" mcc="413" mnc="08" apn="hutch3g" proxy="10.220.135.249" port="8080" type="default,supl" />
<apn carrier="MPT" mcc="414" mnc="01" apn="mptnet" user="mptnet" password="mptnet" type="default,supl" />
<apn carrier="Alfa" mcc="415" mnc="01" apn="internet.mic1.com.lb" user="mic1" password="mic1" type="default,supl" />
<apn carrier="Alfa MMS" mcc="415" mnc="01" apn="mms.mic1.com.lb" user="mic1" password="mic1" mmsc="http://mms.mic1.com.lb" mmsproxy="192.168.23.51" mmsport="9201" type="mms" />
@@ -1256,7 +1353,7 @@
<apn carrier="3G Portal" mcc="425" mnc="01" apn="uwap.orange.co.il" port="8080" type="default,supl" />
<apn carrier="MMS 3G" mcc="425" mnc="01" apn="uwap.orange.co.il" mmsc="http://192.168.220.15/servlets/mms" mmsport="8080" type="mms" />
<apn carrier="Internet 3G" mcc="425" mnc="01" apn="modem.orange.net.il" type="default,supl" />
<apn carrier="CellCOM" mcc="425" mnc="02" apn="internetg" type="default,supl" />
<apn carrier="CellCOM" mcc="425" mnc="02" apn="sphone" type="default,supl" />
<apn carrier="CellCOM MMS" mcc="425" mnc="02" apn="mms" user="" password="" mmsc="http://mms.cellcom.co.il" mmsproxy="172.31.29.38" mmsport="8080" type="mms" />
<apn carrier="Pelephone" mcc="425" mnc="03" apn="internet.pelephone.net.il" user="pcl@3g" password="pcl" type="default,supl" />
<apn carrier="Pelephone MMS" mcc="425" mnc="03" apn="mms.pelephone.net.il" user="pcl@3g" password="pcl" server="pelephone" mmsc="http://mmsu.pelephone.net.il" mmsproxy="10.170.9.54" mmsport="9093" type="mms" />
@@ -1281,20 +1378,29 @@
<apn carrier="Q-tel" mcc="427" mnc="01" apn="web.qtel" user="gprs" password="gprs" type="default,supl" />
<apn carrier="Vodafone QA MMS" mcc="427" mnc="02" apn="vodafone.com.qa" mmsc="http://mms.vodafone.com.qa/mmsc" mmsproxy="10.101.97.102" mmsport="80" type="mms" />
<apn carrier="Vodafone QA" mcc="427" mnc="02" apn="web.vodafone.com.qa" type="default,supl" />
<apn carrier="Nepal Telecom Internet" mcc="429" mnc="01" apn="ntnet" type="default,supl" />
<apn carrier="Nepal Telecom MMS" mcc="429" mnc="01" apn="ntmms" mmsc="http://192.80.11.180" mmsproxy="192.80.7.133" mmsport="8000" type="mms" />
<apn carrier="Nepal Telecom WAP" mcc="429" mnc="02" apn="ntwap" proxy="192.80.7.133" port="8000" type="default,supl" />
<apn carrier="Ncell Internet" mcc="429" mnc="02" apn="web" type="default,supl" />
<apn carrier="Ncell MMS" mcc="429" mnc="02" apn="mms" mmsc="http://192.168.19.15" mmsproxy="192.168.19.15" mmsport="8080" type="mms" />
<apn carrier="Ncell WAP" mcc="429" mnc="02" apn="web" proxy="192.168.19.15" port="8080" type="default,supl" />
<apn carrier="Beeline UZ" mcc="434" mnc="04" apn="internet.beeline.uz" user="beeline" password="beeline" type="default,supl" />
<apn carrier="Beeline UZ MMS" mcc="434" mnc="04" apn="mms.beeline.uz" user="beeline" password="beeline" mmsc="http://mms" mmsproxy="172.30.30.166" mmsport="8080" type="mms" />
<apn carrier="em.std" mcc="440" mnc="00" apn="em.std" user="em" password="em" type="default,supl" bearer="14"/>
<apn carrier="@nifty" mcc="440" mnc="10" apn="lte.fenics.jp" user="nifty@lte.nifty.com" password="nifty" authtype="3" type="default,supl" />
<apn carrier="@nifty do LTE" mcc="440" mnc="10" apn="lte.fenics.jp" user="nifty@lte.nifty.com" password="nifty" authtype="3" type="default,supl" />
<apn carrier="BB.excite" mcc="440" mnc="10" apn="vmobile.jp" user="bb@excite.co.jp" password="excite" authtype="3" type="default,supl" />
<apn carrier="BIGLOBE" mcc="440" mnc="10" apn="biglobe.jp" user="user" password="0000" authtype="2" type="default,supl" />
<apn carrier="DMM mobile" mcc="440" mnc="10" apn="vmobile.jp" user="dmm@dmm.com" password="dmm" authtype="3" type="default,supl" />
<apn carrier="DTI" mcc="440" mnc="10" apn="dream.jp" user="user@dream.jp" password="dti" authtype="2" type="default,supl" />
<apn carrier="IIJmio/BIC SIM" mcc="440" mnc="10" apn="iijmio.jp" user="mio@iij" server="" password="iij" authtype="3" type="default,supl" />
<apn carrier="IIJmio/BIC SIM" mcc="440" mnc="10" apn="iijmio.jp" user="mio@iij" password="iij" authtype="3" type="default,supl" />
<apn carrier="NifMo" mcc="440" mnc="10" apn="mda.nifty.com" user="mda@nifty" password="nifty" authtype="3" type="default,supl" />
<apn carrier="OCN 3G" mcc="440" mnc="10" apn="3g-d-2.ocn.ne.jp" user="mobileid@ocn" password="mobile" authtype="2" type="default,supl" />
<apn carrier="OCN LTE" mcc="440" mnc="10" apn="lte-d.ocn.ne.jp" user="mobileid@ocn" password="mobile" authtype="2" type="default,supl" />
<apn carrier="So-net" mcc="440" mnc="10" apn="so-net.jp" user="nuro" password="nuro" authtype="2" type="default,supl" />
<apn carrier="U-mobile" mcc="440" mnc="10" apn="umobile.jp" user="umobile@umobile.jp" password="umobile" authtype="3" type="default,supl" />
<apn carrier="U-mobile/freetel" mcc="440" mnc="10" apn="umobile.jp" user="umobile@umobile.jp" password="umobile" authtype="3" type="default,supl" />
<apn carrier="Wi-Ho!" mcc="440" mnc="10" apn="bbnw.jp" user="user" password="0000" authtype="3" type="default,supl" />
<apn carrier="WirelessGate 3G" mcc="440" mnc="10" apn="foma01.wi-gate.net" user="wg@sim" password="wg" authtype="3" type="default,supl" />
<apn carrier="WirelessGate LTE" mcc="440" mnc="10" apn="foma01.wi-gate.net" user="wg@sim" password="wg" authtype="3" type="default,supl" />
<apn carrier="WirelessGate LTE" mcc="440" mnc="10" apn="xi01.wi-gate.net" user="wg@sim" password="wg" authtype="3" type="default,supl" />
<apn carrier="b-mobile 4g" mcc="440" mnc="10" apn="bmobile.ne.jp" user="bmobile@4g" password="bmobile" authtype="3" type="default,supl" />
<apn carrier="b-mobile aeon" mcc="440" mnc="10" apn="bmobile.ne.jp" user="bmobile@aeon" password="bmobile" authtype="3" type="default,supl" />
<apn carrier="b-mobile am" mcc="440" mnc="10" apn="bmobile.ne.jp" user="bmobile@am" password="bmobile" authtype="3" type="default,supl" />
@@ -1310,9 +1416,11 @@
<apn carrier="mopera U FF" mcc="440" mnc="10" apn="open.mopera.net" type="default,supl" />
<apn carrier="mopera U Flat" mcc="440" mnc="10" apn="mopera.flat.foma.ne.jp" type="default,supl" />
<apn carrier="spモード" mcc="440" mnc="10" apn="spmode.ne.jp" type="default,supl" />
<apn carrier="楽天" mcc="440" mnc="10" apn="dm.jplat.net" user="mobile@rakutenbb.jp" password="rakutenbb" authtype="3" type="default,supl" />
<apn carrier="楽天ブロードバンド" mcc="440" mnc="10" apn="dm.jplat.net" user="mobile@rakutenbb.jp" password="rakutenbb" authtype="3" type="default,supl" />
<apn carrier="楽天モバイル" mcc="440" mnc="10" apn="vdm.jp" user="rakuten@vdm" password="vrkt" authtype="3" type="default,supl" />
<apn carrier="Y!mobile" mcc="440" mnc="20" apn="plus.acs.jp" user="ym" password="ym" mmsc="http://mms-s" mmsproxy="andmms.plusacs.ne.jp" mmsport="8080" authtype="2" type="default,supl,mms" />
<apn carrier="andoworld" mcc="440" mnc="20" apn="andoworld.softbank.ne.jp" mmsc="http://mms/" mmsproxy="andmms.softbank.ne.jp" mmsport="8080" authtype="2" type="default,supl,mms" />
<apn carrier="fourgsmartphone" mcc="440" mnc="20" apn="fourgsmartphone" user="" password="" mmsc="http://mms/" mmsproxy="andmms.softbank.ne.jp" mmsport="8080" authtype="2" type="default,supl,mms" />
<apn carrier="jpspir" mcc="440" mnc="20" apn="jpspir" user="sirobit" password="amstkoi" mmsc="http://mms/" mmsproxy="smilemms.softbank.ne.jp" mmsport="8080" type="default,supl,mms" />
<apn carrier="open" mcc="440" mnc="20" apn="open.softbank.ne.jp" user="opensoftbank" password="ebMNuX1FIHg9d3DA" mmsc="http://mms/" mmsproxy="mmsopen.softbank.ne.jp" mmsport="8080" type="default,supl,mms" />
<apn carrier="plus" mcc="440" mnc="20" apn="plus.softbank" user="plus" password="softbank" mmsc="http://mms/" mmsproxy="andmms.softbank.ne.jp" mmsport="8080" authtype="3" type="default,supl,mms" />
@@ -1321,6 +1429,7 @@
<apn carrier="smile.world" mcc="440" mnc="20" apn="smile.world" user="dna1trop" password="so2t3k3m2a" mmsc="http://mms/" mmsproxy="smilemms.softbank.ne.jp" mmsport="8080" authtype="1" type="default,supl,mms" />
<apn carrier="LTE NET" mcc="440" mnc="50" apn="uno.au-net.ne.jp" user="685840734641020@uno.au-net.ne.jp" password="KpyrR6BP" authtype="2" type="default,mms,supl,hipri" protocol="IPV4V6" roaming_protocol="IP" />
<apn carrier="LTE NET for DATA" mcc="440" mnc="50" apn="au.au-net.ne.jp" user="user@au.au-net.ne.jp" password="au" authtype="2" type="default,mms,supl,hipri" protocol="IPV4V6" roaming_protocol="IP" />
<apn carrier="UQ mobile" mcc="440" mnc="50" apn="uqmobile.jp" user="uq@uqmobile.jp" password="uq" mmsc="http://mms.ezweb.ne.jp/MMS" mmsport="80" authtype="2" type="default,supl,hipri,dun" />
<apn carrier="mineo" mcc="440" mnc="50" apn="mineo.jp" user="mineo@k-opti.com" password="mineo" authtype="2" type="default,supl,hipri" />
<apn carrier="SKT3G" mcc="450" mnc="05" apn="web.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,supl,mms" />
<apn carrier="SK Telecom (Roaming)" mcc="450" mnc="05" apn="roaming.sktelecom.com" server="*" mmsc="vmms.nate.com" mmsport="8082" type="default,supl,mms" />
@@ -1428,11 +1537,20 @@
<apn carrier="TransAsia" mcc="466" mnc="99" apn="internet" type="default,supl" />
<apn carrier="TransAsia MMS" mcc="466" mnc="99" apn="mms" mmsc="http://mms" mmsproxy="10.1.1.2" mmsport="80" type="mms" />
<apn carrier="台灣大哥大(TW Mobile) (twm)" mcc="466" mnc="99" apn="twm" type="default,supl" />
<apn carrier="Grameenphone" mcc="470" mnc="01" apn="gpinterneth" type="default,supl" />
<apn carrier="Robi MMS" mcc="470" mnc="02" apn="WAP" mmsc="http://192.168.23.4/was" mmsproxy="192.168.023.007" mmsport="9028" type="mms" />
<apn carrier="Robi" mcc="470" mnc="02" apn="internet" port="9201" type="default,supl" />
<apn carrier="Grameenphone" mcc="470" mnc="01" apn="gpinternet" type="default,supl" />
<apn carrier="Grameenphone MMS" mcc="470" mnc="01" apn="gpmms" mmsc="http://mms.gpsurf.net/servlets/mms" mmsproxy="10.128.1.2" mmsport="8080" type="mms" />
<apn carrier="Grameenphone WAP" mcc="470" mnc="01" apn="gpinternet" proxy="10.128.1.2" port="8080" type="default,supl" />
<apn carrier="Robi MMS" mcc="470" mnc="02" apn="wap" mmsc="http://192.168.23.4/was" mmsproxy="192.168.023.007" mmsport="9028" type="mms" />
<apn carrier="Robi" mcc="470" mnc="02" apn="internet" type="default,supl" />
<apn carrier="Robi WAP" mcc="470" mnc="02" apn="wap" proxy="10.128.1.2" port="9208" type="default,supl" />
<apn carrier="Banglalink MMS" mcc="470" mnc="03" apn="blmms" mmsc="http://" mmsproxy="10.10.55.34" mmsport="8799" type="mms" />
<apn carrier="Banglalink" mcc="470" mnc="03" apn="blweb" type="default,supl" />
<apn carrier="Banglalink WAP" mcc="470" mnc="03" apn="blwap" proxy="10.10.55.34" port="8799" type="default,supl" />
<apn carrier="Tele Talk" mcc="470" mnc="04" apn="wap" type="default,supl" />
<apn carrier="Tele Talk WAP" mcc="470" mnc="04" apn="wap" proxy="192.168.145.101" port="9201" type="default,supl" />
<apn carrier="Airtel BD" mcc="470" mnc="07" apn="internet" type="default,supl" />
<apn carrier="Airtel BD MMS" mcc="470" mnc="07" apn="mms" mmsc="http://10.6.0.21/servlets/mms" mmsproxy="10.6.0.2" mmsport="8080" type="mms" />
<apn carrier="Airtel BD WAP" mcc="470" mnc="07" apn="wap" proxy="10.6.0.2" port="8080" type="default,supl" />
<apn carrier="Warid BD" mcc="470" mnc="07" apn="internet" type="default,supl" />
<apn carrier="Warid BD MMS" mcc="470" mnc="07" apn="mms" mmsc="http://mms.waridtel.com.bd/index.jsp" mmsproxy="10.128.5.6" mmsport="8080" type="mms" />
<apn carrier="Maxis 2G Internet" mcc="502" mnc="12" apn="net" user="maxis" password="wap" type="default,supl" />
@@ -1569,6 +1687,8 @@
<apn carrier="Orange TN" mcc="605" mnc="01" apn="keypro" type="default,supl" />
<apn carrier="weborange" mcc="605" mnc="01" apn="weborange" type="default,supl" />
<apn carrier="Orange MMS" mcc="605" mnc="01" apn="mms.otun" mmsc="http://mms.orange.tn" mmsproxy="10.12.1.52" mmsport="8080" type="mms" />
<apn carrier="Tunisie Télécom TN" mcc="605" mnc="02" apn="internet.tn" type="default,supl" />
<apn carrier="Ooredoo TN" mcc="605" mnc="03" apn="internet.ooredoo.tn" type="default,supl" />
<apn carrier="Libyana MMS" mcc="606" mnc="00" apn="mms" mmsc="http://62.240.62.180:80" mmsproxy="192.168.8.148" mmsport="8000" type="mms" />
<apn carrier="Libyana" mcc="606" mnc="00" apn="wap" proxy="192.168.8.148" port="8000" type="default,supl" />
<apn carrier="Al-Madar MMS" mcc="606" mnc="01" apn="almadar.mms" mmsc="http://almadar.mms/servlets/mms" mmsproxy="41.208.82.50" mmsport="8080" type="mms" />
@@ -1592,7 +1712,8 @@
<apn carrier="Zain NG" mcc="621" mnc="20" apn="internet.ng.zain.com" type="default,supl" />
<apn carrier="MTN NG" mcc="621" mnc="30" apn="web.gprs.mtnnigeria.net" user="web" password="web" proxy="10.199.212.2" type="default,supl" />
<apn carrier="MTN NG MMS" mcc="621" mnc="30" apn="web.gprs.mtnnigeria.net" user="web" password="web" mmsc="http://10.199.212.8/servlets/mms" mmsproxy="10.199.212.2" mmsport="8080" type="mms" />
<apn carrier="Glo" mcc="621" mnc="50" apn="glo3gvideo" proxy="10.100.98.22" type="default,supl" />
<apn carrier="Glo Mobile Internet" mcc="621" mnc="50" apn="gloflat" user="flat" password="flat" proxy="10.100.98.22" type="default,supl" />
<apn cariier="Glo PAYU" mcc="621" mnc="50" apn="glosecure" type="default,supl" />
<apn carrier="Glo MMS" mcc="621" mnc="50" apn="glomms" user="mms" password="mms" mmsc="http://mms.gloworld.com/mmsc" mmsproxy="010.100.082.004" mmsport="3130" type="mms" />
<apn carrier="Etisalat NG" mcc="621" mnc="60" apn="etisalat" type="default,supl" />
<apn carrier="Etisalat NG MMS" mcc="621" mnc="60" apn="etisalat" mmsc="http://10.71.170.30:38090/was" mmsproxy="10.71.170.5" mmsport="8080" type="mms" />
@@ -1662,6 +1783,10 @@
<apn carrier="Movistar MMS" mcc="710" mnc="300" apn="mms.movistar.ni" user="movistarni" password="movistarni" mmsproxy="10.12.23.1" mmsport="80" mmsc="http://mms.movistar.ni" authtype="1" type="mms" />
<apn carrier="Enitel" mcc="710" mnc="730" apn="internet.ideasalo.ni" user="internet" password="internet" authtype="1" type="default,supl,dun" />
<apn carrier="Enitel MMS" mcc="710" mnc="730" apn="mms.indeasalo.ni" user="mms" password="mms" mmsproxy="10.6.32.2" mmsport="8080" mmsc="http://10.6.32.27/servlets/mms" authtype="1" type="mms" />
<apn carrier="Claro" mcc="712" mnc="03" apn="internet.ideasclaro" type="default,supl" />
<apn carrier="Claro MMS" mcc="712" mnc="03" apn="mms.ideasclaro" mmsproxy="216.230.133.66" mmsport="8080" mmsc="http://mms.ideasclaro.com:8002" type="mms" />
<apn carrier="Movistar Internet" mcc="712" mnc="04" apn="internet.movistart.cr" user="movistarcr" password="movistarcr" authtype="1" type="default,supl" />
<apn carrier="Movistar MMS" mcc="712" mnc="04" apn="mms.movistar.cr" user="movistarcr" password="movistarcr" mmsc="http://mms.movistar.cr" mmsproxy="10.221.79.83" mmsport="80" authtype="1" type="mms" />
<apn carrier="Cable and Wireless Panama" mcc="714" mnc="01" apn="apn01.cwpanama.com.pa" type="default,supl" />
<apn carrier="Cable and Wireless Panama MMS" mcc="714" mnc="01" apn="apn02.cwpanama.com.pa" mmsc="http://mms.zonamovil.com.pa:80/i.bin" mmsproxy="172.25.3.5" mmsport="8080" type="mms" />
<apn carrier="Movistar PA" mcc="714" mnc="02" apn="internet.movistar.pa" user="movistarpa" password="movistarpa" type="default,supl"/>

View File

@@ -562,6 +562,7 @@
<apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="9" server="*" />
<apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="3" server="*" />
<apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="1" server="*" />
<apn mcc="310" mnc="000" carrier="Verizon CDMA HRPD" mmsc="http://mms.vzwreseller.com/servlets/mms" type="default,mms,hipri,dun,supl" authtype="3" mvno_type="spn" mvno_match_data="Tracfone" />
<apn mcc="310" mnc="4" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE" />
<apn mcc="310" mnc="4" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE" />
<apn mcc="310" mnc="4" carrier="Verizon CDMA HRPD" apn="CdmaNai" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,hipri,dun,stdhipri,supl" protocol="IPV4V6" bearer="6" carrier_enabled="FALSE" />
@@ -1717,8 +1718,6 @@
<apn mcc="434" mnc="4" carrier="Beeline-UZB MMS" apn="mms.beeline.uz" mmsc="http://mms" mmsproxy="172.30.30.166" mmsport="8080" type="mms" user="beeline" password="beeline" authtype="1" />
<apn mcc="434" mnc="5" carrier="UCELL MMS" apn="mms" mmsc="http://mmsc:8002/" mmsproxy="10.64.164.10" mmsport="8080" type="mms" />
<apn mcc="434" mnc="07" carrier="MTS-UZB MMS" apn="mms.mts.uz" mmsc="http://mmsc/was" mmsproxy="10.10.0.10" mmsport="8080" type="mms" />
<apn mcc="440" mnc="20" carrier="Application" apn="plus.acs.jp" mmsc="http://mms-s" mmsproxy="andmms.plusacs.ne.jp" mmsport="8080" type="default,mms,supl" user="plusw6q9tattkmpk" password="msfbbam83bsdetxb" authtype="2" />
<apn mcc="440" mnc="20" carrier="Application" apn="andoworld.softbank.ne.jp" mmsc="http://mms/" mmsproxy="andmms.softbank.ne.jp" mmsport="8080" type="default,mms,supl,hpri" authtype="0" />
<apn mcc="450" mnc="5" carrier="SKT LTE INTERNET" apn="lte.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms,supl,fota,cbs" authtype="0" server="*" />
<apn mcc="450" mnc="5" carrier="SKT-Home" apn="lte.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms" authtype="0" server="*" />
<apn mcc="450" mnc="05" carrier="SKT LTE INTERNET" apn="lte.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="ia,default,mms,supl,fota,cbs" server="*" />

View File

@@ -1,19 +1,31 @@
import sys
import re
import argparse
import sqlite3
import gzip
from progressbar import ProgressBar, Counter, Timer
from lxml import etree
parser = argparse.ArgumentParser(prog='apntool', description="""Process Android's apn xml files and drop them into an easily
queryable SQLite db. Tested up to version 9 of their APN file.""")
parser.add_argument('-v', '--version', action='version', version='%(prog)s v1.0')
parser = argparse.ArgumentParser(prog='apntool', description="""Process Android's apn xml files and drop them into an
easily queryable SQLite db. Tested up to version 9 of
their APN file.""")
parser.add_argument('-v', '--version', action='version', version='%(prog)s v1.1')
parser.add_argument('-i', '--input', help='the xml file to parse', default='apns.xml', required=False)
parser.add_argument('-o', '--output', help='the sqlite db output file', default='apns.db', required=False)
parser.add_argument('--quiet', help='do not show progress or verbose instructions', action='store_true', required=False)
parser.add_argument('--no-gzip', help="do not gzip after creation", action='store_true', required=False)
args = parser.parse_args()
def normalized(target):
o2_typo = re.compile(r"02\.co\.uk")
port_typo = re.compile(r"(\d+\.\d+\.\d+\.\d+)\.(\d+)")
leading_zeros = re.compile(r"(/|\.|^)0+(\d+)")
subbed = o2_typo.sub(r'o2.co.uk', target)
subbed = port_typo.sub(r'\1:\2', subbed)
subbed = leading_zeros.sub(r'\1\2', subbed)
return subbed
try:
connection = sqlite3.connect(args.output)
cursor = connection.cursor()
@@ -28,26 +40,39 @@ try:
cursor.execute("PRAGMA page_size=32768")
cursor.execute("VACUUM")
cursor.execute("DROP TABLE IF EXISTS apns")
cursor.execute("""CREATE TABLE apns(_id INTEGER PRIMARY KEY, mccmnc TEXT, mcc TEXT, mnc TEXT, carrier TEXT, apn TEXT,
mmsc TEXT, port INTEGER, type TEXT, protocol TEXT, bearer TEXT, roaming_protocol TEXT,
cursor.execute("""CREATE TABLE apns(_id INTEGER PRIMARY KEY, mccmnc TEXT, mcc TEXT, mnc TEXT, carrier TEXT,
apn TEXT, mmsc TEXT, port INTEGER, type TEXT, protocol TEXT, bearer TEXT, roaming_protocol TEXT,
carrier_enabled INTEGER, mmsproxy TEXT, mmsport INTEGER, proxy TEXT, mvno_match_data TEXT,
mvno_type TEXT, authtype INTEGER, user TEXT, password TEXT, server TEXT)""")
apns = etree.parse(args.input)
root = apns.getroot()
pbar = ProgressBar(widgets=['Processed: ', Counter(), ' apns (', Timer(), ')'], maxval=len(list(root))).start() if not args.quiet else None
pbar = None
if not args.quiet:
pbar = ProgressBar(widgets=['Processed: ', Counter(), ' apns (', Timer(), ')'], maxval=len(list(root))).start()
count = 0
for apn in root.iter("apn"):
if apn.get("mmsc") == None:
if apn.get("mmsc") is None:
continue
sqlvars = ["?" for x in apn.attrib.keys()] + ["?"]
mccmnc = "%s%s" % (apn.get("mcc"), apn.get("mnc"))
values = [apn.get(attrib) for attrib in apn.attrib.keys()] + [mccmnc]
keys = apn.attrib.keys() + ["mccmnc"]
mccmnc = "%s%s" % (apn.get("mcc"), apn.get("mnc"))
normalized_mmsc = normalized(apn.get("mmsc"))
if normalized_mmsc != apn.get("mmsc"):
print("normalize MMSC: %s => %s" % (apn.get("mmsc"), normalized_mmsc))
apn.set("mmsc", normalized_mmsc)
if not apn.get("mmsproxy") is None:
normalized_mmsproxy = normalized(apn.get("mmsproxy"))
if normalized_mmsproxy != apn.get("mmsproxy"):
print("normalize proxy: %s => %s" % (apn.get("mmsproxy"), normalized_mmsproxy))
apn.set("mmsproxy", normalized_mmsproxy)
values = [apn.get(attrib) for attrib in apn.attrib.keys()] + [mccmnc]
keys = apn.attrib.keys() + ["mccmnc"]
cursor.execute("SELECT 1 FROM apns WHERE mccmnc = ? AND apn = ?", [mccmnc, apn.get("apn")])
if cursor.fetchone() == None:
if cursor.fetchone() is None:
statement = "INSERT INTO apns (%s) VALUES (%s)" % (", ".join(keys), ", ".join(sqlvars))
cursor.execute(statement, values)

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

BIN
artwork/logo-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -5,84 +5,137 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:0.14.2'
classpath 'com.android.tools.build:gradle:1.0.1'
classpath files('libs/gradle-witness.jar')
}
}
apply plugin: 'com.android.application'
apply from: 'strip_play_services.gradle'
apply plugin: 'witness'
repositories {
maven {
url "https://repo1.maven.org/maven2"
url "https://repo1.maven.org/maven2/"
}
maven {
url "https://raw.github.com/whispersystems/maven/master/preferencefragment/releases/"
}
maven {
url "https://raw.github.com/whispersystems/maven/master/gson/releases/"
}
maven {
url "https://raw.github.com/whispersystems/maven/master/smil/releases/"
}
maven {
url "https://raw.github.com/whispersystems/maven/master/shortcutbadger/releases/"
}
jcenter()
mavenLocal()
}
dependencies {
compile 'me.leolin:ShortcutBadger:1.0.2-WS2'
compile 'se.emilsjolander:stickylistheaders:2.2.0'
compile 'com.google.android.gms:play-services:6.1.71'
compile 'com.google.android.gms:play-services-base:6.5.87'
compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
compile 'org.w3c:smil:1.0.0'
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
compile 'com.github.chrisbanes.photoview:library:1.2.3'
compile 'com.android.support:appcompat-v7:20.0.0'
compile 'com.madgag.spongycastle:prov:1.51.0.0'
compile 'com.makeramen:roundedimageview:1.5.0'
compile ('com.afollestad:material-dialogs:0.6.4.7') {
exclude module: 'appcompat-v7'
exclude module: 'recyclerview-v7'
exclude module: 'support-annotations'
}
compile 'com.soundcloud.android:android-crop:0.9.10@aar'
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:recyclerview-v7:21.0.3'
compile 'com.melnykov:floatingactionbutton:1.1.0'
compile 'com.google.zxing:android-integration:3.1.0'
compile ('com.android.support:support-v4-preferencefragment:1.0.0@aar'){
exclude module: 'support-v4'
}
compile 'com.squareup.dagger:dagger:1.2.2'
compile ("com.doomonafireball.betterpickers:library:1.5.3") {
exclude group: 'com.android.support', module: 'support-v4'
}
compile 'com.madgag.spongycastle:prov:1.51.0.0'
provided 'com.squareup.dagger:dagger-compiler:1.2.2'
androidTestCompile 'com.squareup:fest-android:1.0.8'
androidTestCompile 'com.google.dexmaker:dexmaker:1.1'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.1'
compile 'org.whispersystems:jobmanager:0.11.0'
compile 'org.whispersystems:libpastelog:1.0.6'
compile 'org.whispersystems:textsecure-android:1.2.4'
compile project(':libtextsecure')
compile project(':jobqueue')
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
androidTestCompile ('org.assertj:assertj-core:1.7.1') {
exclude group: 'org.hamcrest', module: 'hamcrest-core'
}
androidTestCompile ('com.squareup.assertj:assertj-android:1.0.0') {
exclude group: 'org.hamcrest', module: 'hamcrest-core'
}
androidTestCompile ('com.android.support.test.espresso:espresso-core:2.0') {
exclude group: 'javax.inject'
}
androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
}
dependencyVerification {
verify = [
'me.leolin:ShortcutBadger:027977c718035e5997035e04e05152d6c72d94df645e8b7099a274ada722bd14',
'se.emilsjolander:stickylistheaders:89146b46c96fea0e40200474a2625cda10fe94891e4128f53cdb42375091b9b6',
'com.google.android.gms:play-services:32e7d1834a1cf8fa4b17e8d359db580c286e26c1eefbf84fdb9996eac8d74919',
'com.google.android.gms:play-services-base:832cb6b3130e871db6a412c4ab585656dbcc5e7948101f190186757785703f75',
'com.astuetz:pagerslidingtabstrip:f1641396732c7132a7abb837e482e5ee2b0ebb8d10813fc52bbaec2c15c184c2',
'org.w3c:smil:085dc40f2bb249651578bfa07499fd08b16ad0886dbe2c4078586a408da62f9b',
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
'com.github.chrisbanes.photoview:library:8b5344e206f125e7ba9d684008f36c4992d03853c57e5814125f88496126e3cc',
'com.android.support:appcompat-v7:736f576ab0b68d27bdf18b1e7931566e6d8254b73965175313e87f8866b91547',
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
'com.makeramen:roundedimageview:7dda2e78c406760e5c356ccce59b0df46b5b171cf18abb891998594405021548',
'com.afollestad:material-dialogs:6ed57c1c479219f8ae929c310fc171dbfcbcee8326a6dcd50a91959d69eccdf0',
'com.soundcloud.android:android-crop:ffd4b973cf6e97f7d64118a0dc088df50e9066fd5634fe6911dd0c0c5d346177',
'com.android.support:appcompat-v7:5dbeb5316d0a6027d646ae552804c3baa5e3bd53f7f33db50904d51505c8a0e5',
'com.android.support:recyclerview-v7:e525ad3f33c84bb12b73d2dc975b55364a53f0f2d0697e043efba59ba73e22d2',
'com.melnykov:floatingactionbutton:0679ad9f7d61eb7aeab91e8dc56358cdedd5b1c1b9c48464499ffa05c40d3985',
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
'com.android.support:support-v4-preferencefragment:5470f5872514a6226fa1fc6f4e000991f38805691c534cf0bd2778911fc773ad',
'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883',
'com.android.support:support-v4:81f2b1c2c94efd5a4ec7fcd97b6cdcd00e87a933905c5c86103c7319eb024572',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'com.doomonafireball.betterpickers:library:132ecd685c95a99e7377c4e27bfadbb2d7ed0bea995944060cd62d4369fdaf3d',
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
'org.whispersystems:jobmanager:ea9cb943c4892fb90c1eea1be30efeb85cefca213d52c788419553b58d0ed70d',
'org.whispersystems:libpastelog:550d33c565380d90f4c671e7b8ed5f3a6da55a9fda468373177106b2eb5220b2',
'org.whispersystems:textsecure-android:c867b4e1f9cf430aa15c73841833469f71af9c6149becea447a72b96de214398',
'com.android.support:support-annotations:fdee2354787ef66b268e75958de3f7f6c4f8f325510a6dac9f49c929f83a63de',
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'org.whispersystems:textsecure-java:141132e1c917759bdc285f80ed9e9784be0dc99ec6872f738439505955832906',
'org.whispersystems:axolotl-android:40d3db5004a84749a73f68d2f0d01b2ae35a73c54df96d8c6c6723b96efb6fc0',
'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab',
'org.whispersystems:gson:08f4f7498455d1539c9233e5aac18e9b1805815ef29221572996508eb512fe51',
'com.android.support:support-annotations:1aa96ef0cc4a445bfc2f93ccf762305bc57fa107b12afe9d11f3863ae8a11036',
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
'com.squareup.okhttp:okhttp:89b7f63e2e5b6c410266abc14f50fe52ea8d2d8a57260829e499b1cd9f0e61af',
'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d',
'org.whispersystems:axolotl-java:6daee739b89d8d7101de6d98f77132fee48495c6ea647d880e77def842f999ea',
'org.whispersystems:curve25519-android:3c29a4131a69b0d16baaa3d707678deb39602c3a3ffd75805ce7f9db252e5d0d',
'com.squareup.okio:okio:5e1098bd3fdee4c3347f5ab815b40ba851e4ab1b348c5e49a5b0362f0ce6e978',
'com.fasterxml.jackson.core:jackson-annotations:0ca408c24202a7626ec8b861e99d85eca5e38b73311dd6dd12e3e9deecc3fe94',
'com.fasterxml.jackson.core:jackson-core:cbf4604784b4de226262845447a1ad3bb38a6728cebe86562e2c5afada8be2c0',
'org.whispersystems:curve25519-java:9ccef8f5aba05d9942336f023c589d6278b4f9135bdc34a7bade1f4e7ad65fa3',
'com.android.support:support-v4:703572d3015a088cc5604b7e38885af3d307c829d0c5ceaf8654ff41c71cd160',
]
}
android {
compileSdkVersion 21
buildToolsVersion '21.1.1'
compileSdkVersion 22
buildToolsVersion '22.0.1'
dexOptions {
javaMaxHeapSize "4g"
}
defaultConfig {
minSdkVersion 9
targetSdkVersion 19
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
buildConfigField "long", "BUILD_TIMESTAMP", System.currentTimeMillis() + "L"
}
compileOptions {
@@ -90,44 +143,72 @@ android {
targetCompatibility JavaVersion.VERSION_1_7
}
android {
buildTypes {
debug {
minifyEnabled false
}
release {
minifyEnabled false
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest {
java.srcDirs = ['androidTest/java']
resources.srcDirs = ['androidTest/java']
aidl.srcDirs = ['androidTest/java']
renderscript.srcDirs = ['androidTest/java']
}
}
packagingOptions {
exclude 'LICENSE.txt'
exclude 'LICENSE'
exclude 'NOTICE'
exclude 'asm-license.txt'
}
signingConfigs {
release
}
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-google-play-services.pro',
'proguard-dagger.pro',
'proguard-jackson.pro',
'proguard-sqlite.pro',
'proguard-appcompat-v7.pro',
'proguard-square-okhttp.pro',
'proguard-square-okio.pro',
'proguard-spongycastle.pro',
'proguard-rounded-image-view.pro',
'proguard.cfg'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-google-play-services.pro',
'proguard-dagger.pro',
'proguard-jackson.pro',
'proguard-sqlite.pro',
'proguard-appcompat-v7.pro',
'proguard-square-okhttp.pro',
'proguard-square-okio.pro',
'proguard-spongycastle.pro',
'proguard-rounded-image-view.pro',
'proguard.cfg'
signingConfig signingConfigs.release
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest {
java.srcDirs = ['androidTest/java']
resources.srcDirs = ['androidTest/java']
aidl.srcDirs = ['androidTest/java']
renderscript.srcDirs = ['androidTest/java']
}
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}
lintOptions {
abortOnError false
}

View File

@@ -28,3 +28,4 @@ Truths which we believe to be self-evident:
1. **There is no such thing as time.** Protocol ideas that require synchronized
clocks are doomed to failure.
Before you submit a pull request, please check if your code follows the [Code style Guidelines](https://github.com/WhisperSystems/RedPhone/wiki/Code-style-Guidelines).

View File

@@ -1,6 +1,6 @@
#Fri Nov 14 10:44:11 MSK 2014
#Fri Nov 28 10:03:17 PST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

1
jobqueue/.gitignore vendored
View File

@@ -1 +0,0 @@
/build

View File

@@ -1,238 +0,0 @@
# JobManager
An Android library that facilitates scheduling persistent jobs which are executed when their
prerequisites have been met. Similar to Path's android-priority-queue.
## The JobManager Way
Android apps often need to perform blocking operations. A messaging app might need to make REST
API calls over a network, send SMS messages, download attachments, and interact with a database.
The standard Android way to do these things are with Services, AsyncTasks, or a dedicated Thread.
However, some of an app's operations might need to wait until certain dependencies are available
(such as a network connection), and some of the operations might need to be durable (complete even if the
app restarts before they have a chance to run). The standard Android way can result in
a lot of retry logic, timers for monitoring dependencies, and one-off code for making operations
durable.
By contrast, the JobManager way allows operations to be broken up into Jobs. A Job represents a
unit of work to be done, the prerequisites that need to be met (such as network access) before the
work can execute, and the characteristics of the job (such as durable persistence).
Applications construct a `JobManager` at initialization time:
```
public class ApplicationContext extends Application {
private JobManager jobManager;
@Override
public void onCreate() {
initializeJobManager();
}
private void initializeJobManager() {
this.jobManager = JobManager.newBuilder(this)
.withName("SampleJobManager")
.withConsumerThreads(5)
.build();
}
...
}
```
This constructs a new `JobManager` with 5 consumer threads dedicated to executing Jobs. A
Job looks like this:
```
public class SampleJob extends Job {
public SampleJob() {
super(JobParameters.newBuilder().create());
}
@Override
public onAdded() {
// Called after the Job has been added to the queue.
}
@Override
public void onRun() {
// Here's where we execute our work.
Log.w("SampleJob", "Hello, world!");
}
@Override
public void onCanceled() {
// This would be called if the job had failed.
}
@Override
public boolean onShouldRetry(Exception exception) {
// Called if onRun() had thrown an exception to determine whether
// onRun() should be called again.
return false;
}
}
```
A Job is scheduled simply by adding it to the JobManager:
```
this.jobManager.add(new SampleJob());
```
## Persistence
To create durable Jobs, the JobManager needs to be given an interface responsible for serializing
and deserializing Job objects. A `JavaJobSerializer` is included with JobManager that uses Java
Serialization, but you can specify your own serializer if you wish:
```
public class ApplicationContext extends Application {
private JobManager jobManager;
@Override
public void onCreate() {
initializeJobManager();
}
private void initializeJobManager() {
this.jobManager = JobManager.newBuilder(this)
.withName("SampleJobManager")
.withConsumerThreads(5)
.withJobSerializer(new JavaJobSerializer())
.build();
}
...
}
```
The Job simply needs to declare itself as durable when constructed:
```
public class SampleJob extends Job {
public SampleJob() {
super(JobParameters.newBuilder()
.withPersistence()
.create());
}
...
```
Persistent jobs that are enqueued will be serialized to disk to ensure that they run even if
the App restarts first. A Job's onAdded() method is called after the commit to disk is complete.
## Requirements
A Job might have certain requirements that need to be met before it can run. A requirement is
represented by the `Requirement` interface. Each `Requirement` must also have a corresponding
`RequirementProvider` that is registered with the JobManager.
A `Requirement` tells you whether it is present when queried, while a `RequirementProvider`
broadcasts to a listener when a Requirement's status might have changed. `Requirement` is attached
to Job, while `RequirementProvider` is attached to JobManager.
One common `Requirement` a `Job` might depend on is the presence of network connectivity.
A `NetworkRequirement` is bundled with JobManager:
```
public class ApplicationContext extends Application {
private JobManager jobManager;
@Override
public void onCreate() {
initializeJobManager();
}
private void initializeJobManager() {
this.jobManager = JobManager.newBuilder(this)
.withName("SampleJobManager")
.withConsumerThreads(5)
.withJobSerializer(new JavaJobSerializer())
.withRequirementProviders(new NetworkRequirementProvider(this))
.build();
}
...
}
```
The Job declares itself as having a `Requirement` when constructed:
```
public class SampleJob extends Job {
public SampleJob(Context context) {
super(JobParameters.newBuilder()
.withPersistence()
.withRequirement(new NetworkRequirement(context))
.create());
}
...
```
## Dependency Injection
It is possible that Jobs (and Requirements) might require dependency injection. A simple example
is `Context`, which many Jobs might require, but can't be persisted to disk for durable Jobs. Or
maybe Jobs require more complex DI through libraries such as Dagger.
JobManager has an extremely primitive DI mechanism strictly for injecting `Context` objects into
Jobs and Requirements after they're deserialized, and includes support for plugging in more complex
DI systems such as Dagger.
The JobManager `Context` injection works by having your `Job` and/or `Requirement` implement the
`ContextDependent` interface. `Job`s and `Requirement`s implementing that interface will get a
`setContext(Context context)` call immediately after the persistent `Job` or `Requirement` is
deserialized.
To plugin a more complex DI mechanism, simply pass an instance of the `DependencyInjector` interface
to the `JobManager`:
```
public class ApplicationContext extends Application implements DependencyInjector {
private JobManager jobManager;
@Override
public void onCreate() {
initializeJobManager();
}
private void initializeJobManager() {
this.jobManager = JobManager.newBuilder(this)
.withName("SampleJobManager")
.withConsumerThreads(5)
.withJobSerializer(new JavaJobSerializer())
.withRequirementProviders(new NetworkRequirementProvider(this))
.withDependencyInjector(this)
.build();
}
@Override
public void injectDependencies(Object object) {
// And here we do our DI magic.
}
...
}
```
`injectDependencies(Object object)` will be called for a `Job` before the job's `onAdded()` method
is called, or after a persistent job is deserialized.

View File

@@ -1,19 +0,0 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 21
buildToolsVersion '21.1.1'
defaultConfig {
applicationId "org.whispersystems.jobqueue"
minSdkVersion 9
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}

View File

@@ -1,225 +0,0 @@
package org.whispersystems.jobqueue;
import android.test.AndroidTestCase;
import org.whispersystems.jobqueue.jobs.PersistentTestJob;
import org.whispersystems.jobqueue.jobs.RequirementDeferringTestJob;
import org.whispersystems.jobqueue.jobs.RequirementTestJob;
import org.whispersystems.jobqueue.jobs.TestJob;
import org.whispersystems.jobqueue.persistence.JavaJobSerializer;
import org.whispersystems.jobqueue.requirements.RequirementProvider;
import org.whispersystems.jobqueue.util.MockRequirement;
import org.whispersystems.jobqueue.util.MockRequirementProvider;
import org.whispersystems.jobqueue.util.PersistentMockRequirement;
import org.whispersystems.jobqueue.util.PersistentRequirement;
import org.whispersystems.jobqueue.util.PersistentResult;
import org.whispersystems.jobqueue.util.RunnableThrowable;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class JobManagerTest extends AndroidTestCase {
public void testTransientJobExecution() throws InterruptedException {
TestJob testJob = new TestJob();
JobManager jobManager = JobManager.newBuilder(getContext())
.withName("transient-test")
.withConsumerThreads(1)
.build();
jobManager.add(testJob);
assertTrue(testJob.isAdded());
assertTrue(testJob.isRan());
}
public void testTransientRequirementJobExecution() throws InterruptedException {
MockRequirementProvider provider = new MockRequirementProvider();
MockRequirement requirement = new MockRequirement(false);
TestJob testJob = new RequirementTestJob(requirement);
JobManager jobManager = JobManager.newBuilder(getContext())
.withName("transient-requirement-test")
.withRequirementProviders(provider)
.withConsumerThreads(1)
.build();
jobManager.add(testJob);
assertTrue(testJob.isAdded());
assertTrue(!testJob.isRan());
requirement.setPresent(true);
provider.fireChange();
assertTrue(testJob.isRan());
}
public void testTransientRequirementDeferringJobExecution() throws InterruptedException {
final Object lock = new Object();
RunnableThrowable waitRunnable = new RunnableThrowable() {
public Boolean shouldThrow = false;
@Override
public void run() throws Exception {
try {
synchronized (lock) {
lock.wait();
if (shouldThrow) {
throw new Exception();
}
}
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}
@Override
public void shouldThrow(Boolean value) {
shouldThrow = value;
}
};
MockRequirementProvider provider = new MockRequirementProvider();
MockRequirement requirement = new MockRequirement(false);
RequirementDeferringTestJob testJob = new RequirementDeferringTestJob(requirement, 5, waitRunnable);
JobManager jobManager = JobManager.newBuilder(getContext())
.withName("transient-requirement-test")
.withRequirementProviders(provider)
.withConsumerThreads(1)
.build();
jobManager.add(testJob);
waitRunnable.shouldThrow(true);
requirement.setPresent(true);
provider.fireChange();
assertTrue(testJob.isRan());
assertTrue(!testJob.isFinished());
synchronized (lock) { lock.notifyAll(); }
assertTrue(!testJob.isFinished());
requirement.setPresent(false);
provider.fireChange();
assertTrue(!testJob.isFinished());
synchronized (lock) { lock.notifyAll(); }
assertTrue(!testJob.isFinished());
waitRunnable.shouldThrow(false);
requirement.setPresent(true);
provider.fireChange();
assertTrue(!testJob.isFinished());
synchronized (lock) { lock.notifyAll(); }
assertTrue(testJob.isFinished());
}
public void testPersistentJobExecuton() throws InterruptedException {
PersistentMockRequirement requirement = new PersistentMockRequirement();
PersistentTestJob testJob = new PersistentTestJob(requirement);
JobManager jobManager = JobManager.newBuilder(getContext())
.withName("persistent-requirement-test3")
.withJobSerializer(new JavaJobSerializer())
.withConsumerThreads(1)
.build();
PersistentResult.getInstance().reset();
PersistentRequirement.getInstance().setPresent(false);
jobManager.add(testJob);
assertTrue(PersistentResult.getInstance().isAdded());
assertTrue(!PersistentResult.getInstance().isRan());
PersistentRequirement.getInstance().setPresent(true);
jobManager = JobManager.newBuilder(getContext())
.withName("persistent-requirement-test3")
.withJobSerializer(new JavaJobSerializer())
.withConsumerThreads(1)
.build();
assertTrue(PersistentResult.getInstance().isRan());
}
public void testEncryptedJobExecuton() throws InterruptedException {
EncryptionKeys keys = new EncryptionKeys(new byte[30]);
PersistentMockRequirement requirement = new PersistentMockRequirement();
PersistentTestJob testJob = new PersistentTestJob(requirement, keys);
JobManager jobManager = JobManager.newBuilder(getContext())
.withName("persistent-requirement-test4")
.withJobSerializer(new JavaJobSerializer())
.withConsumerThreads(1)
.build();
jobManager.setEncryptionKeys(keys);
PersistentResult.getInstance().reset();
PersistentRequirement.getInstance().setPresent(false);
jobManager.add(testJob);
assertTrue(PersistentResult.getInstance().isAdded());
assertTrue(!PersistentResult.getInstance().isRan());
PersistentRequirement.getInstance().setPresent(true);
jobManager = JobManager.newBuilder(getContext())
.withName("persistent-requirement-test4")
.withJobSerializer(new JavaJobSerializer())
.withConsumerThreads(1)
.build();
assertTrue(!PersistentResult.getInstance().isRan());
jobManager.setEncryptionKeys(keys);
assertTrue(PersistentResult.getInstance().isRan());
}
public void testGroupIdExecution() throws InterruptedException {
final Object lock = new Object();
Runnable waitRunnable = new Runnable() {
@Override
public void run() {
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}
};
TestJob testJobOne = new TestJob(JobParameters.newBuilder().withGroupId("foo").create(), waitRunnable);
TestJob testJobTwo = new TestJob(JobParameters.newBuilder().withGroupId("foo").create());
TestJob testJobThree = new TestJob(JobParameters.newBuilder().withGroupId("bar").create());
JobManager jobManager = JobManager.newBuilder(getContext())
.withName("transient-test")
.withConsumerThreads(3)
.build();
jobManager.add(testJobOne);
jobManager.add(testJobTwo);
jobManager.add(testJobThree);
assertTrue(testJobOne.isAdded());
assertTrue(testJobTwo.isAdded());
assertTrue(testJobThree.isAdded());
assertTrue(testJobOne.isRan());
assertTrue(!testJobTwo.isRan());
assertTrue(testJobThree.isRan());
synchronized (lock) {
lock.notifyAll();
}
assertTrue(testJobTwo.isRan());
}
}

View File

@@ -1,39 +0,0 @@
package org.whispersystems.jobqueue.jobs;
import org.whispersystems.jobqueue.EncryptionKeys;
import org.whispersystems.jobqueue.Job;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.Requirement;
import org.whispersystems.jobqueue.util.PersistentResult;
public class PersistentTestJob extends Job {
public PersistentTestJob(Requirement requirement) {
super(JobParameters.newBuilder().withRequirement(requirement).withPersistence().create());
}
public PersistentTestJob(Requirement requirement, EncryptionKeys keys) {
super(JobParameters.newBuilder().withRequirement(requirement).withPersistence().withEncryption(keys).create());
}
@Override
public void onAdded() {
PersistentResult.getInstance().onAdded();
}
@Override
public void onRun() throws Exception {
PersistentResult.getInstance().onRun();
}
@Override
public void onCanceled() {
PersistentResult.getInstance().onCanceled();
}
@Override
public boolean onShouldRetry(Exception exception) {
return false;
}
}

View File

@@ -1,51 +0,0 @@
package org.whispersystems.jobqueue.jobs;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.Requirement;
import org.whispersystems.jobqueue.util.RunnableThrowable;
import java.io.IOException;
public class RequirementDeferringTestJob extends TestJob {
private final Object FINISHED_LOCK = new Object();
private boolean finished = false;
private RunnableThrowable runnable;
public RequirementDeferringTestJob(Requirement requirement, int retryCount, RunnableThrowable runnable) {
super(JobParameters.newBuilder().withRequirement(requirement).withRetryCount(retryCount).create());
this.runnable = runnable;
}
@Override
public void onRun() throws Exception {
synchronized (RAN_LOCK) {
this.ran = true;
}
if (runnable != null)
runnable.run();
synchronized (FINISHED_LOCK) {
this.finished = true;
}
}
@Override
public boolean onShouldRetry(Exception exception) {
if (exception instanceof Exception) {
return true;
}
return false;
}
public boolean isFinished() throws InterruptedException {
synchronized (FINISHED_LOCK) {
if (!finished) FINISHED_LOCK.wait(1000);
return finished;
}
}
}

View File

@@ -1,12 +0,0 @@
package org.whispersystems.jobqueue.jobs;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.Requirement;
public class RequirementTestJob extends TestJob {
public RequirementTestJob(Requirement requirement) {
super(JobParameters.newBuilder().withRequirement(requirement).create());
}
}

View File

@@ -1,81 +0,0 @@
package org.whispersystems.jobqueue.jobs;
import org.whispersystems.jobqueue.Job;
import org.whispersystems.jobqueue.JobParameters;
public class TestJob extends Job {
private final Object ADDED_LOCK = new Object();
protected final Object RAN_LOCK = new Object();
private final Object CANCELED_LOCK = new Object();
private boolean added = false;
protected boolean ran = false;
private boolean canceled = false;
private Runnable runnable;
public TestJob() {
this(JobParameters.newBuilder().create());
}
public TestJob(JobParameters parameters) {
super(parameters);
}
public TestJob(JobParameters parameters, Runnable runnable) {
super(parameters);
this.runnable = runnable;
}
@Override
public void onAdded() {
synchronized (ADDED_LOCK) {
this.added = true;
this.ADDED_LOCK.notifyAll();
}
}
@Override
public void onRun() throws Exception {
synchronized (RAN_LOCK) {
this.ran = true;
}
if (runnable != null)
runnable.run();
}
@Override
public void onCanceled() {
synchronized (CANCELED_LOCK) {
this.canceled = true;
}
}
@Override
public boolean onShouldRetry(Exception exception) {
return false;
}
public boolean isAdded() throws InterruptedException {
synchronized (ADDED_LOCK) {
if (!added) ADDED_LOCK.wait(1000);
return added;
}
}
public boolean isRan() throws InterruptedException {
synchronized (RAN_LOCK) {
if (!ran) RAN_LOCK.wait(1000);
return ran;
}
}
public boolean isCanceled() throws InterruptedException {
synchronized (CANCELED_LOCK) {
if (!canceled) CANCELED_LOCK.wait(1000);
return canceled;
}
}
}

View File

@@ -1,23 +0,0 @@
package org.whispersystems.jobqueue.util;
import org.whispersystems.jobqueue.requirements.Requirement;
import java.util.concurrent.atomic.AtomicBoolean;
public class MockRequirement implements Requirement {
private AtomicBoolean present;
public MockRequirement(boolean present) {
this.present = new AtomicBoolean(present);
}
public void setPresent(boolean present) {
this.present.set(present);
}
@Override
public boolean isPresent() {
return present.get();
}
}

View File

@@ -1,23 +0,0 @@
package org.whispersystems.jobqueue.util;
import org.whispersystems.jobqueue.requirements.RequirementListener;
import org.whispersystems.jobqueue.requirements.RequirementProvider;
public class MockRequirementProvider implements RequirementProvider {
private RequirementListener listener;
public void fireChange() {
listener.onRequirementStatusChanged();
}
@Override
public void setListener(RequirementListener listener) {
this.listener = listener;
}
@Override
public String getName() {
return "mock-requirement-provider";
}
}

View File

@@ -1,10 +0,0 @@
package org.whispersystems.jobqueue.util;
import org.whispersystems.jobqueue.requirements.Requirement;
public class PersistentMockRequirement implements Requirement {
@Override
public boolean isPresent() {
return PersistentRequirement.getInstance().isPresent();
}
}

View File

@@ -1,22 +0,0 @@
package org.whispersystems.jobqueue.util;
import java.util.concurrent.atomic.AtomicBoolean;
public class PersistentRequirement {
private AtomicBoolean present = new AtomicBoolean(false);
private static final PersistentRequirement instance = new PersistentRequirement();
public static PersistentRequirement getInstance() {
return instance;
}
public void setPresent(boolean present) {
this.present.set(present);
}
public boolean isPresent() {
return present.get();
}
}

View File

@@ -1,73 +0,0 @@
package org.whispersystems.jobqueue.util;
public class PersistentResult {
private final Object ADDED_LOCK = new Object();
private final Object RAN_LOCK = new Object();
private final Object CANCELED_LOCK = new Object();
private boolean added = false;
private boolean ran = false;
private boolean canceled = false;
private static final PersistentResult instance = new PersistentResult();
public static PersistentResult getInstance() {
return instance;
}
public void onAdded() {
synchronized (ADDED_LOCK) {
this.added = true;
this.ADDED_LOCK.notifyAll();
}
}
public void onRun() throws Exception {
synchronized (RAN_LOCK) {
this.ran = true;
}
}
public void onCanceled() {
synchronized (CANCELED_LOCK) {
this.canceled = true;
}
}
public boolean isAdded() throws InterruptedException {
synchronized (ADDED_LOCK) {
if (!added) ADDED_LOCK.wait(1000);
return added;
}
}
public boolean isRan() throws InterruptedException {
synchronized (RAN_LOCK) {
if (!ran) RAN_LOCK.wait(1000);
return ran;
}
}
public boolean isCanceled() throws InterruptedException {
synchronized (CANCELED_LOCK) {
if (!canceled) CANCELED_LOCK.wait(1000);
return canceled;
}
}
public void reset() {
synchronized (ADDED_LOCK) {
this.added = false;
}
synchronized (RAN_LOCK) {
this.ran = false;
}
synchronized (CANCELED_LOCK) {
this.canceled = false;
}
}
}

View File

@@ -1,8 +0,0 @@
package org.whispersystems.jobqueue.util;
public interface RunnableThrowable {
public void run() throws Exception;
public void shouldThrow(Boolean value);
}

View File

@@ -1,6 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.whispersystems.jobqueue">
<application />
</manifest>

View File

@@ -1,30 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue;
public class EncryptionKeys {
private transient final byte[] encoded;
public EncryptionKeys(byte[] encoded) {
this.encoded = encoded;
}
public byte[] getEncoded() {
return encoded;
}
}

View File

@@ -1,116 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue;
import org.whispersystems.jobqueue.requirements.Requirement;
import java.io.Serializable;
import java.util.List;
/**
* An abstract class representing a unit of work that can be scheduled with
* the JobManager. This should be extended to implement tasks.
*/
public abstract class Job implements Serializable {
private final JobParameters parameters;
private transient long persistentId;
private transient int runIteration;
public Job(JobParameters parameters) {
this.parameters = parameters;
}
public List<Requirement> getRequirements() {
return parameters.getRequirements();
}
public boolean isRequirementsMet() {
for (Requirement requirement : parameters.getRequirements()) {
if (!requirement.isPresent()) return false;
}
return true;
}
public String getGroupId() {
return parameters.getGroupId();
}
public boolean isPersistent() {
return parameters.isPersistent();
}
public EncryptionKeys getEncryptionKeys() {
return parameters.getEncryptionKeys();
}
public void setEncryptionKeys(EncryptionKeys keys) {
parameters.setEncryptionKeys(keys);
}
public int getRetryCount() {
return parameters.getRetryCount();
}
public void setPersistentId(long persistentId) {
this.persistentId = persistentId;
}
public long getPersistentId() {
return persistentId;
}
public int getRunIteration() {
return runIteration;
}
public void setRunIteration(int runIteration) {
this.runIteration = runIteration;
}
/**
* Called after a job has been added to the JobManager queue. If it's a persistent job,
* the state has been persisted to disk before this method is called.
*/
public abstract void onAdded();
/**
* Called to actually execute the job.
* @throws Exception
*/
public abstract void onRun() throws Exception;
/**
* If onRun() throws an exception, this method will be called to determine whether the
* job should be retried.
*
* @param exception The exception onRun() threw.
* @return true if onRun() should be called again, false otherwise.
*/
public abstract boolean onShouldRetry(Exception exception);
/**
* Called if a job fails to run (onShouldRetry returned false, or the number of retries exceeded
* the job's configured retry count.
*/
public abstract void onCanceled();
}

View File

@@ -1,90 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue;
import android.util.Log;
import org.whispersystems.jobqueue.persistence.PersistentStorage;
class JobConsumer extends Thread {
private static final String TAG = JobConsumer.class.getSimpleName();
enum JobResult {
SUCCESS,
FAILURE,
DEFERRED
}
private final JobQueue jobQueue;
private final PersistentStorage persistentStorage;
public JobConsumer(String name, JobQueue jobQueue, PersistentStorage persistentStorage) {
super(name);
this.jobQueue = jobQueue;
this.persistentStorage = persistentStorage;
}
@Override
public void run() {
while (true) {
Job job = jobQueue.getNext();
JobResult result = runJob(job);
if (result == JobResult.DEFERRED) {
jobQueue.push(job);
} else {
if (result == JobResult.FAILURE) {
job.onCanceled();
}
if (job.isPersistent()) {
persistentStorage.remove(job.getPersistentId());
}
}
if (job.getGroupId() != null) {
jobQueue.setGroupIdAvailable(job.getGroupId());
}
}
}
private JobResult runJob(Job job) {
int retryCount = job.getRetryCount();
int runIteration = job.getRunIteration();
for (;runIteration<retryCount;runIteration++) {
try {
job.onRun();
return JobResult.SUCCESS;
} catch (Exception exception) {
Log.w(TAG, exception);
if (exception instanceof RuntimeException) {
throw (RuntimeException)exception;
} else if (!job.onShouldRetry(exception)) {
return JobResult.FAILURE;
} else if (!job.isRequirementsMet()) {
job.setRunIteration(runIteration+1);
return JobResult.DEFERRED;
}
}
}
return JobResult.FAILURE;
}
}

View File

@@ -1,253 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue;
import android.content.Context;
import android.util.Log;
import org.whispersystems.jobqueue.dependencies.DependencyInjector;
import org.whispersystems.jobqueue.persistence.JobSerializer;
import org.whispersystems.jobqueue.persistence.PersistentStorage;
import org.whispersystems.jobqueue.requirements.RequirementListener;
import org.whispersystems.jobqueue.requirements.RequirementProvider;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* A JobManager allows you to enqueue {@link org.whispersystems.jobqueue.Job} tasks
* that are executed once a Job's {@link org.whispersystems.jobqueue.requirements.Requirement}s
* are met.
*/
public class JobManager implements RequirementListener {
private final JobQueue jobQueue = new JobQueue();
private final Executor eventExecutor = Executors.newSingleThreadExecutor();
private final AtomicBoolean hasLoadedEncrypted = new AtomicBoolean(false);
private final PersistentStorage persistentStorage;
private final List<RequirementProvider> requirementProviders;
private final DependencyInjector dependencyInjector;
private JobManager(Context context, String name,
List<RequirementProvider> requirementProviders,
DependencyInjector dependencyInjector,
JobSerializer jobSerializer, int consumers)
{
this.persistentStorage = new PersistentStorage(context, name, jobSerializer, dependencyInjector);
this.requirementProviders = requirementProviders;
this.dependencyInjector = dependencyInjector;
eventExecutor.execute(new LoadTask(null));
if (requirementProviders != null && !requirementProviders.isEmpty()) {
for (RequirementProvider provider : requirementProviders) {
provider.setListener(this);
}
}
for (int i=0;i<consumers;i++) {
new JobConsumer("JobConsumer-" + i, jobQueue, persistentStorage).start();
}
}
/**
* @param context An Android {@link android.content.Context}.
* @return a {@link org.whispersystems.jobqueue.JobManager.Builder} used to construct a JobManager.
*/
public static Builder newBuilder(Context context) {
return new Builder(context);
}
/**
* Returns a {@link org.whispersystems.jobqueue.requirements.RequirementProvider} registered with
* the JobManager by name.
*
* @param name The name of the registered {@link org.whispersystems.jobqueue.requirements.RequirementProvider}
* @return The RequirementProvider, or null if no provider is registered with that name.
*/
public RequirementProvider getRequirementProvider(String name) {
for (RequirementProvider provider : requirementProviders) {
if (provider.getName().equals(name)) {
return provider;
}
}
return null;
}
public void setEncryptionKeys(EncryptionKeys keys) {
if (hasLoadedEncrypted.compareAndSet(false, true)) {
eventExecutor.execute(new LoadTask(keys));
}
}
/**
* Queue a {@link org.whispersystems.jobqueue.Job} to be executed.
*
* @param job The Job to be executed.
*/
public void add(final Job job) {
eventExecutor.execute(new Runnable() {
@Override
public void run() {
try {
if (job.isPersistent()) {
persistentStorage.store(job);
}
if (dependencyInjector != null) {
dependencyInjector.injectDependencies(job);
}
job.onAdded();
jobQueue.add(job);
} catch (IOException e) {
Log.w("JobManager", e);
job.onCanceled();
}
}
});
}
@Override
public void onRequirementStatusChanged() {
eventExecutor.execute(new Runnable() {
@Override
public void run() {
jobQueue.onRequirementStatusChanged();
}
});
}
private class LoadTask implements Runnable {
private final EncryptionKeys keys;
public LoadTask(EncryptionKeys keys) {
this.keys = keys;
}
@Override
public void run() {
List<Job> pendingJobs;
if (keys == null) pendingJobs = persistentStorage.getAllUnencrypted();
else pendingJobs = persistentStorage.getAllEncrypted(keys);
jobQueue.addAll(pendingJobs);
}
}
public static class Builder {
private final Context context;
private String name;
private List<RequirementProvider> requirementProviders;
private DependencyInjector dependencyInjector;
private JobSerializer jobSerializer;
private int consumerThreads;
Builder(Context context) {
this.context = context;
this.consumerThreads = 5;
}
/**
* A name for the {@link org.whispersystems.jobqueue.JobManager}. This is a required parameter,
* and is linked to the durable queue used by persistent jobs.
*
* @param name The name for the JobManager to build.
* @return The builder.
*/
public Builder withName(String name) {
this.name = name;
return this;
}
/**
* The {@link org.whispersystems.jobqueue.requirements.RequirementProvider}s to register with this
* JobManager. Optional. Each {@link org.whispersystems.jobqueue.requirements.Requirement} an
* enqueued Job depends on should have a matching RequirementProvider registered here.
*
* @param requirementProviders The RequirementProviders
* @return The builder.
*/
public Builder withRequirementProviders(RequirementProvider... requirementProviders) {
this.requirementProviders = Arrays.asList(requirementProviders);
return this;
}
/**
* The {@link org.whispersystems.jobqueue.dependencies.DependencyInjector} to use for injecting
* dependencies into {@link Job}s. Optional. Injection occurs just before a Job's onAdded() callback, or
* after deserializing a persistent job.
*
* @param dependencyInjector The injector to use.
* @return The builder.
*/
public Builder withDependencyInjector(DependencyInjector dependencyInjector) {
this.dependencyInjector = dependencyInjector;
return this;
}
/**
* The {@link org.whispersystems.jobqueue.persistence.JobSerializer} to use for persistent Jobs.
* Required if persistent Jobs are used.
*
* @param jobSerializer The serializer to use.
* @return The builder.
*/
public Builder withJobSerializer(JobSerializer jobSerializer) {
this.jobSerializer = jobSerializer;
return this;
}
/**
* Set the number of threads dedicated to consuming Jobs from the queue and executing them.
*
* @param consumerThreads The number of threads.
* @return The builder.
*/
public Builder withConsumerThreads(int consumerThreads) {
this.consumerThreads = consumerThreads;
return this;
}
/**
* @return A constructed JobManager.
*/
public JobManager build() {
if (name == null) {
throw new IllegalArgumentException("You must specify a name!");
}
if (requirementProviders == null) {
requirementProviders = new LinkedList<>();
}
return new JobManager(context, name, requirementProviders,
dependencyInjector, jobSerializer,
consumerThreads);
}
}
}

View File

@@ -1,149 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue;
import org.whispersystems.jobqueue.requirements.Requirement;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
/**
* The set of parameters that describe a {@link org.whispersystems.jobqueue.Job}.
*/
public class JobParameters implements Serializable {
private transient EncryptionKeys encryptionKeys;
private final List<Requirement> requirements;
private final boolean isPersistent;
private final int retryCount;
private final String groupId;
private JobParameters(List<Requirement> requirements,
boolean isPersistent, String groupId,
EncryptionKeys encryptionKeys,
int retryCount)
{
this.requirements = requirements;
this.isPersistent = isPersistent;
this.groupId = groupId;
this.encryptionKeys = encryptionKeys;
this.retryCount = retryCount;
}
public List<Requirement> getRequirements() {
return requirements;
}
public boolean isPersistent() {
return isPersistent;
}
public EncryptionKeys getEncryptionKeys() {
return encryptionKeys;
}
public void setEncryptionKeys(EncryptionKeys encryptionKeys) {
this.encryptionKeys = encryptionKeys;
}
public int getRetryCount() {
return retryCount;
}
/**
* @return a builder used to construct JobParameters.
*/
public static Builder newBuilder() {
return new Builder();
}
public String getGroupId() {
return groupId;
}
public static class Builder {
private List<Requirement> requirements = new LinkedList<>();
private boolean isPersistent = false;
private EncryptionKeys encryptionKeys = null;
private int retryCount = 100;
private String groupId = null;
/**
* Specify a {@link org.whispersystems.jobqueue.requirements.Requirement }that must be met
* before the Job is executed. May be called multiple times to register multiple requirements.
* @param requirement The Requirement that must be met.
* @return the builder.
*/
public Builder withRequirement(Requirement requirement) {
this.requirements.add(requirement);
return this;
}
/**
* Specify that the Job should be durably persisted to disk, so that it remains in the queue
* across application restarts.
* @return The builder.
*/
public Builder withPersistence() {
this.isPersistent = true;
return this;
}
/**
* Specify that the job should use encryption when durably persisted to disk.
* @param encryptionKeys The keys to encrypt the serialized job with before persisting.
* @return the builder.
*/
public Builder withEncryption(EncryptionKeys encryptionKeys) {
this.encryptionKeys = encryptionKeys;
return this;
}
/**
* Specify how many times the job should be retried if execution fails but onShouldRetry() returns
* true.
*
* @param retryCount The number of times the job should be retried.
* @return the builder.
*/
public Builder withRetryCount(int retryCount) {
this.retryCount = retryCount;
return this;
}
/**
* Specify a groupId the job should belong to. Jobs with the same groupId are guaranteed to be
* executed serially.
*
* @param groupId The job's groupId.
* @return the builder.
*/
public Builder withGroupId(String groupId) {
this.groupId = groupId;
return this;
}
/**
* @return the JobParameters instance that describes a Job.
*/
public JobParameters create() {
return new JobParameters(requirements, isPersistent, groupId, encryptionKeys, retryCount);
}
}
}

View File

@@ -1,95 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
class JobQueue {
private final Set<String> activeGroupIds = new HashSet<>();
private final LinkedList<Job> jobQueue = new LinkedList<>();
synchronized void onRequirementStatusChanged() {
notifyAll();
}
synchronized void add(Job job) {
jobQueue.add(job);
notifyAll();
}
synchronized void addAll(List<Job> jobs) {
jobQueue.addAll(jobs);
notifyAll();
}
synchronized void push(Job job) {
jobQueue.push(job);
}
synchronized Job getNext() {
try {
Job nextAvailableJob;
while ((nextAvailableJob = getNextAvailableJob()) == null) {
wait();
}
return nextAvailableJob;
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}
synchronized void setGroupIdAvailable(String groupId) {
if (groupId != null) {
activeGroupIds.remove(groupId);
notifyAll();
}
}
private Job getNextAvailableJob() {
if (jobQueue.isEmpty()) return null;
ListIterator<Job> iterator = jobQueue.listIterator();
while (iterator.hasNext()) {
Job job = iterator.next();
if (job.isRequirementsMet() && isGroupIdAvailable(job.getGroupId())) {
iterator.remove();
setGroupIdUnavailable(job.getGroupId());
return job;
}
}
return null;
}
private boolean isGroupIdAvailable(String groupId) {
return groupId == null || !activeGroupIds.contains(groupId);
}
private void setGroupIdUnavailable(String groupId) {
if (groupId != null) {
activeGroupIds.add(groupId);
}
}
}

View File

@@ -1,27 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.dependencies;
import android.content.Context;
/**
* Any Job or Requirement that depends on {@link android.content.Context} can implement this
* interface to receive a Context after being deserialized.
*/
public interface ContextDependent {
public void setContext(Context context);
}

View File

@@ -1,24 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.dependencies;
/**
* Interface responsible for injecting dependencies into Jobs.
*/
public interface DependencyInjector {
public void injectDependencies(Object object);
}

View File

@@ -1,58 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.persistence;
import android.util.Base64;
import org.whispersystems.jobqueue.EncryptionKeys;
import org.whispersystems.jobqueue.Job;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* An implementation of {@link org.whispersystems.jobqueue.persistence.JobSerializer} that uses
* Java Serialization.
*/
public class JavaJobSerializer implements JobSerializer {
public JavaJobSerializer() {}
@Override
public String serialize(Job job) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(job);
return Base64.encodeToString(baos.toByteArray(), Base64.NO_WRAP);
}
@Override
public Job deserialize(EncryptionKeys keys, boolean encrypted, String serialized) throws IOException {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(serialized, Base64.NO_WRAP));
ObjectInputStream ois = new ObjectInputStream(bais);
return (Job)ois.readObject();
} catch (ClassNotFoundException e) {
throw new IOException(e);
}
}
}

View File

@@ -1,47 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.persistence;
import org.whispersystems.jobqueue.EncryptionKeys;
import org.whispersystems.jobqueue.Job;
import java.io.IOException;
/**
* A JobSerializer is responsible for serializing and deserializing persistent jobs.
*/
public interface JobSerializer {
/**
* Serialize a job object into a string.
* @param job The Job to serialize.
* @return The serialized Job.
* @throws IOException if serialization fails.
*/
public String serialize(Job job) throws IOException;
/**
* Deserialize a String into a Job.
* @param keys Optional encryption keys that could have been used.
* @param encrypted True if the job was encrypted using the encryption keys.
* @param serialized The serialized Job.
* @return The deserialized Job.
* @throws IOException If the Job deserialization fails.
*/
public Job deserialize(EncryptionKeys keys, boolean encrypted, String serialized) throws IOException;
}

View File

@@ -1,152 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.persistence;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import org.whispersystems.jobqueue.EncryptionKeys;
import org.whispersystems.jobqueue.Job;
import org.whispersystems.jobqueue.dependencies.ContextDependent;
import org.whispersystems.jobqueue.dependencies.DependencyInjector;
import org.whispersystems.jobqueue.requirements.Requirement;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class PersistentStorage {
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "queue";
private static final String ID = "_id";
private static final String ITEM = "item";
private static final String ENCRYPTED = "encrypted";
private static final String DATABASE_CREATE = String.format("CREATE TABLE %s (%s INTEGER PRIMARY KEY, %s TEXT NOT NULL, %s INTEGER DEFAULT 0);",
TABLE_NAME, ID, ITEM, ENCRYPTED);
private final Context context;
private final DatabaseHelper databaseHelper;
private final JobSerializer jobSerializer;
private final DependencyInjector dependencyInjector;
public PersistentStorage(Context context, String name,
JobSerializer serializer,
DependencyInjector dependencyInjector)
{
this.databaseHelper = new DatabaseHelper(context, "_jobqueue-" + name);
this.context = context;
this.jobSerializer = serializer;
this.dependencyInjector = dependencyInjector;
}
public void store(Job job) throws IOException {
ContentValues contentValues = new ContentValues();
contentValues.put(ITEM, jobSerializer.serialize(job));
contentValues.put(ENCRYPTED, job.getEncryptionKeys() != null);
long id = databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
job.setPersistentId(id);
}
public List<Job> getAllUnencrypted() {
return getJobs(null, ENCRYPTED + " = 0");
}
public List<Job> getAllEncrypted(EncryptionKeys keys) {
return getJobs(keys, ENCRYPTED + " = 1");
}
private List<Job> getJobs(EncryptionKeys keys, String where) {
List<Job> results = new LinkedList<>();
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = null;
try {
cursor = database.query(TABLE_NAME, null, where, null, null, null, ID + " ASC", null);
while (cursor.moveToNext()) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
String item = cursor.getString(cursor.getColumnIndexOrThrow(ITEM));
boolean encrypted = cursor.getInt(cursor.getColumnIndexOrThrow(ENCRYPTED)) == 1;
try{
Job job = jobSerializer.deserialize(keys, encrypted, item);
job.setPersistentId(id);
job.setEncryptionKeys(keys);
injectDependencies(job);
results.add(job);
} catch (IOException e) {
Log.w("PersistentStore", e);
remove(id);
}
}
} finally {
if (cursor != null)
cursor.close();
}
return results;
}
public void remove(long id) {
databaseHelper.getWritableDatabase()
.delete(TABLE_NAME, ID + " = ?", new String[] {String.valueOf(id)});
}
private void injectDependencies(Job job) {
if (job instanceof ContextDependent) {
((ContextDependent)job).setContext(context);
}
for (Requirement requirement : job.getRequirements()) {
if (requirement instanceof ContextDependent) {
((ContextDependent)requirement).setContext(context);
}
}
if (dependencyInjector != null) {
dependencyInjector.injectDependencies(job);
}
}
private static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context, String name) {
super(context, name, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}

View File

@@ -1,50 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.requirements;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org.whispersystems.jobqueue.dependencies.ContextDependent;
/**
* A requirement that is satisfied when a network connection is present.
*/
public class NetworkRequirement implements Requirement, ContextDependent {
private transient Context context;
public NetworkRequirement(Context context) {
this.context = context;
}
public NetworkRequirement() {}
@Override
public boolean isPresent() {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
@Override
public void setContext(Context context) {
this.context = context;
}
}

View File

@@ -1,59 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.requirements;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class NetworkRequirementProvider implements RequirementProvider {
private RequirementListener listener;
private final NetworkRequirement requirement;
public NetworkRequirementProvider(Context context) {
this.requirement = new NetworkRequirement(context);
context.getApplicationContext().registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (listener == null) {
return;
}
if (requirement.isPresent()) {
listener.onRequirementStatusChanged();
}
}
}, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
@Override
public String getName() {
return "network";
}
@Override
public void setListener(RequirementListener listener) {
this.listener = listener;
}
}

View File

@@ -1,29 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.requirements;
import java.io.Serializable;
/**
* A Requirement that must be satisfied before a Job can run.
*/
public interface Requirement extends Serializable {
/**
* @return true if the requirement is satisfied, false otherwise.
*/
public boolean isPresent();
}

View File

@@ -1,21 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.requirements;
public interface RequirementListener {
public void onRequirementStatusChanged();
}

View File

@@ -1,37 +0,0 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.jobqueue.requirements;
/**
* Notifies listeners when a {@link org.whispersystems.jobqueue.requirements.Requirement}'s
* state is likely to have changed.
*/
public interface RequirementProvider {
/**
* @return The name of the provider.
*/
public String getName();
/**
* The {@link org.whispersystems.jobqueue.requirements.RequirementListener} to call when
* a {@link org.whispersystems.jobqueue.requirements.Requirement}'s status is likely to
* have changed.
*
* @param listener The listener to call.
*/
public void setListener(RequirementListener listener);
}

View File

@@ -1,2 +0,0 @@
<resources>
</resources>

View File

@@ -1,2 +0,0 @@
/build
/obj

View File

@@ -1,85 +0,0 @@
# Overview
This is a ratcheting forward secrecy protocol that works in synchronous and asynchronous messaging
environments. The protocol overview is available [here](https://github.com/trevp/axolotl/wiki),
and the details of the wire format are available [here](https://github.com/WhisperSystems/TextSecure/wiki/ProtocolV2).
## PreKeys
This protocol uses a concept called 'PreKeys'. A PreKey is an ECPublicKey and an associated unique
ID which are stored together by a server. PreKeys can also be signed.
At install time, clients generate a single signed PreKey, as well as a large list of unsigned
PreKeys, and transmit all of them to the server.
## Sessions
The axolotl protocol is session-oriented. Clients establish a "session," which is then used for
all subsequent encrypt/decrypt operations. There is no need to ever tear down a session once one
has been established.
Sessions are established in one of three ways:
1. PreKeyBundles. A client that wishes to send a message to a recipient can establish a session by
retrieving a PreKeyBundle for that recipient from the server.
1. PreKeyWhisperMessages. A client can receive a PreKeyWhisperMessage from a recipient and use it
to establish a session.
1. KeyExchangeMessages. Two clients can exchange KeyExchange messages to establish a session.
## State
An established session encapsulates a lot of state between two clients. That state is maintained
in durable records which need to be kept for the life of the session.
State is kept in the following places:
1. Identity State. Clients will need to maintain the state of their own identity key pair, as well
as identity keys received from other clients.
1. PreKey State. Clients will need to maintain the state of their generated PreKeys.
1. Signed PreKey States. Clients will need to maintain the state of their signed PreKeys.
1. Session State. Clients will need to maintain the state of the sessions they have established.
# Using libaxolotl
## Install time
At install time, a libaxolotl client needs to generate its identity keys, registration id, and
prekeys.
IdentityKeyPair identityKeyPair = KeyHelper.generateIdentityKeyPair();
int registrationId = KeyHelper.generateRegistrationId();
List<PreKeyRecord> preKeys = KeyHelper.generatePreKeys(startId, 100);
PreKeyRecord lastResortKey = KeyHelper.generateLastResortKey();
SignedPreKeyRecord signedPreKey = KeyHelper.generateSignedPreKey(identityKeyPair, 5);
// Store identityKeyPair somewhere durable and safe.
// Store registrationId somewhere durable and safe.
// Store preKeys in PreKeyStore.
// Store signed prekey in SignedPreKeyStore.
## Building a session
A libaxolotl client needs to implement four interfaces: IdentityKeyStore, PreKeyStore,
SignedPreKeyStore, and SessionStore. These will manage loading and storing of identity,
prekeys, signed prekeys, and session state.
Once those are implemented, building a session is fairly straightforward:
SessionStore sessionStore = new MySessionStore();
PreKeyStore preKeyStore = new MyPreKeyStore();
SignedPreKeyStore signedPreKeyStore = new MySignedPreKeyStore();
IdentityKeyStore identityStore = new MyIdentityKeyStore();
// Instantiate a SessionBuilder for a remote recipientId + deviceId tuple.
SessionBuilder sessionBuilder = new SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore,
identityStore, recipientId, deviceId);
// Build a session with a PreKey retrieved from the server.
sessionBuilder.process(retrievedPreKey);
SessionCipher sessionCipher = new SessionCipher(sessionStore, recipientId, deviceId);
CiphertextMessage message = sessionCipher.encrypt("Hello world!".getBytes("UTF-8"));
deliver(message.serialize());

View File

@@ -1,44 +0,0 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.14.2'
}
}
apply plugin: 'com.android.library'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.protobuf:protobuf-java:2.5.0'
}
android {
compileSdkVersion 21
buildToolsVersion '21.1.1'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
android {
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
}
tasks.whenTaskAdded { task ->
if (task.name.equals("lint")) {
task.enabled = false
}
}

View File

@@ -1,27 +0,0 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcurve25519-donna
LOCAL_SRC_FILES := curve25519-donna.c
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcurve25519-ref10
LOCAL_SRC_FILES := $(wildcard ed25519/*.c) $(wildcard ed25519/additions/*.c) $(wildcard ed25519/nacl_sha512/*.c)
LOCAL_C_INCLUDES := ed25519/nacl_includes ed25519/additions ed25519/sha512 ed25519
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcurve25519
LOCAL_SRC_FILES := curve25519-jni.c
LOCAL_C_INCLUDES := ed25519/additions
LOCAL_STATIC_LIBRARIES := libcurve25519-donna libcurve25519-ref10
include $(BUILD_SHARED_LIBRARY)

View File

@@ -1 +0,0 @@
APP_ABI := armeabi armeabi-v7a x86 mips

View File

@@ -1,870 +0,0 @@
/* Copyright 2008, Google Inc.
* 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 Google Inc. 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
* OWNER 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.
*
* curve25519-donna: Curve25519 elliptic curve, public key function
*
* http://code.google.com/p/curve25519-donna/
*
* Adam Langley <agl@imperialviolet.org>
*
* Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
*
* More information about curve25519 can be found here
* http://cr.yp.to/ecdh.html
*
* djb's sample implementation of curve25519 is written in a special assembly
* language called qhasm and uses the floating point registers.
*
* This is, almost, a clean room reimplementation from the curve25519 paper. It
* uses many of the tricks described therein. Only the crecip function is taken
* from the sample implementation. */
#include <string.h>
#include <stdint.h>
#ifdef _MSC_VER
#define inline __inline
#endif
typedef uint8_t u8;
typedef int32_t s32;
typedef int64_t limb;
/* Field element representation:
*
* Field elements are written as an array of signed, 64-bit limbs, least
* significant first. The value of the field element is:
* x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ...
*
* i.e. the limbs are 26, 25, 26, 25, ... bits wide. */
/* Sum two numbers: output += in */
static void fsum(limb *output, const limb *in) {
unsigned i;
for (i = 0; i < 10; i += 2) {
output[0+i] = output[0+i] + in[0+i];
output[1+i] = output[1+i] + in[1+i];
}
}
/* Find the difference of two numbers: output = in - output
* (note the order of the arguments!). */
static void fdifference(limb *output, const limb *in) {
unsigned i;
for (i = 0; i < 10; ++i) {
output[i] = in[i] - output[i];
}
}
/* Multiply a number by a scalar: output = in * scalar */
static void fscalar_product(limb *output, const limb *in, const limb scalar) {
unsigned i;
for (i = 0; i < 10; ++i) {
output[i] = in[i] * scalar;
}
}
/* Multiply two numbers: output = in2 * in
*
* output must be distinct to both inputs. The inputs are reduced coefficient
* form, the output is not.
*
* output[x] <= 14 * the largest product of the input limbs. */
static void fproduct(limb *output, const limb *in2, const limb *in) {
output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]);
output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) +
((limb) ((s32) in2[1])) * ((s32) in[0]);
output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[2]) +
((limb) ((s32) in2[2])) * ((s32) in[0]);
output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) +
((limb) ((s32) in2[2])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[3]) +
((limb) ((s32) in2[3])) * ((s32) in[0]);
output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) +
2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) +
((limb) ((s32) in2[3])) * ((s32) in[1])) +
((limb) ((s32) in2[0])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[0]);
output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) +
((limb) ((s32) in2[3])) * ((s32) in[2]) +
((limb) ((s32) in2[1])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[0]);
output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) +
((limb) ((s32) in2[1])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[1])) +
((limb) ((s32) in2[2])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[2]) +
((limb) ((s32) in2[0])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[0]);
output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[2]) +
((limb) ((s32) in2[1])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[0]);
output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) +
2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[3]) +
((limb) ((s32) in2[1])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[1])) +
((limb) ((s32) in2[2])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[2]) +
((limb) ((s32) in2[0])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[0]);
output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[4]) +
((limb) ((s32) in2[3])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[2]) +
((limb) ((s32) in2[1])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[0]);
output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) +
((limb) ((s32) in2[3])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[3]) +
((limb) ((s32) in2[1])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[1])) +
((limb) ((s32) in2[4])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[4]) +
((limb) ((s32) in2[2])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[2]);
output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[5]) +
((limb) ((s32) in2[4])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[4]) +
((limb) ((s32) in2[3])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[2]);
output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) +
2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[5]) +
((limb) ((s32) in2[3])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[3])) +
((limb) ((s32) in2[4])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[4]);
output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[6]) +
((limb) ((s32) in2[5])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[5]) +
((limb) ((s32) in2[4])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[4]);
output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) +
((limb) ((s32) in2[5])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[5])) +
((limb) ((s32) in2[6])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[6]);
output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[7]) +
((limb) ((s32) in2[6])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[6]);
output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) +
2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[7]));
output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[8]);
output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]);
}
/* Reduce a long form to a short form by taking the input mod 2^255 - 19.
*
* On entry: |output[i]| < 14*2^54
* On exit: |output[0..8]| < 280*2^54 */
static void freduce_degree(limb *output) {
/* Each of these shifts and adds ends up multiplying the value by 19.
*
* For output[0..8], the absolute entry value is < 14*2^54 and we add, at
* most, 19*14*2^54 thus, on exit, |output[0..8]| < 280*2^54. */
output[8] += output[18] << 4;
output[8] += output[18] << 1;
output[8] += output[18];
output[7] += output[17] << 4;
output[7] += output[17] << 1;
output[7] += output[17];
output[6] += output[16] << 4;
output[6] += output[16] << 1;
output[6] += output[16];
output[5] += output[15] << 4;
output[5] += output[15] << 1;
output[5] += output[15];
output[4] += output[14] << 4;
output[4] += output[14] << 1;
output[4] += output[14];
output[3] += output[13] << 4;
output[3] += output[13] << 1;
output[3] += output[13];
output[2] += output[12] << 4;
output[2] += output[12] << 1;
output[2] += output[12];
output[1] += output[11] << 4;
output[1] += output[11] << 1;
output[1] += output[11];
output[0] += output[10] << 4;
output[0] += output[10] << 1;
output[0] += output[10];
}
#if (-1 & 3) != 3
#error "This code only works on a two's complement system"
#endif
/* return v / 2^26, using only shifts and adds.
*
* On entry: v can take any value. */
static inline limb
div_by_2_26(const limb v)
{
/* High word of v; no shift needed. */
const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
/* Set to all 1s if v was negative; else set to 0s. */
const int32_t sign = ((int32_t) highword) >> 31;
/* Set to 0x3ffffff if v was negative; else set to 0. */
const int32_t roundoff = ((uint32_t) sign) >> 6;
/* Should return v / (1<<26) */
return (v + roundoff) >> 26;
}
/* return v / (2^25), using only shifts and adds.
*
* On entry: v can take any value. */
static inline limb
div_by_2_25(const limb v)
{
/* High word of v; no shift needed*/
const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
/* Set to all 1s if v was negative; else set to 0s. */
const int32_t sign = ((int32_t) highword) >> 31;
/* Set to 0x1ffffff if v was negative; else set to 0. */
const int32_t roundoff = ((uint32_t) sign) >> 7;
/* Should return v / (1<<25) */
return (v + roundoff) >> 25;
}
/* return v / (2^25), using only shifts and adds.
*
* On entry: v can take any value. */
static inline s32
div_s32_by_2_25(const s32 v)
{
const s32 roundoff = ((uint32_t)(v >> 31)) >> 7;
return (v + roundoff) >> 25;
}
/* Reduce all coefficients of the short form input so that |x| < 2^26.
*
* On entry: |output[i]| < 280*2^54 */
static void freduce_coefficients(limb *output) {
unsigned i;
output[10] = 0;
for (i = 0; i < 10; i += 2) {
limb over = div_by_2_26(output[i]);
/* The entry condition (that |output[i]| < 280*2^54) means that over is, at
* most, 280*2^28 in the first iteration of this loop. This is added to the
* next limb and we can approximate the resulting bound of that limb by
* 281*2^54. */
output[i] -= over << 26;
output[i+1] += over;
/* For the first iteration, |output[i+1]| < 281*2^54, thus |over| <
* 281*2^29. When this is added to the next limb, the resulting bound can
* be approximated as 281*2^54.
*
* For subsequent iterations of the loop, 281*2^54 remains a conservative
* bound and no overflow occurs. */
over = div_by_2_25(output[i+1]);
output[i+1] -= over << 25;
output[i+2] += over;
}
/* Now |output[10]| < 281*2^29 and all other coefficients are reduced. */
output[0] += output[10] << 4;
output[0] += output[10] << 1;
output[0] += output[10];
output[10] = 0;
/* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19*281*2^29
* So |over| will be no more than 2^16. */
{
limb over = div_by_2_26(output[0]);
output[0] -= over << 26;
output[1] += over;
}
/* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 2^16 < 2^26. The
* bound on |output[1]| is sufficient to meet our needs. */
}
/* A helpful wrapper around fproduct: output = in * in2.
*
* On entry: |in[i]| < 2^27 and |in2[i]| < 2^27.
*
* output must be distinct to both inputs. The output is reduced degree
* (indeed, one need only provide storage for 10 limbs) and |output[i]| < 2^26. */
static void
fmul(limb *output, const limb *in, const limb *in2) {
limb t[19];
fproduct(t, in, in2);
/* |t[i]| < 14*2^54 */
freduce_degree(t);
freduce_coefficients(t);
/* |t[i]| < 2^26 */
memcpy(output, t, sizeof(limb) * 10);
}
/* Square a number: output = in**2
*
* output must be distinct from the input. The inputs are reduced coefficient
* form, the output is not.
*
* output[x] <= 14 * the largest product of the input limbs. */
static void fsquare_inner(limb *output, const limb *in) {
output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]);
output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]);
output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) +
((limb) ((s32) in[0])) * ((s32) in[2]));
output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) +
((limb) ((s32) in[0])) * ((s32) in[3]));
output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) +
4 * ((limb) ((s32) in[1])) * ((s32) in[3]) +
2 * ((limb) ((s32) in[0])) * ((s32) in[4]);
output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) +
((limb) ((s32) in[1])) * ((s32) in[4]) +
((limb) ((s32) in[0])) * ((s32) in[5]));
output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) +
((limb) ((s32) in[2])) * ((s32) in[4]) +
((limb) ((s32) in[0])) * ((s32) in[6]) +
2 * ((limb) ((s32) in[1])) * ((s32) in[5]));
output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) +
((limb) ((s32) in[2])) * ((s32) in[5]) +
((limb) ((s32) in[1])) * ((s32) in[6]) +
((limb) ((s32) in[0])) * ((s32) in[7]));
output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) +
2 * (((limb) ((s32) in[2])) * ((s32) in[6]) +
((limb) ((s32) in[0])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[1])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[5])));
output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) +
((limb) ((s32) in[3])) * ((s32) in[6]) +
((limb) ((s32) in[2])) * ((s32) in[7]) +
((limb) ((s32) in[1])) * ((s32) in[8]) +
((limb) ((s32) in[0])) * ((s32) in[9]));
output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) +
((limb) ((s32) in[4])) * ((s32) in[6]) +
((limb) ((s32) in[2])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[3])) * ((s32) in[7]) +
((limb) ((s32) in[1])) * ((s32) in[9])));
output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) +
((limb) ((s32) in[4])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[8]) +
((limb) ((s32) in[2])) * ((s32) in[9]));
output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) +
2 * (((limb) ((s32) in[4])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[5])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[9])));
output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) +
((limb) ((s32) in[5])) * ((s32) in[8]) +
((limb) ((s32) in[4])) * ((s32) in[9]));
output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) +
((limb) ((s32) in[6])) * ((s32) in[8]) +
2 * ((limb) ((s32) in[5])) * ((s32) in[9]));
output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) +
((limb) ((s32) in[6])) * ((s32) in[9]));
output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) +
4 * ((limb) ((s32) in[7])) * ((s32) in[9]);
output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]);
output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]);
}
/* fsquare sets output = in^2.
*
* On entry: The |in| argument is in reduced coefficients form and |in[i]| <
* 2^27.
*
* On exit: The |output| argument is in reduced coefficients form (indeed, one
* need only provide storage for 10 limbs) and |out[i]| < 2^26. */
static void
fsquare(limb *output, const limb *in) {
limb t[19];
fsquare_inner(t, in);
/* |t[i]| < 14*2^54 because the largest product of two limbs will be <
* 2^(27+27) and fsquare_inner adds together, at most, 14 of those
* products. */
freduce_degree(t);
freduce_coefficients(t);
/* |t[i]| < 2^26 */
memcpy(output, t, sizeof(limb) * 10);
}
/* Take a little-endian, 32-byte number and expand it into polynomial form */
static void
fexpand(limb *output, const u8 *input) {
#define F(n,start,shift,mask) \
output[n] = ((((limb) input[start + 0]) | \
((limb) input[start + 1]) << 8 | \
((limb) input[start + 2]) << 16 | \
((limb) input[start + 3]) << 24) >> shift) & mask;
F(0, 0, 0, 0x3ffffff);
F(1, 3, 2, 0x1ffffff);
F(2, 6, 3, 0x3ffffff);
F(3, 9, 5, 0x1ffffff);
F(4, 12, 6, 0x3ffffff);
F(5, 16, 0, 0x1ffffff);
F(6, 19, 1, 0x3ffffff);
F(7, 22, 3, 0x1ffffff);
F(8, 25, 4, 0x3ffffff);
F(9, 28, 6, 0x1ffffff);
#undef F
}
#if (-32 >> 1) != -16
#error "This code only works when >> does sign-extension on negative numbers"
#endif
/* s32_eq returns 0xffffffff iff a == b and zero otherwise. */
static s32 s32_eq(s32 a, s32 b) {
a = ~(a ^ b);
a &= a << 16;
a &= a << 8;
a &= a << 4;
a &= a << 2;
a &= a << 1;
return a >> 31;
}
/* s32_gte returns 0xffffffff if a >= b and zero otherwise, where a and b are
* both non-negative. */
static s32 s32_gte(s32 a, s32 b) {
a -= b;
/* a >= 0 iff a >= b. */
return ~(a >> 31);
}
/* Take a fully reduced polynomial form number and contract it into a
* little-endian, 32-byte array.
*
* On entry: |input_limbs[i]| < 2^26 */
static void
fcontract(u8 *output, limb *input_limbs) {
int i;
int j;
s32 input[10];
s32 mask;
/* |input_limbs[i]| < 2^26, so it's valid to convert to an s32. */
for (i = 0; i < 10; i++) {
input[i] = input_limbs[i];
}
for (j = 0; j < 2; ++j) {
for (i = 0; i < 9; ++i) {
if ((i & 1) == 1) {
/* This calculation is a time-invariant way to make input[i]
* non-negative by borrowing from the next-larger limb. */
const s32 mask = input[i] >> 31;
const s32 carry = -((input[i] & mask) >> 25);
input[i] = input[i] + (carry << 25);
input[i+1] = input[i+1] - carry;
} else {
const s32 mask = input[i] >> 31;
const s32 carry = -((input[i] & mask) >> 26);
input[i] = input[i] + (carry << 26);
input[i+1] = input[i+1] - carry;
}
}
/* There's no greater limb for input[9] to borrow from, but we can multiply
* by 19 and borrow from input[0], which is valid mod 2^255-19. */
{
const s32 mask = input[9] >> 31;
const s32 carry = -((input[9] & mask) >> 25);
input[9] = input[9] + (carry << 25);
input[0] = input[0] - (carry * 19);
}
/* After the first iteration, input[1..9] are non-negative and fit within
* 25 or 26 bits, depending on position. However, input[0] may be
* negative. */
}
/* The first borrow-propagation pass above ended with every limb
except (possibly) input[0] non-negative.
If input[0] was negative after the first pass, then it was because of a
carry from input[9]. On entry, input[9] < 2^26 so the carry was, at most,
one, since (2**26-1) >> 25 = 1. Thus input[0] >= -19.
In the second pass, each limb is decreased by at most one. Thus the second
borrow-propagation pass could only have wrapped around to decrease
input[0] again if the first pass left input[0] negative *and* input[1]
through input[9] were all zero. In that case, input[1] is now 2^25 - 1,
and this last borrow-propagation step will leave input[1] non-negative. */
{
const s32 mask = input[0] >> 31;
const s32 carry = -((input[0] & mask) >> 26);
input[0] = input[0] + (carry << 26);
input[1] = input[1] - carry;
}
/* All input[i] are now non-negative. However, there might be values between
* 2^25 and 2^26 in a limb which is, nominally, 25 bits wide. */
for (j = 0; j < 2; j++) {
for (i = 0; i < 9; i++) {
if ((i & 1) == 1) {
const s32 carry = input[i] >> 25;
input[i] &= 0x1ffffff;
input[i+1] += carry;
} else {
const s32 carry = input[i] >> 26;
input[i] &= 0x3ffffff;
input[i+1] += carry;
}
}
{
const s32 carry = input[9] >> 25;
input[9] &= 0x1ffffff;
input[0] += 19*carry;
}
}
/* If the first carry-chain pass, just above, ended up with a carry from
* input[9], and that caused input[0] to be out-of-bounds, then input[0] was
* < 2^26 + 2*19, because the carry was, at most, two.
*
* If the second pass carried from input[9] again then input[0] is < 2*19 and
* the input[9] -> input[0] carry didn't push input[0] out of bounds. */
/* It still remains the case that input might be between 2^255-19 and 2^255.
* In this case, input[1..9] must take their maximum value and input[0] must
* be >= (2^255-19) & 0x3ffffff, which is 0x3ffffed. */
mask = s32_gte(input[0], 0x3ffffed);
for (i = 1; i < 10; i++) {
if ((i & 1) == 1) {
mask &= s32_eq(input[i], 0x1ffffff);
} else {
mask &= s32_eq(input[i], 0x3ffffff);
}
}
/* mask is either 0xffffffff (if input >= 2^255-19) and zero otherwise. Thus
* this conditionally subtracts 2^255-19. */
input[0] -= mask & 0x3ffffed;
for (i = 1; i < 10; i++) {
if ((i & 1) == 1) {
input[i] -= mask & 0x1ffffff;
} else {
input[i] -= mask & 0x3ffffff;
}
}
input[1] <<= 2;
input[2] <<= 3;
input[3] <<= 5;
input[4] <<= 6;
input[6] <<= 1;
input[7] <<= 3;
input[8] <<= 4;
input[9] <<= 6;
#define F(i, s) \
output[s+0] |= input[i] & 0xff; \
output[s+1] = (input[i] >> 8) & 0xff; \
output[s+2] = (input[i] >> 16) & 0xff; \
output[s+3] = (input[i] >> 24) & 0xff;
output[0] = 0;
output[16] = 0;
F(0,0);
F(1,3);
F(2,6);
F(3,9);
F(4,12);
F(5,16);
F(6,19);
F(7,22);
F(8,25);
F(9,28);
#undef F
}
/* Input: Q, Q', Q-Q'
* Output: 2Q, Q+Q'
*
* x2 z3: long form
* x3 z3: long form
* x z: short form, destroyed
* xprime zprime: short form, destroyed
* qmqp: short form, preserved
*
* On entry and exit, the absolute value of the limbs of all inputs and outputs
* are < 2^26. */
static void fmonty(limb *x2, limb *z2, /* output 2Q */
limb *x3, limb *z3, /* output Q + Q' */
limb *x, limb *z, /* input Q */
limb *xprime, limb *zprime, /* input Q' */
const limb *qmqp /* input Q - Q' */) {
limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
zzprime[19], zzzprime[19], xxxprime[19];
memcpy(origx, x, 10 * sizeof(limb));
fsum(x, z);
/* |x[i]| < 2^27 */
fdifference(z, origx); /* does x - z */
/* |z[i]| < 2^27 */
memcpy(origxprime, xprime, sizeof(limb) * 10);
fsum(xprime, zprime);
/* |xprime[i]| < 2^27 */
fdifference(zprime, origxprime);
/* |zprime[i]| < 2^27 */
fproduct(xxprime, xprime, z);
/* |xxprime[i]| < 14*2^54: the largest product of two limbs will be <
* 2^(27+27) and fproduct adds together, at most, 14 of those products.
* (Approximating that to 2^58 doesn't work out.) */
fproduct(zzprime, x, zprime);
/* |zzprime[i]| < 14*2^54 */
freduce_degree(xxprime);
freduce_coefficients(xxprime);
/* |xxprime[i]| < 2^26 */
freduce_degree(zzprime);
freduce_coefficients(zzprime);
/* |zzprime[i]| < 2^26 */
memcpy(origxprime, xxprime, sizeof(limb) * 10);
fsum(xxprime, zzprime);
/* |xxprime[i]| < 2^27 */
fdifference(zzprime, origxprime);
/* |zzprime[i]| < 2^27 */
fsquare(xxxprime, xxprime);
/* |xxxprime[i]| < 2^26 */
fsquare(zzzprime, zzprime);
/* |zzzprime[i]| < 2^26 */
fproduct(zzprime, zzzprime, qmqp);
/* |zzprime[i]| < 14*2^52 */
freduce_degree(zzprime);
freduce_coefficients(zzprime);
/* |zzprime[i]| < 2^26 */
memcpy(x3, xxxprime, sizeof(limb) * 10);
memcpy(z3, zzprime, sizeof(limb) * 10);
fsquare(xx, x);
/* |xx[i]| < 2^26 */
fsquare(zz, z);
/* |zz[i]| < 2^26 */
fproduct(x2, xx, zz);
/* |x2[i]| < 14*2^52 */
freduce_degree(x2);
freduce_coefficients(x2);
/* |x2[i]| < 2^26 */
fdifference(zz, xx); // does zz = xx - zz
/* |zz[i]| < 2^27 */
memset(zzz + 10, 0, sizeof(limb) * 9);
fscalar_product(zzz, zz, 121665);
/* |zzz[i]| < 2^(27+17) */
/* No need to call freduce_degree here:
fscalar_product doesn't increase the degree of its input. */
freduce_coefficients(zzz);
/* |zzz[i]| < 2^26 */
fsum(zzz, xx);
/* |zzz[i]| < 2^27 */
fproduct(z2, zz, zzz);
/* |z2[i]| < 14*2^(26+27) */
freduce_degree(z2);
freduce_coefficients(z2);
/* |z2|i| < 2^26 */
}
/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave
* them unchanged if 'iswap' is 0. Runs in data-invariant time to avoid
* side-channel attacks.
*
* NOTE that this function requires that 'iswap' be 1 or 0; other values give
* wrong results. Also, the two limb arrays must be in reduced-coefficient,
* reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped,
* and all all values in a[0..9],b[0..9] must have magnitude less than
* INT32_MAX. */
static void
swap_conditional(limb a[19], limb b[19], limb iswap) {
unsigned i;
const s32 swap = (s32) -iswap;
for (i = 0; i < 10; ++i) {
const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) );
a[i] = ((s32)a[i]) ^ x;
b[i] = ((s32)b[i]) ^ x;
}
}
/* Calculates nQ where Q is the x-coordinate of a point on the curve
*
* resultx/resultz: the x coordinate of the resulting curve point (short form)
* n: a little endian, 32-byte number
* q: a point of the curve (short form) */
static void
cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) {
limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};
limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
unsigned i, j;
memcpy(nqpqx, q, sizeof(limb) * 10);
for (i = 0; i < 32; ++i) {
u8 byte = n[31 - i];
for (j = 0; j < 8; ++j) {
const limb bit = byte >> 7;
swap_conditional(nqx, nqpqx, bit);
swap_conditional(nqz, nqpqz, bit);
fmonty(nqx2, nqz2,
nqpqx2, nqpqz2,
nqx, nqz,
nqpqx, nqpqz,
q);
swap_conditional(nqx2, nqpqx2, bit);
swap_conditional(nqz2, nqpqz2, bit);
t = nqx;
nqx = nqx2;
nqx2 = t;
t = nqz;
nqz = nqz2;
nqz2 = t;
t = nqpqx;
nqpqx = nqpqx2;
nqpqx2 = t;
t = nqpqz;
nqpqz = nqpqz2;
nqpqz2 = t;
byte <<= 1;
}
}
memcpy(resultx, nqx, sizeof(limb) * 10);
memcpy(resultz, nqz, sizeof(limb) * 10);
}
// -----------------------------------------------------------------------------
// Shamelessly copied from djb's code
// -----------------------------------------------------------------------------
static void
crecip(limb *out, const limb *z) {
limb z2[10];
limb z9[10];
limb z11[10];
limb z2_5_0[10];
limb z2_10_0[10];
limb z2_20_0[10];
limb z2_50_0[10];
limb z2_100_0[10];
limb t0[10];
limb t1[10];
int i;
/* 2 */ fsquare(z2,z);
/* 4 */ fsquare(t1,z2);
/* 8 */ fsquare(t0,t1);
/* 9 */ fmul(z9,t0,z);
/* 11 */ fmul(z11,z9,z2);
/* 22 */ fsquare(t0,z11);
/* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9);
/* 2^6 - 2^1 */ fsquare(t0,z2_5_0);
/* 2^7 - 2^2 */ fsquare(t1,t0);
/* 2^8 - 2^3 */ fsquare(t0,t1);
/* 2^9 - 2^4 */ fsquare(t1,t0);
/* 2^10 - 2^5 */ fsquare(t0,t1);
/* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0);
/* 2^11 - 2^1 */ fsquare(t0,z2_10_0);
/* 2^12 - 2^2 */ fsquare(t1,t0);
/* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
/* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0);
/* 2^21 - 2^1 */ fsquare(t0,z2_20_0);
/* 2^22 - 2^2 */ fsquare(t1,t0);
/* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
/* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0);
/* 2^41 - 2^1 */ fsquare(t1,t0);
/* 2^42 - 2^2 */ fsquare(t0,t1);
/* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
/* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0);
/* 2^51 - 2^1 */ fsquare(t0,z2_50_0);
/* 2^52 - 2^2 */ fsquare(t1,t0);
/* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
/* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0);
/* 2^101 - 2^1 */ fsquare(t1,z2_100_0);
/* 2^102 - 2^2 */ fsquare(t0,t1);
/* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
/* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0);
/* 2^201 - 2^1 */ fsquare(t0,t1);
/* 2^202 - 2^2 */ fsquare(t1,t0);
/* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
/* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0);
/* 2^251 - 2^1 */ fsquare(t1,t0);
/* 2^252 - 2^2 */ fsquare(t0,t1);
/* 2^253 - 2^3 */ fsquare(t1,t0);
/* 2^254 - 2^4 */ fsquare(t0,t1);
/* 2^255 - 2^5 */ fsquare(t1,t0);
/* 2^255 - 21 */ fmul(out,t1,z11);
}
int
curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
limb bp[10], x[10], z[11], zmone[10];
uint8_t e[32];
int i;
for (i = 0; i < 32; ++i) e[i] = secret[i];
// e[0] &= 248;
// e[31] &= 127;
// e[31] |= 64;
fexpand(bp, basepoint);
cmult(x, z, e, bp);
crecip(zmone, z);
fmul(z, x, zmone);
fcontract(mypublic, z);
return 0;
}

View File

@@ -1,6 +0,0 @@
#ifndef CURVE25519_DONNA_H
#define CURVE25519_DONNA_H
extern int curve25519_donna(uint8_t *, const uint8_t *, const uint8_t *);
#endif

View File

@@ -1,109 +0,0 @@
/**
* Copyright (C) 2013-2014 Open Whisper Systems
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdint.h>
#include <jni.h>
#include "curve25519-donna.h"
#include "curve_sigs.h"
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_generatePrivateKey
(JNIEnv *env, jclass clazz, jbyteArray random)
{
uint8_t* privateKey = (uint8_t*)(*env)->GetByteArrayElements(env, random, 0);
privateKey[0] &= 248;
privateKey[31] &= 127;
privateKey[31] |= 64;
(*env)->ReleaseByteArrayElements(env, random, privateKey, 0);
return random;
}
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_generatePublicKey
(JNIEnv *env, jclass clazz, jbyteArray privateKey)
{
static const uint8_t basepoint[32] = {9};
jbyteArray publicKey = (*env)->NewByteArray(env, 32);
uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0);
uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0);
curve25519_donna(publicKeyBytes, privateKeyBytes, basepoint);
(*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
return publicKey;
}
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateAgreement
(JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey)
{
jbyteArray sharedKey = (*env)->NewByteArray(env, 32);
uint8_t* sharedKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, sharedKey, 0);
uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0);
uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0);
curve25519_donna(sharedKeyBytes, privateKeyBytes, publicKeyBytes);
(*env)->ReleaseByteArrayElements(env, sharedKey, sharedKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
return sharedKey;
}
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateSignature
(JNIEnv *env, jclass clazz, jbyteArray random, jbyteArray privateKey, jbyteArray message)
{
jbyteArray signature = (*env)->NewByteArray(env, 64);
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0);
uint8_t* randomBytes = (uint8_t*)(*env)->GetByteArrayElements(env, random, 0);
uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0);
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);
int result = curve25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, random, randomBytes, 0);
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);
if (result == 0) return signature;
else (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/AssertionError"), "Signature failed!");
}
JNIEXPORT jboolean JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_verifySignature
(JNIEnv *env, jclass clazz, jbyteArray publicKey, jbyteArray message, jbyteArray signature)
{
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0);
uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0);
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);
jboolean result = (curve25519_verify(signatureBytes, publicKeyBytes, messageBytes, messageLength) == 0);
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);
return result;
}

View File

@@ -1,44 +0,0 @@
#include <string.h>
#include "compare.h"
/* Const-time comparison from SUPERCOP, but here it's only used for
signature verification, so doesn't need to be const-time. But
copied the nacl version anyways. */
int crypto_verify_32_ref(const unsigned char *x, const unsigned char *y)
{
unsigned int differentbits = 0;
#define F(i) differentbits |= x[i] ^ y[i];
F(0)
F(1)
F(2)
F(3)
F(4)
F(5)
F(6)
F(7)
F(8)
F(9)
F(10)
F(11)
F(12)
F(13)
F(14)
F(15)
F(16)
F(17)
F(18)
F(19)
F(20)
F(21)
F(22)
F(23)
F(24)
F(25)
F(26)
F(27)
F(28)
F(29)
F(30)
F(31)
return (1 & ((differentbits - 1) >> 8)) - 1;
}

View File

@@ -1,6 +0,0 @@
#ifndef __COMPARE_H__
#define __COMPARE_H__
int crypto_verify_32_ref(const unsigned char *b1, const unsigned char *b2);
#endif

View File

@@ -1,6 +0,0 @@
#ifndef crypto_hash_sha512_H
#define crypto_hash_sha512_H
extern int crypto_hash_sha512(unsigned char *,const unsigned char *,unsigned long long);
#endif

View File

@@ -1,116 +0,0 @@
#include <string.h>
#include "ge.h"
#include "curve_sigs.h"
#include "crypto_sign.h"
void curve25519_keygen(unsigned char* curve25519_pubkey_out,
const unsigned char* curve25519_privkey_in)
{
ge_p3 ed; /* Ed25519 pubkey point */
fe ed_y, ed_y_plus_one, one_minus_ed_y, inv_one_minus_ed_y;
fe mont_x;
/* Perform a fixed-base multiplication of the Edwards base point,
(which is efficient due to precalculated tables), then convert
to the Curve25519 montgomery-format public key. In particular,
convert Curve25519's "montgomery" x-coordinate into an Ed25519
"edwards" y-coordinate:
mont_x = (ed_y + 1) / (1 - ed_y)
with projective coordinates:
mont_x = (ed_y + ed_z) / (ed_z - ed_y)
NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp
*/
ge_scalarmult_base(&ed, curve25519_privkey_in);
fe_add(ed_y_plus_one, ed.Y, ed.Z);
fe_sub(one_minus_ed_y, ed.Z, ed.Y);
fe_invert(inv_one_minus_ed_y, one_minus_ed_y);
fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y);
fe_tobytes(curve25519_pubkey_out, mont_x);
}
int curve25519_sign(unsigned char* signature_out,
const unsigned char* curve25519_privkey,
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random)
{
ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */
unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */
unsigned char sigbuf[MAX_MSG_LEN + 128]; /* working buffer */
unsigned char sign_bit = 0;
if (msg_len > MAX_MSG_LEN) {
memset(signature_out, 0, 64);
return -1;
}
/* Convert the Curve25519 privkey to an Ed25519 public key */
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
ge_p3_tobytes(ed_pubkey, &ed_pubkey_point);
sign_bit = ed_pubkey[31] & 0x80;
/* Perform an Ed25519 signature with explicit private key */
crypto_sign_modified(sigbuf, msg, msg_len, curve25519_privkey,
ed_pubkey, random);
memmove(signature_out, sigbuf, 64);
/* Encode the sign bit into signature (in unused high bit of S) */
signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */
signature_out[63] |= sign_bit;
return 0;
}
int curve25519_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const unsigned long msg_len)
{
fe mont_x, mont_x_minus_one, mont_x_plus_one, inv_mont_x_plus_one;
fe one;
fe ed_y;
unsigned char ed_pubkey[32];
unsigned long long some_retval;
unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */
unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */
if (msg_len > MAX_MSG_LEN) {
return -1;
}
/* Convert the Curve25519 public key into an Ed25519 public key. In
particular, convert Curve25519's "montgomery" x-coordinate into an
Ed25519 "edwards" y-coordinate:
ed_y = (mont_x - 1) / (mont_x + 1)
NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp
Then move the sign bit into the pubkey from the signature.
*/
fe_frombytes(mont_x, curve25519_pubkey);
fe_1(one);
fe_sub(mont_x_minus_one, mont_x, one);
fe_add(mont_x_plus_one, mont_x, one);
fe_invert(inv_mont_x_plus_one, mont_x_plus_one);
fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one);
fe_tobytes(ed_pubkey, ed_y);
/* Copy the sign bit, and remove it from signature */
ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */
ed_pubkey[31] |= (signature[63] & 0x80);
memmove(verifybuf, signature, 64);
verifybuf[63] &= 0x7F;
memmove(verifybuf+64, msg, msg_len);
/* Then perform a normal Ed25519 verification, return 0 on success */
/* The below call has a strange API: */
/* verifybuf = R || S || message */
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
replaced with pubkey for hashing, then the whole thing gets zeroized
(if bad sig), or contains a copy of msg (good sig) */
return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);
}

View File

@@ -1,50 +0,0 @@
#ifndef __CURVE_SIGS_H__
#define __CURVE_SIGS_H__
#define MAX_MSG_LEN 256
void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */
const unsigned char* curve25519_privkey_in); /* 32 bytes */
/* returns 0 on success */
int curve25519_sign(unsigned char* signature_out, /* 64 bytes */
const unsigned char* curve25519_privkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random); /* 64 bytes */
/* returns 0 on success */
int curve25519_verify(const unsigned char* signature, /* 64 bytes */
const unsigned char* curve25519_pubkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len);
/* helper function - modified version of crypto_sign() to use
explicit private key. In particular:
sk : private key
pk : public key
msg : message
prefix : 0xFE || [0xFF]*31
random : 64 bytes random
q : main subgroup order
The prefix is chosen to distinguish the two SHA512 uses below, since
prefix is an invalid encoding for R (it would encode a "field element"
of 2^255 - 2). 0xFF*32 is set aside for use in ECDH protocols, which
is why the first byte here ix 0xFE.
sig_nonce = SHA512(prefix || sk || msg || random) % q
R = g^sig_nonce
M = SHA512(R || pk || m)
S = sig_nonce + (m * sk)
signature = (R || S)
*/
int crypto_sign_modified(
unsigned char *sm,
const unsigned char *m,unsigned long long mlen,
const unsigned char *sk, /* Curve/Ed25519 private key */
const unsigned char *pk, /* Ed25519 public key */
const unsigned char *random /* 64 bytes random to hash into nonce */
);
#endif

View File

@@ -1,47 +0,0 @@
#include <string.h>
#include "crypto_sign.h"
#include "crypto_hash_sha512.h"
#include "ge.h"
#include "sc.h"
#include "zeroize.h"
/* NEW: Compare to pristine crypto_sign()
Uses explicit private key for nonce derivation and as scalar,
instead of deriving both from a master key.
*/
int crypto_sign_modified(
unsigned char *sm,
const unsigned char *m,unsigned long long mlen,
const unsigned char *sk, const unsigned char* pk,
const unsigned char* random
)
{
unsigned char nonce[64];
unsigned char hram[64];
ge_p3 R;
int count=0;
memmove(sm + 64,m,mlen);
memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */
/* NEW : add prefix to separate hash uses - see .h */
sm[0] = 0xFE;
for (count = 1; count < 32; count++)
sm[count] = 0xFF;
/* NEW: add suffix of random data */
memmove(sm + mlen + 64, random, 64);
crypto_hash_sha512(nonce,sm,mlen + 128);
memmove(sm + 32,pk,32);
sc_reduce(nonce);
ge_scalarmult_base(&R,nonce);
ge_p3_tobytes(sm,&R);
crypto_hash_sha512(hram,sm,mlen + 64);
sc_reduce(hram);
sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */
return 0;
}

View File

@@ -1,17 +0,0 @@
#include "zeroize.h"
void zeroize(unsigned char* b, size_t len)
{
size_t count = 0;
unsigned long retval = 0;
volatile unsigned char *p = b;
for (count = 0; count < len; count++)
p[count] = 0;
}
void zeroize_stack()
{
unsigned char m[ZEROIZE_STACK_SIZE];
zeroize(m, sizeof m);
}

View File

@@ -1,12 +0,0 @@
#ifndef __ZEROIZE_H__
#define __ZEROIZE_H__
#include <stdlib.h>
#define ZEROIZE_STACK_SIZE 2048
void zeroize(unsigned char* b, size_t len);
void zeroize_stack();
#endif

View File

@@ -1,4 +0,0 @@
#define CRYPTO_SECRETKEYBYTES 64
#define CRYPTO_PUBLICKEYBYTES 32
#define CRYPTO_BYTES 64
#define CRYPTO_DETERMINISTIC 1

File diff suppressed because it is too large Load Diff

View File

@@ -1,40 +0,0 @@
{
{ 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
{ -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
{ -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
},
{
{ 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
{ 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
{ 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
},
{
{ 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
{ 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
{ 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
},
{
{ 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
{ -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
{ 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
},
{
{ -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 },
{ -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 },
{ 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 },
},
{
{ -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 },
{ 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 },
{ 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 },
},
{
{ -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 },
{ -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 },
{ -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 },
},
{
{ -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 },
{ -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 },
{ -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 },
},

View File

@@ -1 +0,0 @@
-10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116

View File

@@ -1 +0,0 @@
-21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199

View File

@@ -1,56 +0,0 @@
#ifndef FE_H
#define FE_H
#include "crypto_int32.h"
typedef crypto_int32 fe[10];
/*
fe means field element.
Here the field is \Z/(2^255-19).
An element t, entries t[0]...t[9], represents the integer
t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
Bounds on each t[i] vary depending on context.
*/
#define fe_frombytes crypto_sign_ed25519_ref10_fe_frombytes
#define fe_tobytes crypto_sign_ed25519_ref10_fe_tobytes
#define fe_copy crypto_sign_ed25519_ref10_fe_copy
#define fe_isnonzero crypto_sign_ed25519_ref10_fe_isnonzero
#define fe_isnegative crypto_sign_ed25519_ref10_fe_isnegative
#define fe_0 crypto_sign_ed25519_ref10_fe_0
#define fe_1 crypto_sign_ed25519_ref10_fe_1
#define fe_cswap crypto_sign_ed25519_ref10_fe_cswap
#define fe_cmov crypto_sign_ed25519_ref10_fe_cmov
#define fe_add crypto_sign_ed25519_ref10_fe_add
#define fe_sub crypto_sign_ed25519_ref10_fe_sub
#define fe_neg crypto_sign_ed25519_ref10_fe_neg
#define fe_mul crypto_sign_ed25519_ref10_fe_mul
#define fe_sq crypto_sign_ed25519_ref10_fe_sq
#define fe_sq2 crypto_sign_ed25519_ref10_fe_sq2
#define fe_mul121666 crypto_sign_ed25519_ref10_fe_mul121666
#define fe_invert crypto_sign_ed25519_ref10_fe_invert
#define fe_pow22523 crypto_sign_ed25519_ref10_fe_pow22523
extern void fe_frombytes(fe,const unsigned char *);
extern void fe_tobytes(unsigned char *,const fe);
extern void fe_copy(fe,const fe);
extern int fe_isnonzero(const fe);
extern int fe_isnegative(const fe);
extern void fe_0(fe);
extern void fe_1(fe);
extern void fe_cswap(fe,fe,unsigned int);
extern void fe_cmov(fe,const fe,unsigned int);
extern void fe_add(fe,const fe,const fe);
extern void fe_sub(fe,const fe,const fe);
extern void fe_neg(fe,const fe);
extern void fe_mul(fe,const fe,const fe);
extern void fe_sq(fe,const fe);
extern void fe_sq2(fe,const fe);
extern void fe_mul121666(fe,const fe);
extern void fe_invert(fe,const fe);
extern void fe_pow22523(fe,const fe);
#endif

View File

@@ -1,19 +0,0 @@
#include "fe.h"
/*
h = 0
*/
void fe_0(fe h)
{
h[0] = 0;
h[1] = 0;
h[2] = 0;
h[3] = 0;
h[4] = 0;
h[5] = 0;
h[6] = 0;
h[7] = 0;
h[8] = 0;
h[9] = 0;
}

View File

@@ -1,19 +0,0 @@
#include "fe.h"
/*
h = 1
*/
void fe_1(fe h)
{
h[0] = 1;
h[1] = 0;
h[2] = 0;
h[3] = 0;
h[4] = 0;
h[5] = 0;
h[6] = 0;
h[7] = 0;
h[8] = 0;
h[9] = 0;
}

View File

@@ -1,57 +0,0 @@
#include "fe.h"
/*
h = f + g
Can overlap h with f or g.
Preconditions:
|f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
Postconditions:
|h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
void fe_add(fe h,const fe f,const fe g)
{
crypto_int32 f0 = f[0];
crypto_int32 f1 = f[1];
crypto_int32 f2 = f[2];
crypto_int32 f3 = f[3];
crypto_int32 f4 = f[4];
crypto_int32 f5 = f[5];
crypto_int32 f6 = f[6];
crypto_int32 f7 = f[7];
crypto_int32 f8 = f[8];
crypto_int32 f9 = f[9];
crypto_int32 g0 = g[0];
crypto_int32 g1 = g[1];
crypto_int32 g2 = g[2];
crypto_int32 g3 = g[3];
crypto_int32 g4 = g[4];
crypto_int32 g5 = g[5];
crypto_int32 g6 = g[6];
crypto_int32 g7 = g[7];
crypto_int32 g8 = g[8];
crypto_int32 g9 = g[9];
crypto_int32 h0 = f0 + g0;
crypto_int32 h1 = f1 + g1;
crypto_int32 h2 = f2 + g2;
crypto_int32 h3 = f3 + g3;
crypto_int32 h4 = f4 + g4;
crypto_int32 h5 = f5 + g5;
crypto_int32 h6 = f6 + g6;
crypto_int32 h7 = f7 + g7;
crypto_int32 h8 = f8 + g8;
crypto_int32 h9 = f9 + g9;
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
h[5] = h5;
h[6] = h6;
h[7] = h7;
h[8] = h8;
h[9] = h9;
}

View File

@@ -1,63 +0,0 @@
#include "fe.h"
/*
Replace (f,g) with (g,g) if b == 1;
replace (f,g) with (f,g) if b == 0.
Preconditions: b in {0,1}.
*/
void fe_cmov(fe f,const fe g,unsigned int b)
{
crypto_int32 f0 = f[0];
crypto_int32 f1 = f[1];
crypto_int32 f2 = f[2];
crypto_int32 f3 = f[3];
crypto_int32 f4 = f[4];
crypto_int32 f5 = f[5];
crypto_int32 f6 = f[6];
crypto_int32 f7 = f[7];
crypto_int32 f8 = f[8];
crypto_int32 f9 = f[9];
crypto_int32 g0 = g[0];
crypto_int32 g1 = g[1];
crypto_int32 g2 = g[2];
crypto_int32 g3 = g[3];
crypto_int32 g4 = g[4];
crypto_int32 g5 = g[5];
crypto_int32 g6 = g[6];
crypto_int32 g7 = g[7];
crypto_int32 g8 = g[8];
crypto_int32 g9 = g[9];
crypto_int32 x0 = f0 ^ g0;
crypto_int32 x1 = f1 ^ g1;
crypto_int32 x2 = f2 ^ g2;
crypto_int32 x3 = f3 ^ g3;
crypto_int32 x4 = f4 ^ g4;
crypto_int32 x5 = f5 ^ g5;
crypto_int32 x6 = f6 ^ g6;
crypto_int32 x7 = f7 ^ g7;
crypto_int32 x8 = f8 ^ g8;
crypto_int32 x9 = f9 ^ g9;
b = -b;
x0 &= b;
x1 &= b;
x2 &= b;
x3 &= b;
x4 &= b;
x5 &= b;
x6 &= b;
x7 &= b;
x8 &= b;
x9 &= b;
f[0] = f0 ^ x0;
f[1] = f1 ^ x1;
f[2] = f2 ^ x2;
f[3] = f3 ^ x3;
f[4] = f4 ^ x4;
f[5] = f5 ^ x5;
f[6] = f6 ^ x6;
f[7] = f7 ^ x7;
f[8] = f8 ^ x8;
f[9] = f9 ^ x9;
}

View File

@@ -1,29 +0,0 @@
#include "fe.h"
/*
h = f
*/
void fe_copy(fe h,const fe f)
{
crypto_int32 f0 = f[0];
crypto_int32 f1 = f[1];
crypto_int32 f2 = f[2];
crypto_int32 f3 = f[3];
crypto_int32 f4 = f[4];
crypto_int32 f5 = f[5];
crypto_int32 f6 = f[6];
crypto_int32 f7 = f[7];
crypto_int32 f8 = f[8];
crypto_int32 f9 = f[9];
h[0] = f0;
h[1] = f1;
h[2] = f2;
h[3] = f3;
h[4] = f4;
h[5] = f5;
h[6] = f6;
h[7] = f7;
h[8] = f8;
h[9] = f9;
}

View File

@@ -1,73 +0,0 @@
#include "fe.h"
#include "crypto_int64.h"
#include "crypto_uint64.h"
static crypto_uint64 load_3(const unsigned char *in)
{
crypto_uint64 result;
result = (crypto_uint64) in[0];
result |= ((crypto_uint64) in[1]) << 8;
result |= ((crypto_uint64) in[2]) << 16;
return result;
}
static crypto_uint64 load_4(const unsigned char *in)
{
crypto_uint64 result;
result = (crypto_uint64) in[0];
result |= ((crypto_uint64) in[1]) << 8;
result |= ((crypto_uint64) in[2]) << 16;
result |= ((crypto_uint64) in[3]) << 24;
return result;
}
/*
Ignores top bit of h.
*/
void fe_frombytes(fe h,const unsigned char *s)
{
crypto_int64 h0 = load_4(s);
crypto_int64 h1 = load_3(s + 4) << 6;
crypto_int64 h2 = load_3(s + 7) << 5;
crypto_int64 h3 = load_3(s + 10) << 3;
crypto_int64 h4 = load_3(s + 13) << 2;
crypto_int64 h5 = load_4(s + 16);
crypto_int64 h6 = load_3(s + 20) << 7;
crypto_int64 h7 = load_3(s + 23) << 5;
crypto_int64 h8 = load_3(s + 26) << 4;
crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2;
crypto_int64 carry0;
crypto_int64 carry1;
crypto_int64 carry2;
crypto_int64 carry3;
crypto_int64 carry4;
crypto_int64 carry5;
crypto_int64 carry6;
crypto_int64 carry7;
crypto_int64 carry8;
crypto_int64 carry9;
carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
h[5] = h5;
h[6] = h6;
h[7] = h7;
h[8] = h8;
h[9] = h9;
}

View File

@@ -1,14 +0,0 @@
#include "fe.h"
void fe_invert(fe out,const fe z)
{
fe t0;
fe t1;
fe t2;
fe t3;
int i;
#include "pow225521.h"
return;
}

View File

@@ -1,16 +0,0 @@
#include "fe.h"
/*
return 1 if f is in {1,3,5,...,q-2}
return 0 if f is in {0,2,4,...,q-1}
Preconditions:
|f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
int fe_isnegative(const fe f)
{
unsigned char s[32];
fe_tobytes(s,f);
return s[0] & 1;
}

View File

@@ -1,19 +0,0 @@
#include "fe.h"
#include "crypto_verify_32.h"
/*
return 1 if f == 0
return 0 if f != 0
Preconditions:
|f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
static const unsigned char zero[32];
int fe_isnonzero(const fe f)
{
unsigned char s[32];
fe_tobytes(s,f);
return crypto_verify_32(s,zero);
}

View File

@@ -1,253 +0,0 @@
#include "fe.h"
#include "crypto_int64.h"
/*
h = f * g
Can overlap h with f or g.
Preconditions:
|f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
|g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
Postconditions:
|h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
*/
/*
Notes on implementation strategy:
Using schoolbook multiplication.
Karatsuba would save a little in some cost models.
Most multiplications by 2 and 19 are 32-bit precomputations;
cheaper than 64-bit postcomputations.
There is one remaining multiplication by 19 in the carry chain;
one *19 precomputation can be merged into this,
but the resulting data flow is considerably less clean.
There are 12 carries below.
10 of them are 2-way parallelizable and vectorizable.
Can get away with 11 carries, but then data flow is much deeper.
With tighter constraints on inputs can squeeze carries into int32.
*/
void fe_mul(fe h,const fe f,const fe g)
{
crypto_int32 f0 = f[0];
crypto_int32 f1 = f[1];
crypto_int32 f2 = f[2];
crypto_int32 f3 = f[3];
crypto_int32 f4 = f[4];
crypto_int32 f5 = f[5];
crypto_int32 f6 = f[6];
crypto_int32 f7 = f[7];
crypto_int32 f8 = f[8];
crypto_int32 f9 = f[9];
crypto_int32 g0 = g[0];
crypto_int32 g1 = g[1];
crypto_int32 g2 = g[2];
crypto_int32 g3 = g[3];
crypto_int32 g4 = g[4];
crypto_int32 g5 = g[5];
crypto_int32 g6 = g[6];
crypto_int32 g7 = g[7];
crypto_int32 g8 = g[8];
crypto_int32 g9 = g[9];
crypto_int32 g1_19 = 19 * g1; /* 1.959375*2^29 */
crypto_int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
crypto_int32 g3_19 = 19 * g3;
crypto_int32 g4_19 = 19 * g4;
crypto_int32 g5_19 = 19 * g5;
crypto_int32 g6_19 = 19 * g6;
crypto_int32 g7_19 = 19 * g7;
crypto_int32 g8_19 = 19 * g8;
crypto_int32 g9_19 = 19 * g9;
crypto_int32 f1_2 = 2 * f1;
crypto_int32 f3_2 = 2 * f3;
crypto_int32 f5_2 = 2 * f5;
crypto_int32 f7_2 = 2 * f7;
crypto_int32 f9_2 = 2 * f9;
crypto_int64 f0g0 = f0 * (crypto_int64) g0;
crypto_int64 f0g1 = f0 * (crypto_int64) g1;
crypto_int64 f0g2 = f0 * (crypto_int64) g2;
crypto_int64 f0g3 = f0 * (crypto_int64) g3;
crypto_int64 f0g4 = f0 * (crypto_int64) g4;
crypto_int64 f0g5 = f0 * (crypto_int64) g5;
crypto_int64 f0g6 = f0 * (crypto_int64) g6;
crypto_int64 f0g7 = f0 * (crypto_int64) g7;
crypto_int64 f0g8 = f0 * (crypto_int64) g8;
crypto_int64 f0g9 = f0 * (crypto_int64) g9;
crypto_int64 f1g0 = f1 * (crypto_int64) g0;
crypto_int64 f1g1_2 = f1_2 * (crypto_int64) g1;
crypto_int64 f1g2 = f1 * (crypto_int64) g2;
crypto_int64 f1g3_2 = f1_2 * (crypto_int64) g3;
crypto_int64 f1g4 = f1 * (crypto_int64) g4;
crypto_int64 f1g5_2 = f1_2 * (crypto_int64) g5;
crypto_int64 f1g6 = f1 * (crypto_int64) g6;
crypto_int64 f1g7_2 = f1_2 * (crypto_int64) g7;
crypto_int64 f1g8 = f1 * (crypto_int64) g8;
crypto_int64 f1g9_38 = f1_2 * (crypto_int64) g9_19;
crypto_int64 f2g0 = f2 * (crypto_int64) g0;
crypto_int64 f2g1 = f2 * (crypto_int64) g1;
crypto_int64 f2g2 = f2 * (crypto_int64) g2;
crypto_int64 f2g3 = f2 * (crypto_int64) g3;
crypto_int64 f2g4 = f2 * (crypto_int64) g4;
crypto_int64 f2g5 = f2 * (crypto_int64) g5;
crypto_int64 f2g6 = f2 * (crypto_int64) g6;
crypto_int64 f2g7 = f2 * (crypto_int64) g7;
crypto_int64 f2g8_19 = f2 * (crypto_int64) g8_19;
crypto_int64 f2g9_19 = f2 * (crypto_int64) g9_19;
crypto_int64 f3g0 = f3 * (crypto_int64) g0;
crypto_int64 f3g1_2 = f3_2 * (crypto_int64) g1;
crypto_int64 f3g2 = f3 * (crypto_int64) g2;
crypto_int64 f3g3_2 = f3_2 * (crypto_int64) g3;
crypto_int64 f3g4 = f3 * (crypto_int64) g4;
crypto_int64 f3g5_2 = f3_2 * (crypto_int64) g5;
crypto_int64 f3g6 = f3 * (crypto_int64) g6;
crypto_int64 f3g7_38 = f3_2 * (crypto_int64) g7_19;
crypto_int64 f3g8_19 = f3 * (crypto_int64) g8_19;
crypto_int64 f3g9_38 = f3_2 * (crypto_int64) g9_19;
crypto_int64 f4g0 = f4 * (crypto_int64) g0;
crypto_int64 f4g1 = f4 * (crypto_int64) g1;
crypto_int64 f4g2 = f4 * (crypto_int64) g2;
crypto_int64 f4g3 = f4 * (crypto_int64) g3;
crypto_int64 f4g4 = f4 * (crypto_int64) g4;
crypto_int64 f4g5 = f4 * (crypto_int64) g5;
crypto_int64 f4g6_19 = f4 * (crypto_int64) g6_19;
crypto_int64 f4g7_19 = f4 * (crypto_int64) g7_19;
crypto_int64 f4g8_19 = f4 * (crypto_int64) g8_19;
crypto_int64 f4g9_19 = f4 * (crypto_int64) g9_19;
crypto_int64 f5g0 = f5 * (crypto_int64) g0;
crypto_int64 f5g1_2 = f5_2 * (crypto_int64) g1;
crypto_int64 f5g2 = f5 * (crypto_int64) g2;
crypto_int64 f5g3_2 = f5_2 * (crypto_int64) g3;
crypto_int64 f5g4 = f5 * (crypto_int64) g4;
crypto_int64 f5g5_38 = f5_2 * (crypto_int64) g5_19;
crypto_int64 f5g6_19 = f5 * (crypto_int64) g6_19;
crypto_int64 f5g7_38 = f5_2 * (crypto_int64) g7_19;
crypto_int64 f5g8_19 = f5 * (crypto_int64) g8_19;
crypto_int64 f5g9_38 = f5_2 * (crypto_int64) g9_19;
crypto_int64 f6g0 = f6 * (crypto_int64) g0;
crypto_int64 f6g1 = f6 * (crypto_int64) g1;
crypto_int64 f6g2 = f6 * (crypto_int64) g2;
crypto_int64 f6g3 = f6 * (crypto_int64) g3;
crypto_int64 f6g4_19 = f6 * (crypto_int64) g4_19;
crypto_int64 f6g5_19 = f6 * (crypto_int64) g5_19;
crypto_int64 f6g6_19 = f6 * (crypto_int64) g6_19;
crypto_int64 f6g7_19 = f6 * (crypto_int64) g7_19;
crypto_int64 f6g8_19 = f6 * (crypto_int64) g8_19;
crypto_int64 f6g9_19 = f6 * (crypto_int64) g9_19;
crypto_int64 f7g0 = f7 * (crypto_int64) g0;
crypto_int64 f7g1_2 = f7_2 * (crypto_int64) g1;
crypto_int64 f7g2 = f7 * (crypto_int64) g2;
crypto_int64 f7g3_38 = f7_2 * (crypto_int64) g3_19;
crypto_int64 f7g4_19 = f7 * (crypto_int64) g4_19;
crypto_int64 f7g5_38 = f7_2 * (crypto_int64) g5_19;
crypto_int64 f7g6_19 = f7 * (crypto_int64) g6_19;
crypto_int64 f7g7_38 = f7_2 * (crypto_int64) g7_19;
crypto_int64 f7g8_19 = f7 * (crypto_int64) g8_19;
crypto_int64 f7g9_38 = f7_2 * (crypto_int64) g9_19;
crypto_int64 f8g0 = f8 * (crypto_int64) g0;
crypto_int64 f8g1 = f8 * (crypto_int64) g1;
crypto_int64 f8g2_19 = f8 * (crypto_int64) g2_19;
crypto_int64 f8g3_19 = f8 * (crypto_int64) g3_19;
crypto_int64 f8g4_19 = f8 * (crypto_int64) g4_19;
crypto_int64 f8g5_19 = f8 * (crypto_int64) g5_19;
crypto_int64 f8g6_19 = f8 * (crypto_int64) g6_19;
crypto_int64 f8g7_19 = f8 * (crypto_int64) g7_19;
crypto_int64 f8g8_19 = f8 * (crypto_int64) g8_19;
crypto_int64 f8g9_19 = f8 * (crypto_int64) g9_19;
crypto_int64 f9g0 = f9 * (crypto_int64) g0;
crypto_int64 f9g1_38 = f9_2 * (crypto_int64) g1_19;
crypto_int64 f9g2_19 = f9 * (crypto_int64) g2_19;
crypto_int64 f9g3_38 = f9_2 * (crypto_int64) g3_19;
crypto_int64 f9g4_19 = f9 * (crypto_int64) g4_19;
crypto_int64 f9g5_38 = f9_2 * (crypto_int64) g5_19;
crypto_int64 f9g6_19 = f9 * (crypto_int64) g6_19;
crypto_int64 f9g7_38 = f9_2 * (crypto_int64) g7_19;
crypto_int64 f9g8_19 = f9 * (crypto_int64) g8_19;
crypto_int64 f9g9_38 = f9_2 * (crypto_int64) g9_19;
crypto_int64 h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
crypto_int64 h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
crypto_int64 h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
crypto_int64 h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;
crypto_int64 h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;
crypto_int64 h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19;
crypto_int64 h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38;
crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19;
crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38;
crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ;
crypto_int64 carry0;
crypto_int64 carry1;
crypto_int64 carry2;
crypto_int64 carry3;
crypto_int64 carry4;
crypto_int64 carry5;
crypto_int64 carry6;
crypto_int64 carry7;
crypto_int64 carry8;
crypto_int64 carry9;
/*
|h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
|h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
*/
carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
/* |h0| <= 2^25 */
/* |h4| <= 2^25 */
/* |h1| <= 1.71*2^59 */
/* |h5| <= 1.71*2^59 */
carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
/* |h1| <= 2^24; from now on fits into int32 */
/* |h5| <= 2^24; from now on fits into int32 */
/* |h2| <= 1.41*2^60 */
/* |h6| <= 1.41*2^60 */
carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
/* |h2| <= 2^25; from now on fits into int32 unchanged */
/* |h6| <= 2^25; from now on fits into int32 unchanged */
/* |h3| <= 1.71*2^59 */
/* |h7| <= 1.71*2^59 */
carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
/* |h3| <= 2^24; from now on fits into int32 unchanged */
/* |h7| <= 2^24; from now on fits into int32 unchanged */
/* |h4| <= 1.72*2^34 */
/* |h8| <= 1.41*2^60 */
carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
/* |h4| <= 2^25; from now on fits into int32 unchanged */
/* |h8| <= 2^25; from now on fits into int32 unchanged */
/* |h5| <= 1.01*2^24 */
/* |h9| <= 1.71*2^59 */
carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
/* |h9| <= 2^24; from now on fits into int32 unchanged */
/* |h0| <= 1.1*2^39 */
carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
/* |h0| <= 2^25; from now on fits into int32 unchanged */
/* |h1| <= 1.01*2^24 */
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
h[5] = h5;
h[6] = h6;
h[7] = h7;
h[8] = h8;
h[9] = h9;
}

View File

@@ -1,45 +0,0 @@
#include "fe.h"
/*
h = -f
Preconditions:
|f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
Postconditions:
|h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
*/
void fe_neg(fe h,const fe f)
{
crypto_int32 f0 = f[0];
crypto_int32 f1 = f[1];
crypto_int32 f2 = f[2];
crypto_int32 f3 = f[3];
crypto_int32 f4 = f[4];
crypto_int32 f5 = f[5];
crypto_int32 f6 = f[6];
crypto_int32 f7 = f[7];
crypto_int32 f8 = f[8];
crypto_int32 f9 = f[9];
crypto_int32 h0 = -f0;
crypto_int32 h1 = -f1;
crypto_int32 h2 = -f2;
crypto_int32 h3 = -f3;
crypto_int32 h4 = -f4;
crypto_int32 h5 = -f5;
crypto_int32 h6 = -f6;
crypto_int32 h7 = -f7;
crypto_int32 h8 = -f8;
crypto_int32 h9 = -f9;
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
h[5] = h5;
h[6] = h6;
h[7] = h7;
h[8] = h8;
h[9] = h9;
}

View File

@@ -1,13 +0,0 @@
#include "fe.h"
void fe_pow22523(fe out,const fe z)
{
fe t0;
fe t1;
fe t2;
int i;
#include "pow22523.h"
return;
}

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