├── .gitignore
├── COPYING
├── README.md
├── WebSMSAPI
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── de
│ │ └── ub0r
│ │ └── android
│ │ └── websms
│ │ └── connector
│ │ └── common
│ │ ├── Base64Coder.java
│ │ ├── BasicConnector.java
│ │ ├── BasicSMSLengthCalculator.java
│ │ ├── BuilderWrapper11.java
│ │ ├── CharacterTable.java
│ │ ├── CharacterTableSMSLengthCalculator.java
│ │ ├── Connector.java
│ │ ├── ConnectorCommand.java
│ │ ├── ConnectorPreferenceActivity.java
│ │ ├── ConnectorService.java
│ │ ├── ConnectorSpec.java
│ │ ├── FakeSocketFactory.java
│ │ ├── FakeTrustManager.java
│ │ ├── InfoActivity.java
│ │ ├── KnownFingerprintTrustManager.java
│ │ ├── Log.java
│ │ ├── SMSLengthCalculator.java
│ │ ├── Utils.java
│ │ ├── WebSMSException.java
│ │ ├── WebSMSNoNetworkException.java
│ │ └── package-info.java
│ └── res
│ ├── drawable-hdpi-v11
│ └── stat_notify_sms_pending.png
│ ├── drawable-hdpi-v9
│ └── stat_notify_sms_pending.png
│ ├── drawable-hdpi
│ ├── icon.png
│ └── stat_notify_sms_pending.png
│ ├── drawable-ldpi-v9
│ └── stat_notify_sms_pending.png
│ ├── drawable-mdpi-v11
│ └── stat_notify_sms_pending.png
│ ├── drawable-mdpi-v9
│ └── stat_notify_sms_pending.png
│ ├── drawable-mdpi
│ ├── icon.png
│ └── stat_notify_sms_pending.png
│ ├── drawable-xhdpi
│ ├── icon.png
│ └── stat_notify_sms_pending.png
│ ├── drawable
│ ├── icon.png
│ └── stat_notify_sms_pending.png
│ ├── values-cs
│ └── strings.xml
│ ├── values-de
│ └── strings.xml
│ ├── values-fr
│ └── strings.xml
│ ├── values-hu
│ └── strings.xml
│ ├── values-it
│ └── strings.xml
│ ├── values-pt
│ └── strings.xml
│ ├── values-ro
│ └── strings.xml
│ ├── values-ru
│ └── strings.xml
│ ├── values-sk
│ └── strings.xml
│ ├── values-tr
│ └── strings.xml
│ └── values
│ └── strings.xml
├── build.gradle
├── doc
├── DeveloperFAQ.md
├── DeveloperHelp.md
└── sequence.png
├── hi-res
├── promo.png
├── promo.xcf
├── websms-connector-icon-512x512.png
├── websms-connector-icon-512x512_white.png
└── websms-connector-icon.svgz
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | gen
3 | .ant-targets-build.xml
4 | local.properties
5 | build.properties
6 | *.zip
7 | *.jar
8 | *.swp
9 | .gradle
10 | /local.properties
11 | /.idea/workspace.xml
12 | .DS_Store
13 | build
14 | *.iml
15 | gradle
16 | gradlew
17 | .idea
18 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Discontinued
2 |
3 | This app is discontinued and removed from all distribution channels.
4 |
5 | # General
6 |
7 | This is the API to build connectors for [websms][1].
8 | Please see one of the open source connectors to get an idea how to use the API.
9 | A very good example fot the use of BasicConnector with a very straight forward API is [cherry-sms][2].
10 | Check out the [o2 connector][3] to get an idea of a connector implementing the base class Connector and parsing a full website.
11 |
12 | ## How to build
13 |
14 | There are two ways to build a connector with this websms-api.
15 |
16 | ### Android-Studio / gradle / maven
17 |
18 | Add the websms-api maven repository to your build.gradle and simply reference the remote dependency.
19 | There is no need to check out/ clone the api manually.
20 |
21 | repositories {
22 | maven {
23 | url 'https://raw.githubusercontent.com/felixb/mvn-repo/master/'
24 | }
25 | mavenCentral()
26 | }
27 |
28 | dependencies {
29 | compile 'de.ub0r.android.websms.connector.common:WebSMSAPI:1.1'
30 | }
31 |
32 | You can see it in full details in the [cherry-sms connector's code base][2].
33 | In maven just in add the dependency like this.
34 |
35 |
36 | de.ub0r.android.websms.connector.common
37 | WebSMSAPI
38 | {latest.version}
39 | jar
40 |
41 |
42 | ### Eclipse / ant
43 |
44 | Please clone this git repo and check out the tag `build-env-eclipse`.
45 | You'll need to import this eclipse project and reference it as library project in your connector.
46 |
47 | ## Further reading
48 |
49 | * [Developer Help][4]
50 | * [Developer FAQ][5]
51 |
52 | [1]: http://github.com/felixb/websms/
53 | [2]: https://github.com/felixb/websms-connector-cherrysms/
54 | [3]: https://github.com/lmb/websms-connector-o2/
55 | [4]: https://github.com/felixb/websms-api/blob/master/doc/DeveloperHelp.md
56 | [5]: https://github.com/felixb/websms-api/blob/master/doc/DeveloperFAQ.md
57 |
--------------------------------------------------------------------------------
/WebSMSAPI/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/WebSMSAPI/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | }
5 | dependencies {
6 | classpath 'com.android.tools.build:gradle:1.0.1'
7 | }
8 | }
9 | apply plugin: 'com.android.library'
10 |
11 | repositories {
12 | mavenCentral()
13 | }
14 |
15 | android {
16 | compileSdkVersion 19
17 | buildToolsVersion '21.1.2'
18 |
19 | defaultConfig {
20 | minSdkVersion 5
21 | targetSdkVersion 19
22 | }
23 | }
24 |
25 | apply plugin: 'maven'
26 | apply plugin: 'signing'
27 |
28 | configurations {
29 | archives {
30 | extendsFrom configurations.default
31 | }
32 | }
33 |
34 | signing {
35 | required { has("release") && gradle.taskGraph.hasTask("uploadArchives") }
36 | sign configurations.archives
37 | }
38 |
39 | afterEvaluate { project ->
40 |
41 | uploadArchives {
42 | def user = null
43 | def repo = null
44 | 'git remote -v'.execute(null, project.projectDir).getText().find('.*?git@github.com[:/](.*?)/(.*?)(.git)? .*?') {
45 | match ->
46 | user = match[1]
47 | repo = match[2]
48 | }
49 |
50 | def githubUrl = 'https://api.github.com/repos/' + user + '/' + repo;
51 | if (System.getenv().GITHUB_TOKEN) {
52 | githubUrl += '?access_token=' + System.getenv().GITHUB_TOKEN
53 | }
54 | def repoInfo = new groovy.json.JsonSlurper().parseText(new URL(githubUrl).getText())
55 |
56 | def android_manifest = new XmlParser(false, false).
57 | parseText(new File(project.projectDir, 'src/main/AndroidManifest.xml').getText())
58 | def versionName = android_manifest.'@android:versionName'
59 | def package_name = android_manifest.'@package'
60 | def artifact_id = repo.toLowerCase()
61 | project.version = versionName
62 | project.group = package_name
63 |
64 | configuration = configurations.archives
65 | repositories.mavenDeployer {
66 | // beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
67 |
68 | repository(url: "file:///tmp/websms-api/")
69 |
70 | pom.project {
71 | name repo
72 | packaging 'jar'
73 | description repoInfo.description
74 | url repoInfo.html_url
75 |
76 | scm {
77 | url repoInfo.git_url
78 | connection repoInfo.git_url
79 | developerConnection repoInfo.ssh_url
80 | }
81 |
82 | licenses {
83 | license {
84 | name 'The Apache Software License, Version 2.0'
85 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
86 | distribution 'repo'
87 | }
88 | }
89 |
90 | developers {
91 | developer {
92 | id user
93 | name 'Felix Bechstein'
94 | email 'f@ub0r.de'
95 | }
96 | }
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/Base64Coder.java:
--------------------------------------------------------------------------------
1 | package de.ub0r.android.websms.connector.common;
2 |
3 | /**
4 | * A Base64 Encoder/Decoder.
5 | *
6 | * This class is used to encode and decode data in Base64 format as described in RFC 1521.
7 | *
8 | * This is "Open Source" software and released under the GNU/LGPL license.
10 | * It is provided "as is" without warranty of any kind.
11 | * Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.
12 | * Home page: www.source-code.biz
13 | *
14 | * Version history:
15 | * 2003-07-22 Christian d'Heureuse (chdh): Module created.
16 | * 2005-08-11 chdh: Lincense changed from GPL to LGPL.
17 | * 2006-11-21 chdh:
18 | * Method encode(String) renamed to encodeString(String).
19 | * Method decode(String) renamed to decodeString(String).
20 | * New method encode(byte[],int) added.
21 | * New method decode(String) added.
22 | */
23 | public final class Base64Coder {
24 |
25 | /** Mapping table from 6-bit nibbles to Base64 characters. */
26 | private static char[] map1 = new char[64];
27 | static {
28 | int i = 0;
29 | for (char c = 'A'; c <= 'Z'; c++) {
30 | map1[i++] = c;
31 | }
32 | for (char c = 'a'; c <= 'z'; c++) {
33 | map1[i++] = c;
34 | }
35 | for (char c = '0'; c <= '9'; c++) {
36 | map1[i++] = c;
37 | }
38 | map1[i++] = '+';
39 | map1[i++] = '/';
40 | }
41 |
42 | /** Mapping table from Base64 characters to 6-bit nibbles. */
43 | private static byte[] map2 = new byte[128];
44 | static {
45 | for (int i = 0; i < map2.length; i++) {
46 | map2[i] = -1;
47 | }
48 | for (int i = 0; i < 64; i++) {
49 | map2[map1[i]] = (byte) i;
50 | }
51 | }
52 |
53 | /**
54 | * Encodes a string into Base64 format. No blanks or line breaks are inserted.
55 | *
56 | * @param s
57 | * a String to be encoded.
58 | * @return A String with the Base64 encoded data.
59 | */
60 | public static String encodeString(final String s) {
61 | return new String(encode(s.getBytes()));
62 | }
63 |
64 | /**
65 | * Encodes a byte array into Base64 format. No blanks or line breaks are inserted.
66 | *
67 | * @param in
68 | * an array containing the data bytes to be encoded.
69 | * @return A character array with the Base64 encoded data.
70 | */
71 | public static char[] encode(final byte[] in) {
72 | return encode(in, in.length);
73 | }
74 |
75 | /**
76 | * Encodes a byte array into Base64 format. No blanks or line breaks are inserted.
77 | *
78 | * @param in
79 | * an array containing the data bytes to be encoded.
80 | * @param iLen
81 | * number of bytes to process in in
.
82 | * @return A character array with the Base64 encoded data.
83 | */
84 | public static char[] encode(final byte[] in, final int iLen) {
85 | int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
86 | int oLen = ((iLen + 2) / 3) * 4; // output length including padding
87 | char[] out = new char[oLen];
88 | int ip = 0;
89 | int op = 0;
90 | while (ip < iLen) {
91 | int i0 = in[ip++] & 0xff;
92 | int i1 = ip < iLen ? in[ip++] & 0xff : 0;
93 | int i2 = ip < iLen ? in[ip++] & 0xff : 0;
94 | int o0 = i0 >>> 2;
95 | int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
96 | int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
97 | int o3 = i2 & 0x3F;
98 | out[op++] = map1[o0];
99 | out[op++] = map1[o1];
100 | out[op] = op < oDataLen ? map1[o2] : '=';
101 | op++;
102 | out[op] = op < oDataLen ? map1[o3] : '=';
103 | op++;
104 | }
105 | return out;
106 | }
107 |
108 | /**
109 | * Decodes a string from Base64 format.
110 | *
111 | * @param s
112 | * a Base64 String to be decoded.
113 | * @return A String containing the decoded data.
114 | */
115 | public static String decodeString(final String s) {
116 | return new String(decode(s));
117 | }
118 |
119 | /**
120 | * Decodes a byte array from Base64 format.
121 | *
122 | * @param s
123 | * a Base64 String to be decoded.
124 | * @return An array containing the decoded data bytes.
125 | */
126 | public static byte[] decode(final String s) {
127 | return decode(s.toCharArray());
128 | }
129 |
130 | /**
131 | * Decodes a byte array from Base64 format. No blanks or line breaks are allowed within the
132 | * Base64 encoded data.
133 | *
134 | * @param in
135 | * a character array containing the Base64 encoded data.
136 | * @return An array containing the decoded data bytes.
137 | */
138 | public static byte[] decode(final char[] in) {
139 | int iLen = in.length;
140 | if (iLen % 4 != 0) {
141 | throw new IllegalArgumentException(
142 | "Length of Base64 encoded input string is not a multiple of 4.");
143 | }
144 | while (iLen > 0 && in[iLen - 1] == '=') {
145 | iLen--;
146 | }
147 | int oLen = (iLen * 3) / 4;
148 | byte[] out = new byte[oLen];
149 | int ip = 0;
150 | int op = 0;
151 | while (ip < iLen) {
152 | int i0 = in[ip++];
153 | int i1 = in[ip++];
154 | int i2 = ip < iLen ? in[ip++] : 'A';
155 | int i3 = ip < iLen ? in[ip++] : 'A';
156 | if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) {
157 | throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
158 | }
159 | int b0 = map2[i0];
160 | int b1 = map2[i1];
161 | int b2 = map2[i2];
162 | int b3 = map2[i3];
163 | if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) {
164 | throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
165 | }
166 | int o0 = (b0 << 2) | (b1 >>> 4);
167 | int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
168 | int o2 = ((b2 & 3) << 6) | b3;
169 | out[op++] = (byte) o0;
170 | if (op < oLen) {
171 | out[op++] = (byte) o1;
172 | }
173 | if (op < oLen) {
174 | out[op++] = (byte) o2;
175 | }
176 | }
177 | return out;
178 | }
179 |
180 | /**
181 | * Dummy constructor.
182 | */
183 | private Base64Coder() {
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/BasicConnector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import java.io.IOException;
22 | import java.net.HttpURLConnection;
23 | import java.util.ArrayList;
24 |
25 | import org.apache.http.Header;
26 | import org.apache.http.HttpEntity;
27 | import org.apache.http.HttpResponse;
28 | import org.apache.http.message.BasicNameValuePair;
29 |
30 | import android.content.Context;
31 | import android.content.Intent;
32 | import android.text.TextUtils;
33 | import de.ub0r.android.websms.connector.common.Utils.HttpOptions;
34 |
35 | /**
36 | * AsyncTask to manage IO to a basic WebAPI.
37 | *
38 | * @author flx
39 | */
40 | public abstract class BasicConnector extends Connector {
41 | /** Tag for output. */
42 | private static final String TAG = "bcon";
43 | /** User Agent. */
44 | private static final String USERAGENT = // .
45 | "curl/7.21.3 (x86_64-pc-linux-gnu) "
46 | + "libcurl/7.21.3 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18";
47 |
48 | /**
49 | * Get the URL used for sending messages.
50 | *
51 | * @param context
52 | * {@link Context}
53 | * @param d
54 | * {@link ArrayList} of arguments
55 | * @return gateway URL for sending
56 | */
57 | protected String getUrlSend(final Context context,
58 | final ArrayList d) {
59 | return this.getUrlSend(d);
60 | }
61 |
62 | /**
63 | * Get the URL used for sending messages.
64 | *
65 | * @param d
66 | * {@link ArrayList} of arguments
67 | * @return gateway URL for sending
68 | */
69 | @Deprecated
70 | protected String getUrlSend(final ArrayList d) {
71 | return null;
72 | }
73 |
74 | /**
75 | * Get the URL used for getting balance.
76 | *
77 | * @param context
78 | * {@link Context}
79 | * @param d
80 | * {@link ArrayList} of arguments
81 | * @return gateway URL for balance update
82 | */
83 | protected String getUrlBalance(final Context context,
84 | final ArrayList d) {
85 | return this.getUrlBalance(d);
86 | }
87 |
88 | /**
89 | * Get the URL used for getting balance.
90 | *
91 | * @param d
92 | * {@link ArrayList} of arguments
93 | * @return gateway URL for balance update
94 | */
95 | @Deprecated
96 | protected String getUrlBalance(final ArrayList d) {
97 | return null;
98 | }
99 |
100 | /**
101 | * Get HTTP method used for transmitting data to the Service.
102 | *
103 | * @return true to use POST, false for GET; default implementation returns
104 | * true
105 | */
106 | protected boolean usePost(final ConnectorCommand command) {
107 | return true;
108 | }
109 |
110 | /**
111 | * Do HTTP basic auth.
112 | *
113 | * @return true to do HTTP basic auth
114 | */
115 | protected boolean useBasicAuth() {
116 | return false;
117 | }
118 |
119 | /** @return user agent */
120 | protected String getUserAgent() {
121 | return USERAGENT;
122 | }
123 |
124 | /**
125 | * Trust any SSL certificates.
126 | *
127 | * @return true to trust any SSL certificate, default implementation returns
128 | * false
129 | */
130 | protected boolean trustAllSLLCerts() {
131 | return false;
132 | }
133 |
134 | /**
135 | * Array of SHA-1 fingerprint hashes of trusted SSL certificates. Only this
136 | * certificates will be accepted as trusted.
137 | *
138 | * @return array of trusted SSL certificates
139 | */
140 | protected String[] trustedSSLCerts() {
141 | return null;
142 | }
143 |
144 | /**
145 | * Set encoding used for HTTP GET requests.
146 | *
147 | * @return encoding used for HTTP GET requests; default implementation uses
148 | * ISO-8859-15
149 | */
150 | protected String getEncoding() {
151 | return "ISO-8859-15";
152 | }
153 |
154 | /**
155 | * Set timeout for establishing a connection and waiting for a response from
156 | * the server.
157 | *
158 | * @return timeout; defaults to no timeout
159 | */
160 | protected int getTimeout() {
161 | return 0;
162 | }
163 |
164 | /**
165 | * Set maximum number of HTTP connections.
166 | *
167 | * @param context
168 | * {@link Context}
169 | * @param cs
170 | * {@link ConnectorSpec}
171 | * @return number of connections; defaults to system default
172 | */
173 | protected int getMaxHttpConnections(final Context context,
174 | final ConnectorSpec cs) {
175 | return 0;
176 | }
177 |
178 | /**
179 | * Set parameter name for username.
180 | *
181 | * @return API param for username
182 | */
183 | protected abstract String getParamUsername();
184 |
185 | /**
186 | * Set parameter name for password.
187 | *
188 | * @return API param for password
189 | */
190 | protected abstract String getParamPassword();
191 |
192 | /**
193 | * Set parameter name for recipients.
194 | *
195 | * @return API param for recipients
196 | */
197 | protected abstract String getParamRecipients();
198 |
199 | /**
200 | * Set paramteter name for text.
201 | *
202 | * @return API param for text
203 | */
204 | protected abstract String getParamText();
205 |
206 | /**
207 | * Set paramter name for sender id.
208 | *
209 | * @return API param for sender
210 | */
211 | protected abstract String getParamSender();
212 |
213 | /**
214 | * Set parameter name for send later.
215 | *
216 | * @return API param for send later; default implementation returns null
217 | */
218 | protected String getParamSendLater() {
219 | return null;
220 | }
221 |
222 | /**
223 | * Set paramter name for selecting the sub connector.
224 | *
225 | * @return API param name for subconnector; default implementation returns
226 | * null
227 | */
228 | protected String getParamSubconnector() {
229 | return null;
230 | }
231 |
232 | /**
233 | * Set paramter name for sending message as flash sms.
234 | *
235 | * @return API param for flash type; default implementation returns null
236 | */
237 | protected String getParamFlash() {
238 | return null;
239 | }
240 |
241 | /**
242 | * Set username value.
243 | *
244 | * @param context
245 | * {@link Context}
246 | * @param command
247 | * {@link ConnectorCommand}
248 | * @param cs
249 | * {@link ConnectorSpec}
250 | * @return the username for authorization at the WebAPI.
251 | */
252 | protected abstract String getUsername(final Context context,
253 | final ConnectorCommand command, final ConnectorSpec cs);
254 |
255 | /**
256 | * Set password value.
257 | *
258 | * @param context
259 | * {@link Context}
260 | * @param command
261 | * {@link ConnectorCommand}
262 | * @param cs
263 | * {@link ConnectorSpec}
264 | * @return the password for authorization at the WebAPI.
265 | */
266 | protected abstract String getPassword(final Context context,
267 | final ConnectorCommand command, final ConnectorSpec cs);
268 |
269 | /**
270 | * Set selected sub connector. Get used subconnector. Default implementation
271 | * returns just the param subcon.
272 | *
273 | * @param subcon
274 | * id of selected subconnector
275 | * @return value for subconnector
276 | */
277 | protected String getSubconnector(final String subcon) {
278 | return subcon;
279 | }
280 |
281 | /**
282 | * Set message's text. Default implementation returns just the given text.
283 | *
284 | * @param text
285 | * message body
286 | * @return value for text
287 | */
288 | protected String getText(final String text) {
289 | return text;
290 | }
291 |
292 | /**
293 | * Set sender id value.
294 | *
295 | * @param context
296 | * {@link Context}
297 | * @param command
298 | * {@link ConnectorCommand}
299 | * @param cs
300 | * {@link ConnectorSpec}
301 | * @return value for sender.
302 | */
303 | protected abstract String getSender(final Context context,
304 | final ConnectorCommand command, final ConnectorSpec cs);
305 |
306 | /**
307 | * Set recipients value.
308 | *
309 | * @param command
310 | * {@link ConnectorCommand}
311 | * @return value for recipients.
312 | */
313 | protected abstract String getRecipients(final ConnectorCommand command);
314 |
315 | /**
316 | * Set send later value. Default implementation just returns the plain
317 | * value.
318 | *
319 | * @param sendLater
320 | * send later
321 | * @return value for send later
322 | */
323 | protected String getSendLater(final long sendLater) {
324 | return String.valueOf(sendLater);
325 | }
326 |
327 | /**
328 | * Parse response. Implement this message to parse the returned text from
329 | * HTTP server.
330 | *
331 | * @param context
332 | * {@link Context}
333 | * @param command
334 | * {@link ConnectorCommand}
335 | * @param cs
336 | * {@link ConnectorSpec}
337 | * @param htmlText
338 | * HTTP response body
339 | */
340 | protected abstract void parseResponse(final Context context,
341 | final ConnectorCommand command, final ConnectorSpec cs,
342 | final String htmlText);
343 |
344 | /**
345 | * Parse HTTP response code. Default implementation throws
346 | * {@link WebSMSException} if response != HTTP_OK.
347 | *
348 | * @param context
349 | * {@link Context}
350 | * @param response
351 | * {@link HttpResponse}
352 | */
353 | protected void parseResponseCode(final Context context,
354 | final HttpResponse response) {
355 | final int resp = response.getStatusLine().getStatusCode();
356 | if (resp != HttpURLConnection.HTTP_OK) {
357 | Log.e(TAG, "HTTP Status Line: "
358 | + response.getStatusLine().toString());
359 | Log.e(TAG, "HTTP Headers:");
360 | for (Header h : response.getAllHeaders()) {
361 | Log.e(TAG, h.getName() + ": " + h.getValue());
362 | }
363 | try {
364 | final String htmlText = Utils.stream2str(
365 | response.getEntity().getContent()).trim();
366 | Log.e(TAG, "HTTP Body:");
367 | for (String l : htmlText.split("\n")) {
368 | Log.e(TAG, l);
369 | }
370 | } catch (Exception e) {
371 | Log.w(TAG, "error getting content", e);
372 | }
373 | throw new WebSMSException(context, R.string.error_http,
374 | String.valueOf(resp));
375 | }
376 | }
377 |
378 | /**
379 | * Add some {@link BasicNameValuePair}s to arguments before calling the web
380 | * service.
381 | *
382 | * @param context
383 | * {@link Context}
384 | * @param command
385 | * {@link ConnectorCommand}
386 | * @param cs
387 | * {@link ConnectorSpec}
388 | * @param d
389 | * {@link ArrayList} of arguments
390 | */
391 | protected void addExtraArgs(final Context context,
392 | final ConnectorCommand command, final ConnectorSpec cs,
393 | final ArrayList d) {
394 | // default implementation does nothing
395 | }
396 |
397 | /**
398 | * Add a HTTP entity and push it with HTTP POST.
399 | *
400 | * @param context
401 | * {@link Context}
402 | * @param command
403 | * {@link ConnectorCommand}
404 | * @param cs
405 | * {@link ConnectorSpec}
406 | * @return {@link HttpEntity}
407 | */
408 | protected HttpEntity addHttpEntity(final Context context,
409 | final ConnectorCommand command, final ConnectorSpec cs) {
410 | return null;
411 | }
412 |
413 | /**
414 | * Send data. This method actually calls the web service with all set
415 | * parameters. The response is parsed in custom methods implemented by the
416 | * actual connector.
417 | *
418 | * @param context
419 | * Context
420 | * @param command
421 | * ConnectorCommand
422 | * @throws IOException
423 | * IOException
424 | */
425 | private void sendData(final Context context, final ConnectorCommand command)
426 | throws IOException {
427 | // check network availability
428 | if (!Utils.isNetworkAvailable(context)) {
429 | throw new WebSMSNoNetworkException(context);
430 | }
431 | HttpOptions o = new HttpOptions(this.getEncoding());
432 | o.userAgent = this.getUserAgent();
433 | // get Connection
434 | final ConnectorSpec cs = this.getSpec(context);
435 | ArrayList d = new ArrayList();
436 | final String text = command.getText();
437 | if (text != null && text.length() > 0) {
438 | o.url = this.getUrlSend(context, d);
439 | final String subCon = command.getSelectedSubConnector();
440 | addParam(d, this.getParamText(), this.getText(text));
441 | addParam(d, this.getParamRecipients(), this.getRecipients(command));
442 |
443 | if (command.getFlashSMS()) {
444 | addParam(d, this.getParamSubconnector(), this.getParamFlash());
445 | } else {
446 | addParam(d, this.getParamSubconnector(),
447 | this.getSubconnector(subCon));
448 | }
449 |
450 | final String customSender = command.getCustomSender();
451 | if (customSender == null) {
452 | addParam(d, this.getParamSender(),
453 | this.getSender(context, command, cs));
454 | } else {
455 | addParam(d, this.getParamSender(), customSender);
456 | }
457 | final long sendLater = command.getSendLater();
458 | final String pSendLater = this.getParamSendLater();
459 | if (sendLater > 0 && pSendLater != null) {
460 | d.add(new BasicNameValuePair(pSendLater, this
461 | .getSendLater(sendLater)));
462 | }
463 | } else {
464 | o.url = this.getUrlBalance(context, d);
465 | }
466 |
467 | if (!this.useBasicAuth()) {
468 | addParam(d, this.getParamUsername(),
469 | this.getUsername(context, command, cs));
470 | addParam(d, this.getParamPassword(),
471 | this.getPassword(context, command, cs));
472 | }
473 |
474 | this.addExtraArgs(context, command, cs, d);
475 |
476 | final String encoding = this.getEncoding();
477 | if (!this.usePost(command)) {
478 | o.url = Utils.httpGetParams(o.url, d, encoding);
479 | d = null;
480 | } else {
481 | o.postData = this.addHttpEntity(context, command, cs);
482 | if (o.postData == null) {
483 | o.addFormParameter(d);
484 | } else {
485 | o.url = Utils.httpGetParams(o.url, d, encoding);
486 | d = null;
487 | }
488 | }
489 | if (this.useBasicAuth()) {
490 | o.addBasicAuthHeader(this.getUsername(context, command, cs),
491 | this.getPassword(context, command, cs));
492 | }
493 |
494 | o.trustAll = this.trustAllSLLCerts();
495 | o.knownFingerprints = this.trustedSSLCerts();
496 |
497 | o.timeout = this.getTimeout();
498 | o.maxConnections = this.getMaxHttpConnections(context, cs);
499 |
500 | Log.d(TAG, "HTTP REQUEST: " + o.url);
501 | HttpResponse response = Utils.getHttpClient(o);
502 |
503 | this.parseResponseCode(context, response);
504 | final String htmlText = Utils.stream2str(
505 | response.getEntity().getContent()).trim();
506 | Log.d(TAG, "HTTP RESPONSE: " + htmlText);
507 | this.parseResponse(context, command, cs, htmlText);
508 | }
509 |
510 | /**
511 | * {@inheritDoc}
512 | */
513 | @Override
514 | protected void doUpdate(final Context context, final Intent intent)
515 | throws IOException {
516 | this.sendData(context, new ConnectorCommand(intent));
517 | }
518 |
519 | /**
520 | * {@inheritDoc}
521 | */
522 | @Override
523 | protected void doSend(final Context context, final Intent intent)
524 | throws IOException {
525 | this.sendData(context, new ConnectorCommand(intent));
526 | }
527 |
528 | /**
529 | * Add a {@link BasicNameValuePair} to a {@link ArrayList}.
530 | *
531 | * @param d
532 | * {@link ArrayList} of {@link BasicNameValuePair}
533 | * @param n
534 | * name
535 | * @param v
536 | * value
537 | * @return the list
538 | */
539 | protected static ArrayList addParam(
540 | final ArrayList d, final String n,
541 | final String v) {
542 | if (!TextUtils.isEmpty(n)) {
543 | d.add(new BasicNameValuePair(n, v));
544 | }
545 | return d;
546 | }
547 | }
548 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/BasicSMSLengthCalculator.java:
--------------------------------------------------------------------------------
1 | package de.ub0r.android.websms.connector.common;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | /**
7 | * A simple implementation of an SMSLengthCalculator. Provide an array of
8 | * message lengths representing the number of characters that can be added each
9 | * time before an additional SMS will be used.
10 | *
11 | * For example: [160, 149] - here the first 160 characters is just one SMS, the
12 | * next 149 (for a total of 309) would constitute 2 messages.
13 | *
14 | * Note that the final value implicitly repeats, so the above example is
15 | * actually [160, 149, 149, ...].
16 | *
17 | * If the provider has a maximum message length and this is set correctly the
18 | * repeating message length will not be an issue.
19 | *
20 | * @author Fintan Fairmichael
21 | *
22 | */
23 | public class BasicSMSLengthCalculator implements SMSLengthCalculator {
24 | private static final long serialVersionUID = -2841752540084364776L;
25 |
26 | private final int[] messageLengths;
27 |
28 | /**
29 | *
30 | * @param messageLengths
31 | * the message lengths representing the number of characters that
32 | * can be added at each point before an additional message is
33 | * required
34 | */
35 | public BasicSMSLengthCalculator(final int[] messageLengths) {
36 | this.messageLengths = messageLengths;
37 | }
38 |
39 | private final int messageLength(final int index) {
40 | if (index >= this.messageLengths.length) {
41 | return this.messageLengths[this.messageLengths.length - 1];
42 | } else {
43 | // Last message length repeats, if necessary
44 | return this.messageLengths[index];
45 | }
46 | }
47 |
48 | @Override
49 | public int[] calculateLength(final String messageBody,
50 | final boolean use7bitOnly) {
51 | // Currently ignoring use7bitOnly param
52 | final int length = messageBody.length();
53 |
54 | int numberSMSRequired = 0;
55 | int charsRemaining = length;
56 | int remainingTilNextSMS = 0;
57 |
58 | while (true) {
59 | final int messageLength = this.messageLength(numberSMSRequired);
60 | numberSMSRequired++;
61 | if (messageLength >= charsRemaining) {
62 | remainingTilNextSMS = messageLength - charsRemaining;
63 | break;
64 | }
65 | charsRemaining -= messageLength;
66 | }
67 | return new int[] { numberSMSRequired, length, remainingTilNextSMS, 0 };
68 | }
69 |
70 | // Parcel stuff
71 | private BasicSMSLengthCalculator(final Parcel parcel) {
72 | this(parcel.createIntArray());
73 | }
74 |
75 | public int describeContents() {
76 | return 0;
77 | }
78 |
79 | public void writeToParcel(final Parcel out, final int flags) {
80 | out.writeIntArray(this.messageLengths);
81 | }
82 |
83 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
84 | public BasicSMSLengthCalculator createFromParcel(final Parcel in) {
85 | return new BasicSMSLengthCalculator(in);
86 | }
87 |
88 | public BasicSMSLengthCalculator[] newArray(final int size) {
89 | return new BasicSMSLengthCalculator[size];
90 | }
91 | };
92 | }
93 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/BuilderWrapper11.java:
--------------------------------------------------------------------------------
1 | package de.ub0r.android.websms.connector.common;
2 |
3 | import android.app.AlertDialog.Builder;
4 | import android.content.Context;
5 |
6 | /**
7 | * Get a {@link Builder} with theme support.
8 | *
9 | * @author flx
10 | */
11 | final class BuilderWrapper11 {
12 | /**
13 | * Hide constructor.
14 | */
15 | private BuilderWrapper11() {
16 | // nothing to do
17 | }
18 |
19 | /**
20 | * Get a {@link Builder}.
21 | *
22 | * @param context
23 | * {@link Context}
24 | * @param theme
25 | * theme
26 | * @return {@link Builder}
27 | */
28 | static Builder getBuilder(final Context context, final int theme) {
29 | return new Builder(context, theme);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/CharacterTable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009-2012 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import java.util.HashMap;
22 | import java.util.Map;
23 |
24 | import android.os.Bundle;
25 |
26 | /**
27 | * Character table is replacing unwanted characters with well behaving ones.
28 | *
29 | * @author Thomas Pilarski , Felix Bechstein
30 | *
31 | */
32 | public final class CharacterTable {
33 |
34 | /** Mapping. */
35 | private final Map mMap;
36 |
37 | /**
38 | * Default constructor.
39 | *
40 | * @param map
41 | * {@link Map} holding bad and good characters
42 | */
43 | public CharacterTable(final Map map) {
44 | // this.mMap = new HashMap(map.size());
45 | // this.mMap.putAll(map);
46 | this.mMap = map;
47 | }
48 |
49 | /**
50 | * Import from {@link Bundle} constructor.
51 | *
52 | * @param b
53 | * {@link Bundle} holding bad and good characters
54 | */
55 | public CharacterTable(final Bundle b) {
56 | this.mMap = new HashMap(b.size());
57 | for (String k : b.keySet()) {
58 | this.mMap.put(k, b.getString(k));
59 | }
60 | }
61 |
62 | /**
63 | * Encode {@link String}.
64 | *
65 | * @param str
66 | * {@link String}
67 | * @return encoded {@link String}
68 | */
69 | public String encodeString(final String str) {
70 | final int l = str.length();
71 | final StringBuffer strb = new StringBuffer(l);
72 | for (int i = 0; i < l; i++) {
73 | String s = str.substring(i, i + 1);
74 | String chr = this.mMap.get(s);
75 | if (chr == null) {
76 | strb.append(s);
77 | } else {
78 | strb.append(chr);
79 | }
80 | }
81 | return strb.toString();
82 | }
83 |
84 | /**
85 | * @return inner {@link Map}
86 | */
87 | public Map getMap() {
88 | return this.mMap;
89 | }
90 |
91 | /**
92 | * @return inner {@link Map} as {@link Bundle}
93 | */
94 | public Bundle getBundle() {
95 | final Bundle b = new Bundle(this.mMap.size());
96 | for (String k : this.mMap.keySet()) {
97 | b.putString(k, this.mMap.get(k));
98 | }
99 | return b;
100 | }
101 |
102 | }
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/CharacterTableSMSLengthCalculator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009-2012 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import android.os.Bundle;
22 | import android.os.Parcel;
23 | import android.os.Parcelable;
24 | import android.telephony.SmsMessage;
25 |
26 | /**
27 | * This implementation of an SMSLengthCalculator replaces bad characters with a
28 | * {@link CharacterTable} before calculating the message length. This class does
29 | * need at least an Android API 4.
30 | *
31 | * @author Felix Bechstein
32 | */
33 | public class CharacterTableSMSLengthCalculator implements SMSLengthCalculator {
34 | /** Automatic generated serial version UID. */
35 | private static final long serialVersionUID = 750570280586096152L;
36 |
37 | /** {@link CharacterTable} used for replacing bad chars. */
38 | private final CharacterTable mCT;
39 |
40 | /**
41 | * @param table
42 | * {@link CharacterTable} used for replacing bad chars
43 | */
44 | public CharacterTableSMSLengthCalculator(final CharacterTable table) {
45 | this.mCT = table;
46 | }
47 |
48 | /**
49 | * @param b
50 | * {@link Bundle} for creating a {@link CharacterTable}
51 | */
52 | public CharacterTableSMSLengthCalculator(final Bundle b) {
53 | this.mCT = new CharacterTable(b);
54 | }
55 |
56 | @Override
57 | public int[] calculateLength(final String messageBody,
58 | final boolean use7bitOnly) {
59 | return SmsMessage.calculateLength(this.mCT.encodeString(messageBody),
60 | use7bitOnly);
61 | }
62 |
63 | // Parcel stuff
64 | private CharacterTableSMSLengthCalculator(final Parcel parcel) {
65 | this(parcel.readBundle());
66 | }
67 |
68 | public int describeContents() {
69 | return 0;
70 | }
71 |
72 | public void writeToParcel(final Parcel out, final int flags) {
73 | out.writeBundle(this.mCT.getBundle());
74 | }
75 |
76 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
77 | public CharacterTableSMSLengthCalculator createFromParcel(
78 | final Parcel in) {
79 | return new CharacterTableSMSLengthCalculator(in);
80 | }
81 |
82 | public CharacterTableSMSLengthCalculator[] newArray(final int size) {
83 | return new CharacterTableSMSLengthCalculator[size];
84 | }
85 | };
86 | }
87 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/Connector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import java.io.IOException;
22 |
23 | import android.app.Activity;
24 | import android.content.BroadcastReceiver;
25 | import android.content.Context;
26 | import android.content.Intent;
27 | import android.os.Bundle;
28 | import android.widget.Toast;
29 |
30 | /**
31 | * Receives commands coming as broadcast from WebSMS.
32 | *
33 | * @author flx
34 | */
35 | public abstract class Connector extends BroadcastReceiver {
36 | /** Common Action prefix. */
37 | private static final String ACTION_PREFIX = "de.ub0r."
38 | + "android.websms.connector.";
39 |
40 | /** API version. */
41 | public static final int API_VERSION = 2;
42 |
43 | /**
44 | * Action to start a connector's Preference Activity.
45 | */
46 | public static final String ACTION_PREFS = ".PREFS";
47 |
48 | /**
49 | * Action to start a connector's {@link android.app.Service}. This should
50 | * include a {@link ConnectorCommand}: bootstrap.
51 | */
52 | public static final String ACTION_RUN_BOOTSTRAP = ".RUN_BOOTSTRAP";
53 |
54 | /**
55 | * Action to start a connector's {@link android.app.Service}. This should
56 | * include a {@link ConnectorCommand}: update.
57 | */
58 | public static final String ACTION_RUN_UPDATE = ".RUN_UPDATE";
59 |
60 | /**
61 | * Action to start a connector's {@link android.app.Service}. This should
62 | * include a {@link ConnectorCommand}: send.
63 | */
64 | public static final String ACTION_RUN_SEND = ".RUN_SEND";
65 |
66 | /** Broadcast Action requesting update of {@link ConnectorSpec}'s status. */
67 | public static final String ACTION_CONNECTOR_UPDATE = ACTION_PREFIX
68 | + "UPDATE";
69 |
70 | /**
71 | * Broadcast Action sending updated {@link ConnectorSpec} informations back
72 | * to WebSMS. This should include a {@link ConnectorSpec}.
73 | */
74 | public static final String ACTION_INFO = ACTION_PREFIX + "INFO";
75 |
76 | /**
77 | * Broadcast Action requesting to solve a captcha. Send
78 | * EXTRA_CAPTCHA_DRAWABLE and your {@link ConnectorSpec} with it.
79 | */
80 | public static final String ACTION_CAPTCHA_REQUEST = ACTION_PREFIX
81 | + "CAPTCHA_REQUEST";
82 | /**
83 | * Broadcast Action sending solved captcha back. The solved captcha will
84 | * come as EXTRA_CAPTCHA_SOLVED. If no Extra is given back, the user aborted
85 | * the activity.
86 | */
87 | public static final String ACTION_CAPTCHA_SOLVED = ".CAPTCHA_SOLVED";
88 |
89 | /**
90 | * Broadcast Action requesting to cancel a message.
91 | */
92 | public static final String ACTION_CANCEL = ACTION_PREFIX + "CANCEL";
93 |
94 | /**
95 | * Broadcast Action requesting to resend a message.
96 | */
97 | public static final String ACTION_RESEND = ACTION_PREFIX + "RESEND";
98 |
99 | /** Extra holding captcha as Drawable saved as Parcelable. */
100 | public static final String EXTRA_CAPTCHA_DRAWABLE = "captcha";
101 | /** Extra holding a message displayed to the user. */
102 | public static final String EXTRA_CAPTCHA_MESSAGE = "text";
103 | /** Extra holding the solved catpcha. */
104 | public static final String EXTRA_CAPTCHA_SOLVED = "solved";
105 |
106 | /** Internal {@link ConnectorSpec}. */
107 | private static ConnectorSpec connector = null;
108 |
109 | /** Sync access to connector. */
110 | protected static final Object SYNC_UPDATE = new Object();
111 |
112 | /**
113 | * This instance is ran by {@link ConnectorService} via
114 | * {@link ConnectorTask}.Each implementer of this class should register
115 | * here.
116 | */
117 | private static Connector instance = null;
118 |
119 | /**
120 | * @return single instance running all the IO in different thread.
121 | */
122 | protected static final Connector getInstance() {
123 | if (instance == null) {
124 | throw new WebSMSException("no running Connector available");
125 | }
126 | return instance;
127 | }
128 |
129 | /**
130 | * Register a {@link Connector} which should be ran to do all the IO in
131 | * different thread.
132 | *
133 | * @param receiver
134 | * {@link Connector}
135 | */
136 | protected static final void registerInstance(final Connector receiver) {
137 | instance = receiver;
138 | }
139 |
140 | /**
141 | * Initialize {@link ConnectorSpec}. This is only run once. Changing
142 | * properties should be set in updateSpec(). Implement this method to
143 | * register subconnectors and set up the connector. UpdateSpec() is called
144 | * later. There is no need to duplicate code. Default implementation does
145 | * nothing at all.
146 | *
147 | * @param context
148 | * {@link Context}
149 | * @return updated {@link ConnectorSpec}
150 | */
151 | protected ConnectorSpec initSpec(final Context context) {
152 | return new ConnectorSpec("noname");
153 | }
154 |
155 | /**
156 | * Update {@link ConnectorSpec}. Implement this method to return the
157 | * connectors status etc. Default implementation does nothing at all.
158 | *
159 | * @param context
160 | * {@link Context}
161 | * @param connectorSpec
162 | * {@link ConnectorSpec}
163 | * @return updated {@link ConnectorSpec}
164 | */
165 | protected ConnectorSpec updateSpec(final Context context,
166 | final ConnectorSpec connectorSpec) {
167 | return connectorSpec;
168 | }
169 |
170 | /**
171 | * Get {@link ConnectorSpec}. Initialize and update it if needed.
172 | *
173 | * @param context
174 | * {@link Context}
175 | * @return {@link ConnectorSpec}
176 | */
177 | protected final synchronized ConnectorSpec getSpec(final Context context) {
178 | synchronized (SYNC_UPDATE) {
179 | if (connector == null) {
180 | connector = this.initSpec(context);
181 | connector.setPackage(context.getPackageName());
182 | connector.setAPIVersion(API_VERSION);
183 | }
184 | return this.updateSpec(context, connector);
185 | }
186 | }
187 |
188 | /**
189 | * Flush everything known about the connector.
190 | */
191 | public static final void flushSpec() {
192 | synchronized (SYNC_UPDATE) {
193 | connector = null;
194 | }
195 | }
196 |
197 | /**
198 | * Send INFO Broadcast back to WebSMS. Call this method after updating your
199 | * status, changing balance and after processing a command.
200 | *
201 | * @param context
202 | * {@link Context}
203 | * @param specs
204 | * {@link ConnectorSpec}; if null, getSpec() is called to get
205 | * them
206 | * @param command
207 | * send back the {@link ConnectorCommand} which was done
208 | */
209 | protected final void sendInfo(final Context context,
210 | final ConnectorSpec specs, final ConnectorCommand command) {
211 | ConnectorSpec c = specs;
212 | if (c == null) {
213 | c = this.getSpec(context);
214 | }
215 | final Intent i = c.setToIntent(null);
216 | if (command != null) {
217 | command.setToIntent(i);
218 | }
219 | Log.d(this.getSpec(context).toString(), "-> bc: " + i.getAction());
220 | context.sendBroadcast(i);
221 | }
222 |
223 | /**
224 | * This default implementation will register the running {@link Connector}
225 | * to an external service. This {@link ConnectorService} will run a
226 | * {@link ConnectorTask} running the methods doBootstrap(), doUpdate() and
227 | * doSend() implemented above.
228 | *
229 | * @param context
230 | * {@link Context}
231 | * @param intent
232 | * {@link Intent}
233 | */
234 | @Override
235 | public void onReceive(final Context context, final Intent intent) {
236 | final ConnectorSpec specs = this.getSpec(context);
237 | final String tag = specs.toString();
238 | final String action = intent.getAction();
239 | Log.d(tag, "action: " + action);
240 | final String pkg = context.getPackageName();
241 | if (action == null) {
242 | return;
243 | }
244 | if (Connector.ACTION_CONNECTOR_UPDATE.equals(action)) {
245 | Log.d(tag, "got info request");
246 | this.sendInfo(context, null, null);
247 | // try {
248 | // this.setResultCode(Activity.RESULT_OK);
249 | // } catch (Exception e) {
250 | // Log.d(tag, "not an ordered boradcast: " + e.toString());
251 | // }
252 | } else if (action.equals(pkg + Connector.ACTION_CAPTCHA_SOLVED)) {
253 | Log.d(tag, "got solved captcha");
254 | final Bundle extras = intent.getExtras();
255 | if (extras == null) {
256 | this.gotSolvedCaptcha(context, null);
257 | } else {
258 | this.gotSolvedCaptcha(context, extras
259 | .getString(EXTRA_CAPTCHA_SOLVED));
260 | }
261 | try {
262 | this.setResultCode(Activity.RESULT_OK);
263 | } catch (Exception e) {
264 | Log.w(tag, "not an ordered boradcast: " + e.toString());
265 | }
266 | } else if (action.equals(pkg + Connector.ACTION_RUN_BOOTSTRAP)
267 | || action.equals(pkg + Connector.ACTION_RUN_UPDATE)
268 | || action.equals(pkg + Connector.ACTION_RUN_SEND)) {
269 | Log.d(tag, "got command");
270 | final ConnectorCommand command = ConnectorCommand.fromIntent(intent);
271 | final ConnectorSpec origSpecs = ConnectorSpec.fromIntent(intent);
272 | boolean ordered = true;
273 | if (action.equals(pkg + Connector.ACTION_RUN_UPDATE)) {
274 | ordered = false;
275 | }
276 | if (specs == null) {
277 | // skip disabled connector
278 | Log.w(tag, "specs=null");
279 | return;
280 | }
281 | if (!specs.hasStatus(ConnectorSpec.STATUS_ENABLED)) {
282 | if (ordered) {
283 | this.setResultCode(Activity.RESULT_CANCELED);
284 | }
285 | Log.w(tag, "connector disabled");
286 | return;
287 | }
288 | if (command == null) {
289 | // skip faulty commands
290 | Log.w(tag, "command=null");
291 | return;
292 | }
293 | if (command.getType() != ConnectorCommand.TYPE_SEND
294 | || (origSpecs != null && specs.equals(origSpecs))) {
295 | // command type is set.
296 | // if command == send: this receiver is the wanted one.
297 | registerInstance(this); // this instance will be run by service
298 | final Intent i = new Intent(context, ConnectorService.class);
299 | i.setAction(intent.getAction());
300 | // set command to intent
301 | command.setToIntent(i);
302 | if (origSpecs != null) {
303 | // set original specs to intent (preserve the original
304 | // specs and let ConnectorService make the decisions)
305 | origSpecs.setToIntent(i);
306 | }
307 | Log.i(tag, "start service " + i.getAction());
308 | if (null != context.startService(i) && ordered) {
309 | // start service
310 | try {
311 | this.setResultCode(Activity.RESULT_OK);
312 | } catch (Exception e) {
313 | Log.w(tag, "not an ordered boradcast: " + e.toString());
314 | }
315 | }
316 | } else {
317 | Log.w(tag, "faulty command:");
318 | Log.w(tag, "command: " + command.getType());
319 | Log.w(tag, "origSpecs: " + origSpecs);
320 | Log.w(tag, "specs: " + specs);
321 | }
322 | }
323 | }
324 |
325 | /**
326 | * Show {@link Toast} on main thread. Call this method for notifying the
327 | * user.
328 | *
329 | * @param context
330 | * {@link Context}
331 | * @param text
332 | * text
333 | */
334 | protected final void showToast(final Context context, final String text) {
335 | if (context == null || text == null) {
336 | return;
337 | }
338 | if (context instanceof ConnectorService) {
339 | ((ConnectorService) context).showToast(text);
340 | }
341 | }
342 |
343 | /**
344 | * Do bootstrap: This method is called after each change of settings for
345 | * doing some kind of remote setup. Most connectors do not need to implement
346 | * this. Default implementation does nothing. This is executed in a
347 | * different thread! Do not do any GUI stuff.
348 | *
349 | * @param context
350 | * {@link Context}
351 | * @param intent
352 | * {@link Intent} coming from outside
353 | * @throws IOException
354 | * IOException
355 | */
356 | protected void doBootstrap(final Context context, final Intent intent)
357 | throws IOException {
358 | // do nothing by default
359 | }
360 |
361 | /**
362 | * Do update: This method is called to update balance. Default
363 | * implementation does nothing. This is executed in a different thread! Do
364 | * not do any GUI stuff.
365 | *
366 | * @param context
367 | * {@link Context}
368 | * @param intent
369 | * {@link Intent} coming from outside
370 | * @throws IOException
371 | * IOException
372 | */
373 | protected void doUpdate(final Context context, final Intent intent)
374 | throws IOException {
375 | // do nothing by default
376 | }
377 |
378 | /**
379 | * Do send: This method is called to send the actual message. Default
380 | * implementation does nothing. This is executed in a different thread! Do
381 | * not do any GUI stuff.
382 | *
383 | * @param context
384 | * {@link Context}
385 | * @param intent
386 | * {@link Intent} coming from outside
387 | * @throws IOException
388 | * IOException
389 | */
390 | protected void doSend(final Context context, final Intent intent)
391 | throws IOException {
392 | // do nothing by default
393 | }
394 |
395 | /**
396 | * This method will be run, if any broadcast with a solved captcha arrived.
397 | * You should release the locks waiting for this to happen. This is not done
398 | * in the same thread as all the do* methods!
399 | *
400 | * @param context
401 | * {@link Context}
402 | * @param solvedCaptcha
403 | * the captcha solved as {@link String}, null if aborted by user.
404 | */
405 | protected void gotSolvedCaptcha(final Context context,
406 | final String solvedCaptcha) {
407 | // do nothing by default
408 | }
409 |
410 | /**
411 | * This method is called when a new request is received. Default
412 | * implementation does nothing. This is executed in a different thread! Do
413 | * not do any GUI stuff.
414 | *
415 | * @param context
416 | * {@link Context}
417 | * @param regSpec
418 | * {@link ConnectorSpec} from the request intent
419 | * @param command
420 | * {@link ConnectorCommand}
421 | */
422 | protected void onNewRequest(final Context context,
423 | final ConnectorSpec regSpec, final ConnectorCommand command) {
424 | // do nothing by default
425 | }
426 |
427 | }
428 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/ConnectorCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 |
20 | package de.ub0r.android.websms.connector.common;
21 |
22 | import java.util.ArrayList;
23 |
24 | import android.content.Intent;
25 | import android.os.Bundle;
26 |
27 | /**
28 | * A Command send to a Connector.
29 | *
30 | * @author flx
31 | */
32 | public final class ConnectorCommand implements Cloneable {
33 |
34 | /** Key to find command in a Bundle. */
35 | private static final String EXTRAS_COMMAND = "command";
36 |
37 | /** Command: type. */
38 | private static final String TYPE = "command_type";
39 | /** Command: type - none. */
40 | public static final short TYPE_NONE = 0;
41 | /** Command: type - bootstrap. */
42 | public static final short TYPE_BOOTSTRAP = 1;
43 | /** Command: type - update. */
44 | public static final short TYPE_UPDATE = 2;
45 | /** Command: type - send. */
46 | public static final short TYPE_SEND = 4;
47 | /** Command: message id. */
48 | private static final String MSG_ID = "msg_id";
49 | /** Command: default sender. */
50 | private static final String DEFSENDER = "command_defsender";
51 | /** Command: default prefix. */
52 | private static final String DEFPREFIX = "command_defprefix";
53 | /** Command: recipients. */
54 | private static final String RECIPIENTS = "command_reciepients";
55 | /** Command: text. */
56 | private static final String TEXT = "command_text";
57 | /** Command: flashsms. */
58 | private static final String FLASHSMS = "command_flashsms";
59 | /** Command: timestamp. */
60 | private static final String TIMESTAMP = "command_timestamp";
61 | /** Command: custom sender. */
62 | private static final String CUSTOMSENDER = "command_customsender";
63 | /** Command: list of message Uris. */
64 | private static final String MSG_URIS = "command_msgUris";
65 | /** Command: selected SubConnectorSpec for sending. */
66 | private static final String SELECTEDSUBCONNECTOR = // .
67 | "command_selectedsubconnector";
68 | /** Command: count of resend attempts. */
69 | private static final String RESEND_COUNT = "resend_count";
70 |
71 | /** {@link Bundle} represents the ConnectorSpec. */
72 | private final Bundle bundle;
73 |
74 | /**
75 | * Create command with type update.
76 | *
77 | * @param defPrefix
78 | * default prefix
79 | * @param defSender
80 | * default sender
81 | * @return created command
82 | */
83 | public static ConnectorCommand update(final String defPrefix,
84 | final String defSender) {
85 | final Bundle b = new Bundle();
86 | b.putShort(TYPE, TYPE_UPDATE);
87 | b.putString(DEFPREFIX, defPrefix);
88 | b.putString(DEFSENDER, defSender);
89 | return new ConnectorCommand(b);
90 | }
91 |
92 | /**
93 | * Create command with type bootstrap.
94 | *
95 | * @param defPrefix
96 | * default prefix
97 | * @param defSender
98 | * default sender
99 | * @return created command
100 | */
101 | public static ConnectorCommand bootstrap(final String defPrefix,
102 | final String defSender) {
103 | final Bundle b = new Bundle();
104 | b.putShort(TYPE, TYPE_BOOTSTRAP);
105 | b.putString(DEFPREFIX, defPrefix);
106 | b.putString(DEFSENDER, defSender);
107 | return new ConnectorCommand(b);
108 | }
109 |
110 | /**
111 | * Create Command with type "send".
112 | *
113 | * @param msgId
114 | * unique message id
115 | * @param selectedSubConnector
116 | * selected SubConnectorSpec
117 | * @param defPrefix
118 | * default prefix
119 | * @param defSender
120 | * default sender
121 | * @param recipients
122 | * recipients
123 | * @param text
124 | * text
125 | * @param flashSMS
126 | * flashsms
127 | * @param timestamp
128 | * timestamp for sending
129 | * @param customSender
130 | * custom sender
131 | * @return created command
132 | */
133 | public static ConnectorCommand send(final long msgId,
134 | final String selectedSubConnector, final String defPrefix,
135 | final String defSender, final String[] recipients,
136 | final String text, final boolean flashSMS, final long timestamp,
137 | final String customSender) {
138 | ConnectorCommand ret = send(msgId, selectedSubConnector, defPrefix,
139 | defSender, recipients, text, flashSMS);
140 | ret.setSendLater(timestamp);
141 | ret.setCustomSender(customSender);
142 | return ret;
143 | }
144 |
145 | /**
146 | * Create Command with type "send".
147 | *
148 | * @param msgId
149 | * unique message id
150 | * @param selectedSubConnector
151 | * selected SubConnectorSpec
152 | * @param defPrefix
153 | * default prefix
154 | * @param defSender
155 | * default sender
156 | * @param recipients
157 | * recipients
158 | * @param text
159 | * text
160 | * @param flashSMS
161 | * flashsms
162 | * @return created command
163 | */
164 | public static ConnectorCommand send(final long msgId,
165 | final String selectedSubConnector, final String defPrefix,
166 | final String defSender, final String[] recipients,
167 | final String text, // .
168 | final boolean flashSMS) {
169 | final Bundle b = new Bundle();
170 | b.putShort(TYPE, TYPE_SEND);
171 | b.putLong(MSG_ID, msgId);
172 | b.putString(SELECTEDSUBCONNECTOR, selectedSubConnector);
173 | b.putString(DEFPREFIX, defPrefix);
174 | b.putString(DEFSENDER, defSender);
175 | final int l = recipients.length;
176 | ArrayList r = new ArrayList(l);
177 | String s;
178 | for (int i = 0; i < l; i++) {
179 | s = recipients[i];
180 | if (s != null && s.trim().length() > 0) {
181 | r.add(s);
182 | }
183 | }
184 | s = null;
185 | b.putStringArray(RECIPIENTS, r.toArray(new String[0]));
186 | b.putString(TEXT, text);
187 | b.putBoolean(FLASHSMS, flashSMS);
188 | b.putLong(TIMESTAMP, -1);
189 | b.putString(CUSTOMSENDER, null);
190 | return new ConnectorCommand(b);
191 | }
192 |
193 | /**
194 | * Create Command from {@link Bundle}.
195 | *
196 | * @param b
197 | * Bundle
198 | */
199 | private ConnectorCommand(final Bundle b) {
200 | this.bundle = b;
201 | }
202 |
203 | /**
204 | * {@inheritDoc}
205 | */
206 | @Override
207 | public Object clone() {
208 | return new ConnectorCommand((Bundle) this.bundle.clone());
209 | }
210 |
211 | /**
212 | * Create Command from {@link Intent}.
213 | *
214 | * @param i
215 | * Intent
216 | */
217 | public ConnectorCommand(final Intent i) {
218 | Bundle e = i.getExtras();
219 | if (e != null) {
220 | this.bundle = e.getBundle(EXTRAS_COMMAND);
221 | } else {
222 | this.bundle = new Bundle();
223 | }
224 | }
225 |
226 | /**
227 | * Create Command from {@link Intent}.
228 | *
229 | * @param i
230 | * Intent
231 | * @return {@link ConnectorCommand} or null if not found
232 | */
233 | public static ConnectorCommand fromIntent(final Intent i) {
234 | Bundle bundle = i.getExtras();
235 | if (bundle != null) {
236 | bundle = bundle.getBundle(EXTRAS_COMMAND);
237 | }
238 | if (bundle != null) {
239 | return new ConnectorCommand(bundle);
240 | } else {
241 | return null;
242 | }
243 | }
244 |
245 | /**
246 | * Set this {@link ConnectorCommand} to an {@link Intent}. Creates new
247 | * Intent if needed.
248 | *
249 | * @param intent
250 | * {@link Intent}.
251 | * @return the same {@link Intent}
252 | */
253 | public Intent setToIntent(final Intent intent) {
254 | Intent i = intent;
255 | if (i == null) {
256 | switch (this.getType()) {
257 | case TYPE_BOOTSTRAP:
258 | i = new Intent(Connector.ACTION_RUN_BOOTSTRAP);
259 | break;
260 | case TYPE_UPDATE:
261 | i = new Intent(Connector.ACTION_RUN_UPDATE);
262 | break;
263 | case TYPE_SEND:
264 | i = new Intent(Connector.ACTION_RUN_SEND);
265 | break;
266 | default:
267 | return null;
268 | }
269 | }
270 | i.putExtra(EXTRAS_COMMAND, this.getBundle());
271 | return i;
272 | }
273 |
274 | /**
275 | * Get internal {@link Bundle}.
276 | *
277 | * @return internal {@link Bundle}
278 | */
279 | public Bundle getBundle() {
280 | return this.bundle;
281 | }
282 |
283 | /**
284 | * Get type.
285 | *
286 | * @return type
287 | */
288 | public short getType() {
289 | if (this.bundle != null) {
290 | return this.bundle.getShort(TYPE);
291 | } else {
292 | return TYPE_NONE;
293 | }
294 | }
295 |
296 | /**
297 | * Get selected SubConnectorSpec.
298 | *
299 | * @return selected SubConnectorSpec
300 | */
301 | public String getSelectedSubConnector() {
302 | if (this.bundle != null) {
303 | return this.bundle.getString(SELECTEDSUBCONNECTOR);
304 | } else {
305 | return "";
306 | }
307 | }
308 |
309 | /**
310 | * Set selected SubConnectorSpec.
311 | *
312 | * @param selected
313 | * SubConnectorSpec
314 | */
315 | public void setSelectedSubConnector(final String sub) {
316 | this.bundle.putString(SELECTEDSUBCONNECTOR, sub);
317 | }
318 |
319 | /**
320 | * Get default sender.
321 | *
322 | * @return default sender
323 | */
324 | public String getDefSender() {
325 | return this.bundle.getString(DEFSENDER);
326 | }
327 |
328 | /**
329 | * Get default prefix.
330 | *
331 | * @return default prefix
332 | */
333 | public String getDefPrefix() {
334 | return this.bundle.getString(DEFPREFIX);
335 | }
336 |
337 | /**
338 | * Set a single recipient to this command.
339 | *
340 | * @param recipient
341 | * recipient
342 | */
343 | public void setRecipients(final String recipient) {
344 | this.bundle.putStringArray(RECIPIENTS, new String[] { recipient });
345 | }
346 |
347 | /**
348 | * Get recipients.
349 | *
350 | * @return recipients
351 | */
352 | public String[] getRecipients() {
353 | return this.bundle.getStringArray(RECIPIENTS);
354 | }
355 |
356 | /**
357 | * Get text.
358 | *
359 | * @return text
360 | */
361 | public String getText() {
362 | return this.bundle.getString(TEXT);
363 | }
364 |
365 | /**
366 | * Check if message should be sent as flash sms.
367 | *
368 | * @return flashsms
369 | */
370 | public boolean getFlashSMS() {
371 | return this.bundle.getBoolean(FLASHSMS, false);
372 | }
373 |
374 | /**
375 | * Get time of when the message should be sent.
376 | *
377 | * @return timestamp for sending
378 | */
379 | public long getSendLater() {
380 | return this.bundle.getLong(TIMESTAMP, -1);
381 | }
382 |
383 | /**
384 | * Set timestamp for sending later.
385 | *
386 | * @param timestamp
387 | * timestamp
388 | */
389 | public void setSendLater(final long timestamp) {
390 | this.bundle.putLong(TIMESTAMP, timestamp);
391 | }
392 |
393 | /**
394 | * Get custom sender with which the message should be sent.
395 | *
396 | * @return custom sender
397 | */
398 | public String getCustomSender() {
399 | return this.bundle.getString(CUSTOMSENDER);
400 | }
401 |
402 | /**
403 | * Set custom sender.
404 | *
405 | * @param customSender
406 | * custom sender
407 | */
408 | public void setCustomSender(final String customSender) {
409 | this.bundle.putString(CUSTOMSENDER, customSender);
410 | }
411 |
412 | /**
413 | * Get message Uris.
414 | *
415 | * @return message uris
416 | */
417 | public String[] getMsgUris() {
418 | return this.bundle.getStringArray(MSG_URIS);
419 | }
420 |
421 | /**
422 | * Set message Uris.
423 | *
424 | * @param uris
425 | * uris
426 | */
427 | public void setMsgUris(final String[] uris) {
428 | this.bundle.putStringArray(MSG_URIS, uris);
429 | }
430 |
431 | /**
432 | * Get current count of resend attempts.
433 | *
434 | * @return count of resend attempts
435 | */
436 | public int getResendCount() {
437 | return this.bundle.getInt(RESEND_COUNT, 0);
438 | }
439 |
440 | /**
441 | * Set current count of resend attempts.
442 | *
443 | * @param resendCount
444 | * count of resend attempts
445 | */
446 | public void setResendCount(final int resendCount) {
447 | this.bundle.putInt(RESEND_COUNT, resendCount);
448 | }
449 |
450 | /**
451 | * Get id of the linked message.
452 | *
453 | * @return message id
454 | */
455 | public long getMsgId() {
456 | return this.bundle.getLong(MSG_ID);
457 | }
458 |
459 | /**
460 | * Compare two {@link Intent}s.
461 | *
462 | * @param i1
463 | * first intent
464 | * @param i2
465 | * second intent
466 | * @return true if both intents describe the same command
467 | */
468 | public static boolean equals(final Intent i1, final Intent i2) {
469 | Bundle b1 = i1.getExtras();
470 | Bundle b2 = i2.getExtras();
471 | if (b1 == null || b2 == null) {
472 | return false;
473 | }
474 | b1 = b1.getBundle(EXTRAS_COMMAND);
475 | b2 = b2.getBundle(EXTRAS_COMMAND);
476 | if (b1 == null || b2 == null) {
477 | return false;
478 | }
479 | final short s1 = b1.getShort(TYPE);
480 | final short s2 = b2.getShort(TYPE);
481 | return s1 == s2;
482 | }
483 | }
484 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/ConnectorPreferenceActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import android.os.Build;
22 | import android.os.Bundle;
23 | import android.preference.PreferenceActivity;
24 | import android.view.MenuItem;
25 |
26 | /**
27 | * Preferences.
28 | *
29 | * @author flx
30 | */
31 | public abstract class ConnectorPreferenceActivity extends PreferenceActivity {
32 |
33 | /**
34 | * {@inheritDoc}
35 | */
36 | @Override
37 | protected void onCreate(final Bundle savedInstanceState) {
38 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
39 | this.setTheme(android.R.style.Theme_Holo);
40 | }
41 | super.onCreate(savedInstanceState);
42 | }
43 |
44 | /**
45 | * {@inheritDoc}
46 | */
47 | @Override
48 | public boolean onOptionsItemSelected(final MenuItem item) {
49 | switch (item.getItemId()) {
50 | case android.R.id.home:
51 | // app icon in Action Bar clicked; go home
52 | this.finish();
53 | return true;
54 | default:
55 | return super.onOptionsItemSelected(item);
56 | }
57 | }
58 |
59 | /**
60 | * {@inheritDoc}
61 | */
62 | @Override
63 | protected void onPause() {
64 | super.onPause();
65 | Connector.flushSpec();
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/ConnectorService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010-2011 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import java.util.ArrayList;
22 |
23 | import android.app.IntentService;
24 | import android.app.Notification;
25 | import android.app.NotificationManager;
26 | import android.app.PendingIntent;
27 | import android.content.Context;
28 | import android.content.Intent;
29 | import android.os.Handler;
30 | import android.os.Message;
31 | import android.os.PowerManager;
32 | import android.os.PowerManager.WakeLock;
33 | import android.widget.Toast;
34 |
35 | /**
36 | * {@link Service} run by the connectors BroadcastReceiver.
37 | *
38 | * @author flx
39 | */
40 | public final class ConnectorService extends IntentService {
41 | /** Tag for output. */
42 | private static final String TAG = "IO";
43 |
44 | /** {@link NotificationManager}. */
45 | private NotificationManager mNM = null;
46 |
47 | /** Notification ID of this Service. */
48 | public static final int NOTIFICATION_PENDING = 0;
49 |
50 | /** Pending tasks. */
51 | private final ArrayList pendingIOOps = new ArrayList();
52 |
53 | /** {@link WakeLock} for forcing IO done before sleep. */
54 | private WakeLock wakelock = null;
55 |
56 | /** {@link Handler}. */
57 | private Handler handler = null;
58 |
59 | /**
60 | * Default constructor.
61 | */
62 | public ConnectorService() {
63 | super("WebSMS.Connector");
64 | }
65 |
66 | /**
67 | * {@inheritDoc}
68 | */
69 | @Override
70 | public void onCreate() {
71 | super.onCreate();
72 | this.handler = new Handler() {
73 | @Override
74 | public void handleMessage(final Message msg) {
75 | Log.i(TAG, "In handleMessage...");
76 | }
77 | };
78 | }
79 |
80 | /**
81 | * {@inheritDoc}
82 | */
83 | @Override
84 | public void onStart(final Intent intent, final int startId) {
85 | Log.d(TAG, "onStart()");
86 | if (intent != null) {
87 | this.register(intent);
88 | }
89 | // note that super.onStart will start processing the intent on the
90 | // background thread so we need to register etc before that
91 | super.onStart(intent, startId);
92 | }
93 |
94 | /**
95 | * Show {@link Toast} on main thread.
96 | *
97 | * @param text
98 | * text
99 | */
100 | void showToast(final String text) {
101 | Log.d(TAG, "showToast(" + text + ")");
102 | this.handler.post(new Runnable() {
103 | @Override
104 | public void run() {
105 | Toast.makeText(ConnectorService.this, text, Toast.LENGTH_LONG)
106 | .show();
107 | }
108 | });
109 | }
110 |
111 | /**
112 | * Build IO {@link Notification}.
113 | *
114 | * @param context
115 | * {@link Context}
116 | * @param command
117 | * {@link ConnectorCommand}
118 | * @return {@link Notification}
119 | */
120 | public static Notification getNotification(final Context context,
121 | final ConnectorCommand command) {
122 | final String t = context.getString(R.string.stat_notify_sms_pending);
123 | final String te = context.getString(R.string.stat_notify_sending) + " "
124 | + Utils.joinRecipients(command.getRecipients(), ", ");
125 | final String tt = command.getText();
126 |
127 | final Notification notification = new Notification(
128 | R.drawable.stat_notify_sms_pending, t, System
129 | .currentTimeMillis());
130 | final Intent intent = new Intent(Intent.ACTION_VIEW);
131 | intent.setClassName("de.ub0r.android.websms", "WebSMS");
132 | final PendingIntent contentIntent = PendingIntent.getActivity(context,
133 | 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
134 | notification.setLatestEventInfo(context, te, tt, contentIntent);
135 | notification.defaults |= Notification.FLAG_NO_CLEAR
136 | | Notification.FLAG_ONGOING_EVENT;
137 | notification.defaults &= Notification.DEFAULT_ALL
138 | ^ Notification.DEFAULT_LIGHTS ^ Notification.DEFAULT_SOUND
139 | ^ Notification.DEFAULT_VIBRATE;
140 | Log.d(TAG, "defaults: " + notification.defaults);
141 | return notification;
142 | }
143 |
144 | /**
145 | * Register a IO task.
146 | *
147 | * @param intent
148 | * intent holding IO operation
149 | */
150 | private void register(final Intent intent) {
151 | Log.i(TAG, "register(" + intent.getAction() + ")");
152 | synchronized (this.pendingIOOps) {
153 | if (this.wakelock == null) {
154 | final PowerManager pm = (PowerManager) this
155 | .getSystemService(Context.POWER_SERVICE);
156 | this.wakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
157 | TAG);
158 | this.wakelock.acquire();
159 | }
160 | final ConnectorCommand c = new ConnectorCommand(intent);
161 | if (c.getType() == ConnectorCommand.TYPE_SEND) {
162 | if (this.mNM == null) {
163 | this.mNM = (NotificationManager) this
164 | .getSystemService(NOTIFICATION_SERVICE);
165 | }
166 | try {
167 | final Notification notification = getNotification(this, c);
168 | this.mNM.notify(NOTIFICATION_PENDING, notification);
169 | } catch (IllegalArgumentException e) {
170 | Log.e(TAG, "illegal argument", e);
171 | }
172 | }
173 | Log.d(TAG, "currentIOOps=" + this.pendingIOOps.size());
174 | this.pendingIOOps.add(intent);
175 | Log.d(TAG, "currentIOOps=" + this.pendingIOOps.size());
176 | }
177 | }
178 |
179 | /**
180 | * Unregister a IO task.
181 | *
182 | * @param intent
183 | * intent holding IO operation
184 | */
185 | private void unregister(final Intent intent) {
186 | Log.i(TAG, "unregister(" + intent.getAction() + ")");
187 | synchronized (this.pendingIOOps) {
188 | Log.d(TAG, "currentIOOps=" + this.pendingIOOps.size());
189 | final int l = this.pendingIOOps.size();
190 | if (l == 1) {
191 | this.pendingIOOps.clear();
192 | } else {
193 | Intent oi;
194 | for (int i = 0; i < l; i++) {
195 | oi = this.pendingIOOps.get(i);
196 | // note that ConnectorSpec.equals will not work here because
197 | // not all intent types have ConnectorSpec bundle in them
198 | if (ConnectorCommand.equals(intent, oi)) {
199 | this.pendingIOOps.remove(i);
200 | break;
201 | }
202 | }
203 | }
204 | Log.d(TAG, "currentIOOps=" + this.pendingIOOps.size());
205 | if (this.pendingIOOps.size() == 0) {
206 | // set service to background
207 | if (this.mNM != null) {
208 | this.mNM.cancel(NOTIFICATION_PENDING);
209 | }
210 | if (this.wakelock != null && this.wakelock.isHeld()) {
211 | this.wakelock.release();
212 | }
213 | // stop unneeded service
214 | // this.stopSelf();
215 | }
216 | }
217 | }
218 |
219 | /**
220 | * {@inheritDoc}
221 | */
222 | @Override
223 | public void onDestroy() {
224 | super.onDestroy();
225 | Log.i(TAG, "onDestroy()");
226 | Log.i(TAG, "currentIOOps=" + this.pendingIOOps.size());
227 | final int s = this.pendingIOOps.size();
228 | ConnectorCommand cc;
229 | ConnectorSpec cs;
230 | Intent in;
231 | for (int i = 0; i < s; i++) {
232 | cc = new ConnectorCommand(this.pendingIOOps.get(i));
233 | cs = new ConnectorSpec(// .
234 | this.pendingIOOps.get(i));
235 | if (cc.getType() == ConnectorCommand.TYPE_SEND) {
236 | cs.setErrorMessage("error while IO");
237 | in = cs.setToIntent(null);
238 | cc.setToIntent(in);
239 | in.setFlags(in.getFlags()
240 | | Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
241 | this.sendBroadcast(in);
242 | in = null;
243 | } else {
244 | // Toast.makeText(this, cs.getName() + ": error while IO",
245 | // Toast.LENGTH_LONG);
246 | }
247 | }
248 | }
249 |
250 | /**
251 | * {@inheritDoc}
252 | */
253 | @Override
254 | protected void onHandleIntent(final Intent intent) {
255 | Log.d(TAG, "onHandleIntent()");
256 | if (intent == null) {
257 | return;
258 | }
259 | final String a = intent.getAction();
260 | Log.d(TAG, "action: " + a);
261 | final String pkg = this.getPackageName();
262 | if (a != null && (// .
263 | a.equals(pkg + Connector.ACTION_RUN_BOOTSTRAP) || // .
264 | a.equals(pkg + Connector.ACTION_RUN_UPDATE) || // .
265 | a.equals(pkg + Connector.ACTION_RUN_SEND))) {
266 | // register intent, if service gets killed, all pending intents
267 | // get send to websms
268 | // this.register(intent);
269 |
270 | try {
271 | final ConnectorSpec reqSpec = ConnectorSpec.fromIntent(intent);
272 | final ConnectorCommand command = new ConnectorCommand(intent);
273 | final Connector receiver = Connector.getInstance();
274 |
275 | receiver.onNewRequest(this, reqSpec, command);
276 |
277 | ConnectorSpec respSpec = receiver.getSpec(this).clone();
278 |
279 | this.doInBackground(intent, respSpec, command, receiver);
280 | this.onPostExecute(respSpec, command, receiver);
281 | } catch (WebSMSException e) {
282 | Log.e(TAG, "error starting service", e);
283 | // Toast.makeText(this, e.getMessage(),
284 | // Toast.LENGTH_LONG).show();
285 | }
286 | }
287 | this.unregister(intent);
288 | }
289 |
290 | /**
291 | * Do the work in background.
292 | *
293 | * @param intent
294 | * {@link Intent}
295 | * @param respSpec
296 | * {@link ConnectorSpec}
297 | * @param command
298 | * {@link ConnectorCommand}
299 | * @param receiver
300 | * {@link Connector}
301 | */
302 | private void doInBackground(final Intent intent,
303 | final ConnectorSpec respSpec, final ConnectorCommand command,
304 | final Connector receiver) {
305 | try {
306 | switch (command.getType()) {
307 | case ConnectorCommand.TYPE_BOOTSTRAP:
308 | receiver.doBootstrap(this, intent);
309 | break;
310 | case ConnectorCommand.TYPE_UPDATE:
311 | receiver.doUpdate(this, intent);
312 | break;
313 | case ConnectorCommand.TYPE_SEND:
314 | String t = command.getText();
315 | String[] r = command.getRecipients();
316 | if (t == null || t.length() == 0 || // .
317 | r == null || r.length == 0) {
318 | break;
319 | }
320 | t = null;
321 | r = null;
322 | receiver.doSend(this, intent);
323 | break;
324 | default:
325 | break;
326 | }
327 | } catch (Exception e) {
328 | if (e instanceof WebSMSException) {
329 | Log.d(TAG, respSpec.getPackage() + ": error in AsyncTask", e);
330 | } else {
331 | Log.e(TAG, respSpec.getPackage() + ": error in AsyncTask", e);
332 | }
333 | // put error message to ConnectorSpec
334 | respSpec.setErrorMessage(this, e);
335 | }
336 | }
337 |
338 | /**
339 | * Do post processing.
340 | *
341 | * @param respSpec
342 | * {@link ConnectorSpec}
343 | * @param command
344 | * {@link ConnectorCommand}
345 | * @param receiver
346 | * {@link Connector}
347 | */
348 | private void onPostExecute(final ConnectorSpec respSpec,
349 | final ConnectorCommand command, final Connector receiver) {
350 | // final String e = connector.getErrorMessage();
351 | // if (e != null) {
352 | // Toast.makeText(this, e, Toast.LENGTH_LONG).show();
353 | // }
354 | respSpec.update(receiver.getSpec(this));
355 | final Intent i = respSpec.setToIntent(null);
356 | command.setToIntent(i);
357 | i.setFlags(i.getFlags() | Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
358 | Log.d(TAG, respSpec.getPackage() + ": send broadcast info");
359 | this.sendBroadcast(i);
360 | // this.unregister(i);
361 | }
362 | }
363 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/FakeSocketFactory.java:
--------------------------------------------------------------------------------
1 | package de.ub0r.android.websms.connector.common;
2 |
3 | import java.io.IOException;
4 | import java.net.InetAddress;
5 | import java.net.InetSocketAddress;
6 | import java.net.Socket;
7 |
8 | import javax.net.ssl.SSLContext;
9 | import javax.net.ssl.SSLSocket;
10 | import javax.net.ssl.TrustManager;
11 |
12 | import org.apache.http.conn.scheme.LayeredSocketFactory;
13 | import org.apache.http.conn.scheme.SocketFactory;
14 | import org.apache.http.params.HttpConnectionParams;
15 | import org.apache.http.params.HttpParams;
16 |
17 | /**
18 | * Fake Socket Factory.
19 | */
20 | public final class FakeSocketFactory implements SocketFactory,
21 | LayeredSocketFactory {
22 |
23 | /** {@link SSLContext}. */
24 | private SSLContext sslcontext = null;
25 | /** Known good fingerprints. */
26 | private final String[] knownFingerprints;
27 |
28 | /** Default constructor. */
29 | public FakeSocketFactory() {
30 | this((String[]) null);
31 | }
32 |
33 | /**
34 | * Constructor checking for known good fingerprints.
35 | *
36 | * @param fingerprints
37 | * known good fingerprints
38 | */
39 | public FakeSocketFactory(final String... fingerprints) {
40 | this.knownFingerprints = fingerprints;
41 | }
42 |
43 | /**
44 | * Create a {@link SSLContext}.
45 | *
46 | * @return {@link SSLContext}
47 | * @throws IOException
48 | * IOException
49 | */
50 | private SSLContext createEasySSLContext() throws IOException {
51 | try {
52 | SSLContext context = SSLContext.getInstance("TLS");
53 | final TrustManager trustManager;
54 | if (this.knownFingerprints == null) {
55 | trustManager = new FakeTrustManager();
56 | } else {
57 | trustManager = new KnownFingerprintTrustManager(
58 | this.knownFingerprints);
59 | }
60 | context.init(null, new TrustManager[] { trustManager }, null);
61 | return context;
62 | } catch (Exception e) {
63 | throw new IOException(e.getMessage());
64 | }
65 | }
66 |
67 | /**
68 | * @return {@link SSLContext}
69 | * @throws IOException
70 | * IOException
71 | */
72 | private SSLContext getSSLContext() throws IOException {
73 | if (this.sslcontext == null) {
74 | this.sslcontext = this.createEasySSLContext();
75 | }
76 | return this.sslcontext;
77 | }
78 |
79 | /**
80 | * {@inheritDoc}
81 | */
82 | @Override
83 | public Socket connectSocket(final Socket sock, final String host,
84 | final int port, final InetAddress localAddress,
85 | final int localPort, final HttpParams params) throws IOException {
86 | int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
87 | int soTimeout = HttpConnectionParams.getSoTimeout(params);
88 |
89 | InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
90 | SSLSocket sslsock = (SSLSocket) sock;
91 | if (sslsock == null) {
92 | this.createSocket();
93 | }
94 |
95 | if ((localAddress != null) || (localPort > 0)) {
96 | int lp = localPort;
97 | // we need to bind explicitly
98 | if (lp < 0) {
99 | lp = 0; // indicates "any"
100 | }
101 | InetSocketAddress isa = new InetSocketAddress(localAddress, lp);
102 | sslsock.bind(isa);
103 | }
104 |
105 | sslsock.connect(remoteAddress, connTimeout);
106 | sslsock.setSoTimeout(soTimeout);
107 | return sslsock;
108 | }
109 |
110 | /**
111 | * {@inheritDoc}
112 | */
113 | @Override
114 | public Socket createSocket() throws IOException {
115 | return this.getSSLContext().getSocketFactory().createSocket();
116 | }
117 |
118 | /**
119 | * {@inheritDoc}
120 | */
121 | @Override
122 | public boolean isSecure(final Socket arg0) {
123 | return true;
124 | }
125 |
126 | /**
127 | * {@inheritDoc}
128 | */
129 | @Override
130 | public Socket createSocket(final Socket socket, final String host,
131 | final int port, final boolean autoClose) throws IOException {
132 | return this.getSSLContext().getSocketFactory().createSocket(socket,
133 | host, port, autoClose);
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/FakeTrustManager.java:
--------------------------------------------------------------------------------
1 | package de.ub0r.android.websms.connector.common;
2 |
3 | import java.security.cert.CertificateException;
4 | import java.security.cert.X509Certificate;
5 |
6 | import javax.net.ssl.X509TrustManager;
7 |
8 | /**
9 | * All SSL certs are trusted!
10 | */
11 | public final class FakeTrustManager implements X509TrustManager {
12 |
13 | /** ?? */
14 | private static final X509Certificate[] _AcceptedIssuers = // .
15 | new X509Certificate[] {};
16 |
17 | /**
18 | * {@inheritDoc}
19 | */
20 | @Override
21 | public void checkClientTrusted(final X509Certificate[] chain,
22 | final String authType) throws CertificateException {
23 | }
24 |
25 | /**
26 | * {@inheritDoc}
27 | */
28 | @Override
29 | public void checkServerTrusted(final X509Certificate[] chain,
30 | final String authType) throws CertificateException {
31 | }
32 |
33 | /**
34 | * {@inheritDoc}
35 | */
36 | public boolean isClientTrusted(final X509Certificate[] chain) {
37 | return true;
38 | }
39 |
40 | /**
41 | * {@inheritDoc}
42 | */
43 | public boolean isServerTrusted(final X509Certificate[] chain) {
44 | return true;
45 | }
46 |
47 | /**
48 | * {@inheritDoc}
49 | */
50 | @Override
51 | public X509Certificate[] getAcceptedIssuers() {
52 | return _AcceptedIssuers;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/InfoActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 Felix Bechstein
3 | *
4 | * This file is part of ConnectorTest.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import java.util.List;
22 |
23 | import android.app.Activity;
24 | import android.app.AlertDialog.Builder;
25 | import android.content.ActivityNotFoundException;
26 | import android.content.DialogInterface;
27 | import android.content.Intent;
28 | import android.content.pm.ResolveInfo;
29 | import android.net.Uri;
30 | import android.os.Build;
31 |
32 | /**
33 | * This is the default Activity launched from android market after install of
34 | * any plugin. This activity simply says: "i am a plugin for WebSMS".
35 | *
36 | * @author flx
37 | */
38 | public final class InfoActivity extends Activity {
39 | /** Tag for debug output. */
40 | private static final String TAG = "Info";
41 |
42 | /** Link to WebSMS in android market. */
43 | private static final Intent INTENT_MARKET_WEBSMS = new Intent(
44 | Intent.ACTION_VIEW, Uri.parse(// .
45 | "market://search?q=pname:de.ub0r.android.websms"));
46 |
47 | /** Link to Connectors in android market. */
48 | private static final Intent INTENT_MARKET_CONNECTORS = new Intent(
49 | Intent.ACTION_VIEW, Uri.parse(// .
50 | "market://search?q=websms+connector"));
51 |
52 | /** Info text shown to user. */
53 | private static final String INFO_TEXT = "This is a WebSMS Connector."
54 | + "\nThe only way to use it, is lauching it with WebSMS.";
55 |
56 | /** Button label: search websms. */
57 | private static final String BTN_MARKET_WEBSMS = "market: WebSMS";
58 | /** Button label: search connectors. */
59 | private static final String BTN_MARKET_CONNECTORS = // .
60 | "market: Connectors";
61 |
62 | /**
63 | * {@inheritDoc}
64 | */
65 | @Override
66 | protected void onResume() {
67 | super.onResume();
68 | Builder b;
69 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
70 | b = BuilderWrapper11.getBuilder(this,
71 | android.R.style.Theme_Holo_Light_Dialog);
72 | } else {
73 | b = new Builder(this);
74 | }
75 | b.setTitle(this.getTitle());
76 | final String pkg = this.getPackageName();
77 | final int info = this.getResources().getIdentifier("info_text",
78 | "string", pkg);
79 | final int icon = this.getResources().getIdentifier("icon", "drawable",
80 | pkg);
81 | Log.d(TAG, "resID.icon=" + icon);
82 | Log.d(TAG, "resID.info=" + info);
83 | if (icon > 0) {
84 | b.setIcon(icon);
85 | }
86 | if (info > 0) {
87 | b.setMessage(info);
88 | } else {
89 | b.setMessage(INFO_TEXT);
90 | }
91 | b.setPositiveButton(android.R.string.ok,
92 | new DialogInterface.OnClickListener() {
93 | @Override
94 | public void onClick(final DialogInterface dialog,
95 | final int which) {
96 | InfoActivity.this.finish();
97 | }
98 | });
99 | final List ri = this.getPackageManager()
100 | .queryBroadcastReceivers(new Intent(Connector.ACTION_INFO), 0);
101 | if (ri.size() == 0) {
102 | b.setNeutralButton(BTN_MARKET_WEBSMS,
103 | new DialogInterface.OnClickListener() {
104 | @Override
105 | public void onClick(final DialogInterface dialog,
106 | final int which) {
107 | try {
108 | InfoActivity.this
109 | .startActivity(INTENT_MARKET_WEBSMS);
110 | } catch (ActivityNotFoundException e) {
111 | Log.e(TAG, "no market", e);
112 | }
113 | InfoActivity.this.finish();
114 | }
115 | });
116 | }
117 | b.setNegativeButton(BTN_MARKET_CONNECTORS,
118 | new DialogInterface.OnClickListener() {
119 | @Override
120 | public void onClick(final DialogInterface dialog,
121 | final int which) {
122 | try {
123 | InfoActivity.this
124 | .startActivity(INTENT_MARKET_CONNECTORS);
125 | } catch (ActivityNotFoundException e) {
126 | Log.e(TAG, "no market", e);
127 | }
128 | InfoActivity.this.finish();
129 | }
130 | });
131 | b.setOnCancelListener(new DialogInterface.OnCancelListener() {
132 | @Override
133 | public void onCancel(final DialogInterface dialog) {
134 | InfoActivity.this.finish();
135 | }
136 | });
137 | b.setCancelable(true);
138 | b.show();
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/KnownFingerprintTrustManager.java:
--------------------------------------------------------------------------------
1 | package de.ub0r.android.websms.connector.common;
2 |
3 | import java.security.MessageDigest;
4 | import java.security.NoSuchAlgorithmException;
5 | import java.security.cert.CertificateException;
6 | import java.security.cert.X509Certificate;
7 | import java.util.ArrayList;
8 | import java.util.Arrays;
9 | import java.util.List;
10 |
11 | import javax.net.ssl.X509TrustManager;
12 |
13 | /**
14 | * A TrustManager-implementation that checks that a site-certificate has a known
15 | * (meaning developer-verified) fingerprint.
16 | *
17 | * @author boris
18 | */
19 | public final class KnownFingerprintTrustManager implements X509TrustManager {
20 |
21 | /** Hex = 16 . */
22 | private static final int HEX = 16;
23 |
24 | /** Array of known good CAs? */
25 | private static final X509Certificate[] ACCEPTED_ISSUERS = // .
26 | new X509Certificate[] {};
27 |
28 | /** List of known good fingerprints. */
29 | private final List knownSha1Fingerprints;
30 |
31 | /**
32 | * @param knownFingerprints
33 | * The known fingerprint that should be used for the
34 | * check-methods
35 | * @throws NullPointerException
36 | * If {@code knownSha1Fingerprint == null}
37 | */
38 | public KnownFingerprintTrustManager(final String... knownFingerprints) {
39 | this.knownSha1Fingerprints = new ArrayList(
40 | knownFingerprints.length);
41 |
42 | for (String fingerprint : knownFingerprints) {
43 | this.knownSha1Fingerprints.add(fingerprintToBytes(fingerprint));
44 | }
45 | }
46 |
47 | /**
48 | * {@inheritDoc}
49 | */
50 | @Override
51 | public void checkClientTrusted(final X509Certificate[] chain,
52 | final String authType) throws CertificateException {
53 | this.checkTrusted(chain);
54 | }
55 |
56 | /**
57 | * {@inheritDoc}
58 | */
59 | @Override
60 | public void checkServerTrusted(final X509Certificate[] chain,
61 | final String authType) throws CertificateException {
62 | this.checkTrusted(chain);
63 | }
64 |
65 | /**
66 | * Check trusted certificate. It only checks for known good fingerprints!
67 | *
68 | * @param chain
69 | * chain of certifications
70 | * @throws CertificateException
71 | * CertificateException
72 | */
73 | private void checkTrusted(final X509Certificate[] chain)
74 | throws CertificateException {
75 | if (chain.length == 0) {
76 | throw new CertificateException("No entries in certificate-chain");
77 | }
78 |
79 | try {
80 | X509Certificate siteCert = chain[0];
81 | MessageDigest md = MessageDigest.getInstance("SHA-1");
82 | byte[] certFingerprint = md.digest(siteCert.getEncoded());
83 |
84 | boolean matched = false;
85 | for (byte[] fingerprint : this.knownSha1Fingerprints) {
86 | if (Arrays.equals(certFingerprint, fingerprint)) {
87 | matched = true;
88 | break;
89 | }
90 | }
91 |
92 | if (!matched) {
93 | throw new CertificateException(
94 | "Unknown certificate fingerprint "
95 | + Arrays.toString(certFingerprint));
96 | }
97 | } catch (NoSuchAlgorithmException e) {
98 | throw new CertificateException(
99 | "Cannot calculate SHA-1 because the algorithm is missing",
100 | e);
101 | }
102 | }
103 |
104 | /**
105 | * {@inheritDoc}
106 | */
107 | @Override
108 | public X509Certificate[] getAcceptedIssuers() {
109 | return ACCEPTED_ISSUERS;
110 | }
111 |
112 | /**
113 | * Convert fingerprint from {@link String} to {@link byte[]}.
114 | *
115 | * @param knownFingerprint
116 | * fingerprint as : separated {@link String}
117 | * @return fingerprint
118 | */
119 | private static byte[] fingerprintToBytes(final String knownFingerprint) {
120 | final String[] byteTokens = knownFingerprint.split(":");
121 | final byte[] result = new byte[byteTokens.length];
122 | for (int i = 0; i < result.length; ++i) {
123 | result[i] = Integer.valueOf(byteTokens[i], HEX).byteValue();
124 | }
125 | return result;
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/Log.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 |
24 | import android.app.Activity;
25 | import android.app.AlertDialog;
26 | import android.content.DialogInterface;
27 | import android.content.Intent;
28 | import android.content.pm.PackageManager;
29 | import android.net.Uri;
30 | import android.text.TextUtils;
31 |
32 | /**
33 | * @author flx
34 | */
35 | public final class Log {
36 | /** Tag for output. */
37 | public static final String TAG = "WebSMS";
38 |
39 | /** Packagename of SendLog. */
40 | private static final String SENDLOG_PACKAGE_NAME = "org.l6n.sendlog";
41 |
42 | /** Classname of SendLog. */
43 | // private static final String SENDLOG_CLASS_NAME = ".SendLog";
44 |
45 | /** Priority constant for the println method. */
46 | public static final int ASSERT = android.util.Log.ASSERT;
47 | /** Priority constant for the println method; use Log.d. */
48 | public static final int DEBUG = android.util.Log.DEBUG;
49 | /** Priority constant for the println method; use Log.e. */
50 | public static final int ERROR = android.util.Log.ERROR;
51 | /** Priority constant for the println method; use Log.i. */
52 | public static final int INFO = android.util.Log.INFO;
53 | /** Priority constant for the println method; use Log.v. */
54 | public static final int VERBOSE = android.util.Log.VERBOSE;
55 | /** Priority constant for the println method; use Log.w. */
56 | public static final int WARN = android.util.Log.WARN;
57 |
58 | /**
59 | * Fire a given {@link Intent}.
60 | *
61 | * @author flx
62 | */
63 | private static class FireIntent implements DialogInterface.OnClickListener {
64 | /** {@link Activity}. */
65 | private final Activity a;
66 | /** {@link Intent}. */
67 | private final Intent i;
68 |
69 | /**
70 | * Default Constructor.
71 | *
72 | * @param activity
73 | * {@link Activity}
74 | * @param intent
75 | * {@link Intent}
76 | */
77 | public FireIntent(final Activity activity, final Intent intent) {
78 | this.a = activity;
79 | this.i = intent;
80 | }
81 |
82 | /**
83 | * {@inheritDoc}
84 | */
85 | public void onClick(final DialogInterface dialog, // .
86 | final int whichButton) {
87 | this.a.startActivity(this.i);
88 | }
89 | }
90 |
91 | /**
92 | * Default Constructor.
93 | */
94 | private Log() {
95 |
96 | }
97 |
98 | /**
99 | * Send a DEBUG log message.
100 | *
101 | * @param tag
102 | * Used to identify the source of a log message. It usually
103 | * identifies the class or activity where the log call occurs.
104 | * @param msg
105 | * The message you would like logged.
106 | */
107 | public static void d(final String tag, final String msg) {
108 | android.util.Log.d(TAG, tag + ": " + msg);
109 | }
110 |
111 | /**
112 | * Send a DEBUG log message and log the exception.
113 | *
114 | * @param tag
115 | * Used to identify the source of a log message. It usually
116 | * identifies the class or activity where the log call occurs.
117 | * @param msg
118 | * The message you would like logged.
119 | * @param tr
120 | * An exception to log.
121 | */
122 | public static void d(final String tag, final String msg, // .
123 | final Throwable tr) {
124 | android.util.Log.d(TAG, tag + ": " + msg, tr);
125 | }
126 |
127 | /**
128 | * Send a DEBUG log message.
129 | *
130 | * @param tag
131 | * Used to identify the source of a log message. It usually
132 | * identifies the class or activity where the log call occurs.
133 | * @param msg
134 | * The message you would like logged.
135 | * @param array
136 | * array to print
137 | */
138 | public static void d(final String tag, final String msg,
139 | final String[] array) {
140 | if (array == null) {
141 | d(tag, msg);
142 | }
143 | final StringBuilder buf = new StringBuilder();
144 | final int l = array.length;
145 | for (int i = 0; i < l; i++) {
146 | buf.append(array[i]);
147 | if (i < l - 1) {
148 | buf.append("; ");
149 | }
150 | }
151 | android.util.Log.d(TAG, tag + ": " + msg + buf.toString());
152 | }
153 |
154 | /**
155 | * Send a DEBUG log message.
156 | *
157 | * @param tag
158 | * Used to identify the source of a log message. It usually
159 | * identifies the class or activity where the log call occurs.
160 | * @param s
161 | * message as stream
162 | */
163 | public static void d(final String tag, final InputStream s) {
164 | if (s == null) {
165 | d(tag, "");
166 | } else {
167 | try {
168 | String str = Utils.stream2str(s);
169 | if (TextUtils.isEmpty(str)) {
170 | d(tag, "");
171 | } else {
172 | String[] ss = str.split("\n");
173 | for (String sstr : ss) {
174 | d(tag, sstr);
175 | }
176 | }
177 | } catch (IOException e) {
178 | d(tag, "", e);
179 | }
180 | }
181 | }
182 |
183 | /**
184 | * Send a ERROR log message.
185 | *
186 | * @param tag
187 | * Used to identify the source of a log message. It usually
188 | * identifies the class or activity where the log call occurs.
189 | * @param msg
190 | * The message you would like logged.
191 | */
192 | public static void e(final String tag, final String msg) {
193 | android.util.Log.e(TAG, tag + ": " + msg);
194 | }
195 |
196 | /**
197 | * Send a ERROR log message and log the exception.
198 | *
199 | * @param tag
200 | * Used to identify the source of a log message. It usually
201 | * identifies the class or activity where the log call occurs.
202 | * @param msg
203 | * The message you would like logged.
204 | * @param tr
205 | * An exception to log.
206 | */
207 | public static void e(final String tag, final String msg, // .
208 | final Throwable tr) {
209 | android.util.Log.e(TAG, tag + ": " + msg, tr);
210 | }
211 |
212 | /**
213 | * Send a INFO log message.
214 | *
215 | * @param tag
216 | * Used to identify the source of a log message. It usually
217 | * identifies the class or activity where the log call occurs.
218 | * @param msg
219 | * The message you would like logged.
220 | */
221 | public static void i(final String tag, final String msg) {
222 | android.util.Log.i(TAG, tag + ": " + msg);
223 | }
224 |
225 | /**
226 | * Send a INFO log message and log the exception.
227 | *
228 | * @param tag
229 | * Used to identify the source of a log message. It usually
230 | * identifies the class or activity where the log call occurs.
231 | * @param msg
232 | * The message you would like logged.
233 | * @param tr
234 | * An exception to log.
235 | */
236 | public static void i(final String tag, final String msg, // .
237 | final Throwable tr) {
238 | android.util.Log.i(TAG, tag + ": " + msg, tr);
239 | }
240 |
241 | /**
242 | * Send a VERBOSE log message.
243 | *
244 | * @param tag
245 | * Used to identify the source of a log message. It usually
246 | * identifies the class or activity where the log call occurs.
247 | * @param msg
248 | * The message you would like logged.
249 | */
250 | public static void v(final String tag, final String msg) {
251 | android.util.Log.v(TAG, tag + ": " + msg);
252 | }
253 |
254 | /**
255 | * Send a VERBOSE log message and log the exception.
256 | *
257 | * @param tag
258 | * Used to identify the source of a log message. It usually
259 | * identifies the class or activity where the log call occurs.
260 | * @param msg
261 | * The message you would like logged.
262 | * @param tr
263 | * An exception to log.
264 | */
265 | public static void v(final String tag, final String msg, // .
266 | final Throwable tr) {
267 | android.util.Log.v(TAG, tag + ": " + msg, tr);
268 | }
269 |
270 | /**
271 | * Send a WARN log message.
272 | *
273 | * @param tag
274 | * Used to identify the source of a log message. It usually
275 | * identifies the class or activity where the log call occurs.
276 | * @param msg
277 | * The message you would like logged.
278 | */
279 | public static void w(final String tag, final String msg) {
280 | android.util.Log.w(TAG, tag + ": " + msg);
281 | }
282 |
283 | /**
284 | * Send a WARN log message and log the exception.
285 | *
286 | * @param tag
287 | * Used to identify the source of a log message. It usually
288 | * identifies the class or activity where the log call occurs.
289 | * @param msg
290 | * The message you would like logged.
291 | * @param tr
292 | * An exception to log.
293 | */
294 | public static void w(final String tag, final String msg, // .
295 | final Throwable tr) {
296 | android.util.Log.w(TAG, tag + ": " + msg, tr);
297 | }
298 |
299 | /**
300 | * Collect and send Log.
301 | *
302 | * @param activity
303 | * {@link Activity}.
304 | */
305 | public static void collectAndSendLog(final Activity activity) {
306 | final PackageManager packageManager = activity.getPackageManager();
307 | Intent intent = packageManager
308 | .getLaunchIntentForPackage(SENDLOG_PACKAGE_NAME);
309 | final String pkg = activity.getPackageName();
310 | int title, message;
311 | if (intent == null) {
312 | intent = new Intent(
313 | Intent.ACTION_VIEW,
314 | Uri.parse("market://search?q=pname:" + SENDLOG_PACKAGE_NAME));
315 | title = activity.getResources().getIdentifier("sendlog_install_",
316 | "string", pkg);
317 | message = activity.getResources().getIdentifier("sendlog_install",
318 | "string", pkg);
319 | } else {
320 | intent.putExtra("filter", TAG + ":D *:W");
321 | intent.setType("0||android@ub0r.de");
322 | title = activity.getResources().getIdentifier("sendlog_run_",
323 | "string", pkg);
324 | message = activity.getResources().getIdentifier("sendlog_run",
325 | "string", pkg);
326 | }
327 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
328 | final AlertDialog.Builder b = new AlertDialog.Builder(activity);
329 | b.setIcon(android.R.drawable.ic_dialog_info);
330 | b.setTitle(title);
331 | b.setMessage(message);
332 | b.setPositiveButton(android.R.string.ok, new FireIntent(activity,
333 | intent));
334 | b.setNegativeButton(android.R.string.cancel, null);
335 | b.show();
336 | }
337 | }
338 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/SMSLengthCalculator.java:
--------------------------------------------------------------------------------
1 | package de.ub0r.android.websms.connector.common;
2 |
3 | import java.io.Serializable;
4 |
5 | import android.os.Parcelable;
6 |
7 | /**
8 | * A simple interface for computing the length of a message based on the message
9 | * body. This is used for informing users how many characters they have
10 | * remaining before an additional message is required, as well as how many
11 | * messages they are currently using.
12 | *
13 | * @author Fintan Fairmichael
14 | *
15 | */
16 | public interface SMSLengthCalculator extends Serializable, Parcelable {
17 | int[] calculateLength(final String messageBody, final boolean use7bitOnly);
18 | }
19 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/WebSMSException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import android.content.Context;
22 |
23 | /**
24 | * Exception while Connector IO.
25 | *
26 | * @author flx
27 | */
28 | public class WebSMSException extends RuntimeException {
29 |
30 | /** The Constant serialVersionUID. */
31 | private static final long serialVersionUID = -6215729019426883487L;
32 |
33 | /**
34 | * Create a new WebSMSException.
35 | *
36 | * @param s
37 | * error message
38 | */
39 | public WebSMSException(final String s) {
40 | super(s);
41 | }
42 |
43 | /**
44 | * Create a new {@link WebSMSException}.
45 | *
46 | * @param ex
47 | * a {@link Throwable} instance
48 | */
49 | public WebSMSException(final Throwable ex) {
50 | super(ex);
51 | }
52 |
53 | /**
54 | * Create a new {@link WebSMSException}.
55 | *
56 | * @param ex
57 | * a {@link WebSMSException} instance
58 | */
59 | public WebSMSException(final WebSMSException ex) {
60 | super(ex.getMessage());
61 | }
62 |
63 | /**
64 | * Create a new WebSMSException.
65 | *
66 | * @param c
67 | * Context to resolve resource id
68 | * @param rid
69 | * error message as resource id
70 | */
71 | public WebSMSException(final Context c, final int rid) {
72 | super(c.getString(rid));
73 | }
74 |
75 | /**
76 | * Create a new WebSMSException.
77 | *
78 | * @param c
79 | * Context to resolve resource id
80 | * @param rid
81 | * error message as resource id
82 | * @param s
83 | * error message
84 | */
85 | public WebSMSException(final Context c, final int rid, final String s) {
86 | super(c.getString(rid) + s);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/WebSMSNoNetworkException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 | package de.ub0r.android.websms.connector.common;
20 |
21 | import android.content.Context;
22 |
23 | /**
24 | * No network available.
25 | */
26 | public class WebSMSNoNetworkException extends WebSMSException {
27 |
28 | /** The Constant serialVersionUID. */
29 | private static final long serialVersionUID = 8849042093428089066L;
30 |
31 | /**
32 | * Create a new WebSMSException.
33 | *
34 | * @param c
35 | * Context to resolve resource
36 | */
37 | public WebSMSNoNetworkException(final Context c) {
38 | super(c.getString(R.string.no_network));
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 Felix Bechstein
3 | *
4 | * This file is part of WebSMS.
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License as published by the Free Software
8 | * Foundation; either version 3 of the License, or (at your option) any later
9 | * version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 | * details.
15 | *
16 | * You should have received a copy of the GNU General Public License along with
17 | * this program; If not, see .
18 | */
19 |
20 | /**
21 | * This package is holding common classes for connectors. Implement new
22 | * connectors by inherent {@link Connector}.
23 | *
24 | * @version 3.0
25 | * @author flx
26 | */
27 | package de.ub0r.android.websms.connector.common;
28 |
29 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-hdpi-v11/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-hdpi-v11/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-hdpi-v9/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-hdpi-v9/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-hdpi/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-hdpi/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-ldpi-v9/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-ldpi-v9/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-mdpi-v11/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-mdpi-v11/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-mdpi-v9/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-mdpi-v9/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-mdpi/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-mdpi/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable-xhdpi/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable-xhdpi/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable/icon.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/drawable/stat_notify_sms_pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/WebSMSAPI/src/main/res/drawable/stat_notify_sms_pending.png
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-cs/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
23 |
24 | WebSMS Rozhraní je aplikace, kterou lze používat prostřednictvím aplikace WebSMS.
25 | WebSMS: odesílaní
26 | Odesílání:
27 | CHYBA
28 | Připojení ukončeno/vypršel časový limit. Pokud je Vaše připojení aktivní, pravděpodobně není dostupná cílová služba. Prosím zkontrolujte stránky aplikace, případně twitter.
29 | NEÚSPĚCH: HTTP
30 | Zadán neplatný email nebo heslo!
31 | Zadáno neplatné uživatelské jméno nebo heslo!
32 | Špatné číslo odesílatele. Formát musí mít mezinárodní tvar, např. +4917012345678.
33 | Odesílatel musí být registrovaný a mít ověřené číslo u poskytovatele služby.
34 | NEÚSPĚCH: Odpověď serveru:
35 | Webová služba není dostupná. Pravděpodobně se nejedná o chybu rozhraní. Prosím zkuste to později. Zkontrolujte stránky aplikace, případně twitter.
36 | Špatně vyplněný kód. Prosím zkuste to znovu.
37 | Chybě zadaný vstup!
38 | Hlavička: Chybí velikost obsahu!
39 | Maximálně 15 minut je dostupných pro Váše rozhraní!
40 | Skrýt podrozhraní \"s odesílatelem\"
41 | Skrýt podrozhraní \"s odesílatelem\" z výběru
42 | Skrýt podrozhraní \"bez odesílatele\"
43 | Skrýt podrozhraní \"bez odesílatele\" z výběru
44 | Skrýt podrozhraní \"zdarma\"
45 | Skrýt podrozhraní \"zdarma\" z výběru.
46 | Ignorovat chyby v ověření SSL
47 | Ignorovat chyby během ověření SSL. Některé telefony nemají instalovány potřebné certifikáty. Ignorování snižuje zabezpečení komunikace.
48 | Uživatelské jméno
49 | Heslo
50 | Vytvořit účet
51 | Použít výchozího odesílatele
52 | Použít výchozího odesílatele, kterého poskytuje WebSMS.
53 | Vlastní odesílatel
54 | Mez. telefonní číslo, např. +491791234567
55 | Odeslat záznamy
56 | Odeslat záznamy telefonu vývojářům. Vyberte pouze pokud jste byli požádáni.
57 | Spustit SendLog
58 | SendLog automaticky shromáždí záznamy Vašeho telefonu a odešle je vývojářům.\nBudete mít možnost tyto data prohlížet, případně měnit.
59 | Instalovat SendLog
60 | Instalovat zdarma aplikaci SendLog, která shromažďuje data a odesílá je vývojářům.
61 | Dostupný update pro rozhraní
62 | Rozhraní bylo změněno.\nPro získání nové verze klikněte prosím zde.
63 |
64 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
23 |
24 | Diese App ist ein WebSMS Connector.\nDu kannst ihn nur mit WebSMS nutzen.
25 | WebSMS: senden
26 | Sende:
27 | FEHLER
28 | Verbindung abgebrochen/fehlgeschlagen. Wenn deine Verbindung funktioniert, ist das sehr wahrscheinlich eine Downtime des Services. Kontrolliere die Issues auf der App-Website sowie Twitter für weitere Informationen.
29 | FEHLER: HTTP
30 | Falsche Emailadresse oder Passwort angegeben!
31 | Falscher Benutzername oder Passwort angegeben!
32 | Falscher Absender! Das Format muss im internationalen Format sein, z.B. +4917012345678.
33 | Absender muss bei deinem Provider registriert und bestätigt sein.
34 | FEHLER: Serverantwort:
35 | Der Webservice ist down! Das ist sehr wahrscheinlich kein Fehler des Connectors. Bitte versuch es später noch einmal. Kontrolliere die Issues auf der App-Website sowie Twitter für weitere Informationen.
36 | Captcha war falsch. Bitte versuche es nochmal.
37 | Benutzereingabe ist falsch!
38 | Header: Content-Length fehlt!
39 | Nur volle 15 Minuten werden von deinem Provider erlaubt!
40 | Guthaben reicht nicht aus!
41 | Empfänger nicht gültig!
42 | Nachricht nicht gültig!
43 | Verstecke \"mit Absender\" SubConnector
44 | Verstecke \"mit Absender\" SubConnector in der Auswahl.
45 | Verstecke \"ohne Absender\" SubConnector
46 | Verstecke \"ohne Absender\" SubConnector in der Auswahl.
47 | Verstecke \"free\" SubConnector
48 | Verstecke \"free\" SubConnector in der Auswahl.
49 | Ignoriere SSL Handshake Fehler
50 | Ignoriere Fehler beim SSL Handshake. Einige Telefone haben nicht die benötigten Zertifikate installiert. Das Aktivieren führ zu Unsicherheiten.
51 | Benutzername
52 | Passwort
53 | Account anlegen
54 | Standard-Absender nutzen
55 | Benutze den in WebSMS eingestellten Absender.
56 | Anderer Absender
57 | Deine int. Mobilnummer, z.B. +491791234567
58 | Logs senden
59 | Logs von deinem Handy an den Entwickler senden.\nBitte nur nach Aufforderung senden.
60 | SendLog starten
61 | SendLog wird die Logs aus deinem Gerät auslesen und zum Entwickler schicken.\nDu hast vor dem Senden die Möglichkeit die Daten zu begutachten und zu verändern.
62 | SendLog installieren
63 | Installiere die kostenlose App SendLog um die Logs auszulesen und an den Entwickler zu schicken.
64 | Connector Update verfügbar
65 | Dieser Connector wird jetzt von einem anderen Entwickler betreut.\nBitte klicke hier, um den neuen Connector zu installieren.
66 |
67 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
23 |
24 | Ceci est un connecteur WebSMS.\nLa seule manière de l\'utiliser et de le démarrer à travers WebSMS
25 | WebSMS: envoi en cours
26 | Envoi en cours:
27 | ERREUR
28 | Connexion interrompue. Si votre connexion fonctionne, le problème est probablement une interruption du service. Vérifiez le site web de l\'application et twitter pour un statut.
29 | ECHEC: HTTP
30 | Adresse mail ou mot de passe incorrect !
31 | Nom d\'utilisateur ou mot de passe incorrect !
32 | Expéditeur invalide ! Utilisez le format international: +4917012345678.
33 | L\'expéditeur doit être validé et confirmé par votre fournisseur de service.
34 | ECHEC : réponse du serveur :
35 | Web-Service inaccessible ! Ceci n\'est très probablement pas un problème du connecteur. Veuillez réessayer plus tard. Vérifiez le site web de l\'application et twitter pour un statut.
36 | Captcha incorrect. Veuillez réessayer.
37 | Entête: Content-Length manque !
38 | Crédits insuffisants !
39 | Erreur dans la saisie utilisateur !
40 | Seuls des intervales de 15 minutes sont supportés par votre connecteur !
41 | Destinataire invalide !
42 | Message invalide !
43 | Cacher le sous-connecteur \"avec expéditeur\"
44 | Cacher le sous-connecteur \"sans expéditeur\"
45 | Cacher le sous-connecteur \"avec expéditeur\" de la sélection
46 | Cacher le sous-connecteur \"sans expéditeur\" de la sélection
47 | Cacher le sous-connecteur \"gratuit\"
48 | Cacher le sous-connecteur \"gratuit\" de la sélection
49 | Ignorer les erreurs de handshake SSL
50 | Ignorer les erreurs de handshake SSL. Certains téléphones n\'ont pas les certificats nécessaires installés. Utiliser cette option n\'est pas sûr.
51 | Nom d\'utilisateur
52 | Mot de passe
53 | Créer compte
54 | Utiliser expéditeur par défaut
55 | Utiliser expéditeur par défaut défini dans WebSMS
56 | Expéditeur custom
57 | Numéro de téléphone int., p.ex. +4917912345678
58 | Envoi des logs
59 | Envoi des logs de votre téléphone au développeur.\nNe faites cela que si on vous le demande.
60 | Exécuter SendLog
61 | SendLog va collecter les logs du téléphone et les envoyer au développeur.\nVous aurez l\'opportunité de visualiser et modifier les données avant l\'envoi.
62 | Installer SendLog
63 | Installer l\'application gratuite SendLog qui permet de collecter les logs du téléphone et de les envoyer au développeur.
64 | Mise à jour du connecteur disponible
65 | Le propriétaire de ce connecteur a changé.\nVeuillez cliquer ici pour installer la nouvelle application.
66 | Aucune connexion réseau de données disponible. Vérifiez les paramètres réseau.
67 |
68 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-hu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
23 |
24 | Ez egy WebSMS kiegészítő.\nKizárólag a WebSMS-el együtt haszálható!
25 | WebSMS: küldés
26 | Küldés:
27 | HIBA
28 | Kapcsolat időtúllépési hiba. Ha az internetkapcsolatod működik, akkor valószínűleg a cél szerverrel van a hiba. A program honlapján és twitter accountján általában be van jelentve ha valami gond van.
29 | HIBA: HTTP
30 | Hibás email cím, vagy jelszó!
31 | Hibás email cím, vagy jelszó!
32 | Hibás címzett! Nemzetközi számformátumot használj pl.: +4917012345678.
33 | A címzettnek regisztráltnak, és visszaigazoltnak kell lennie a szolgáltatódnál.
34 | HIBA: Szerver válasz:
35 | A szolgáltatás nem elérhető! Kérem próbálkozzon később újra.
36 | Hibás Captcha. Kérlek próbálkozz újra.
37 | Hiba a felhasználó által bevitt adatokban!
38 | Fejléc: Tartalom-hossz hiányzik!
39 | Csak 15 percnyi használatot engedélyez a kiegészítőd!
40 | Elrejtés \"feladóval\" alcsatoló
41 | \"Feladóval\" alcsatoló elrejtése a listában
42 | Elrejtés \"feladó nélkül\"
43 | Feladó nélkül gomb elrejtése
44 | Elrejtés \"ingyenes\" alcsatoló
45 | \"Ingyenes\" alcsatoló elrejtése a listából
46 | Felhasználónév
47 | Jelszó
48 | Fiók létrehozása
49 | Alapértelmezett küldő használata
50 | A WebSMS által megadott alapértelmezett küldő használata.
51 | Egyedi küldő
52 | Nemzetközi telefonszám pl.: +4917912345678
53 | Logok küldése
54 | Küldd be a program napló filejait a fejlesztőnek.\nCsak akkor küld be a fileokat, ha erre felkérést kaptál.
55 | SendLog futtatása
56 | SendLog a programmal kapcsolatos log fileokat gyájti össze, majd elküldi azokat a fejlesztőnek.\nAz elküldés előtt meg lesz alkalmad a beküldendő adatok átolvasására, és szerkesztésére.
57 | SendLog telepítése
58 | Telepítsd az ingyenes SendLog alkalmazást, a napló fájlok összegyűjtéséhez, és a fejlesztőnek való elküldéséhez.
59 | Elégtelen egyenleg!
60 | Érvénytelen címzett!
61 | Érvénytelen üzenet!
62 | SSL kommunikációs hibák figyelmen kívül hagyása
63 | SSL kommunikációs hibák figyelmen kívül hagyása. Néhány telefonon nincsenek a szükséges tanúsítványok telepítve. Ezt használva nem lesz biztonságos.
64 | Connector modul frissítés elérhető
65 | A Connector modul tulajdonosa megváltozott.\nNyomjon ide, hogy telepítse az új Alkalmazást.
66 | Nem érhető el adathálózat. Ellenőrizze a hálózati beállításokat.
67 |
68 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
23 |
24 | Questo è un Connector per WebSMS
25 | L\'unico modo per usarlo è lanciarlo con WebSMS.
26 | WebSMS: invio
27 | Invio:
28 | ERRORE
29 | Connessione terminata/scaduta. Se la connessione funziona, probabilmente si tratta di un guasto del servizio. Vedere il sito dell\'app per problemi e twitter per lo stato.
30 | Errore: HTTP
31 | Indirizzo o password errata!
32 | Nome utente o password errata!
33 | Mittente errato! Impostare nel formato internazionale. Es. +393201234567.
34 | Il mittente deve essere registrato e confermato dal provider.
35 | ERRORE: Risposta server:
36 | Il servizio web è down! Probabilmente non è un problema del Connector. Si prega di ritentare più tardi. Vedere il sito dell\'app per problemi e twitter per lo stato.
37 | Captcha errato. Ritenta.
38 | Errore nell\'immissione utente!
39 | Header: Content-Length mancante!
40 | Solo 15 minuti sono supportati dal connector!
41 | Nascondi SubConnector \"con mittente\"
42 | Nasconde il SubConnector \"con mittente\" dalla scelta.
43 | Nascondi SubConnector \"senza mittente\"
44 | Nasconde il SubConnector \"senza mittente\" dalla scelta.
45 | Nascondi SubConnector \"gratis\"
46 | Nasconde il SubConnector \"gratis\" dalla scelta.
47 | Nome utente
48 | Password
49 | Crea account
50 | Usa mittente predefinito
51 | Usa mittente predefinito su WebSMS
52 | Mittente personalizzato
53 | Numero internazionale Es. +393201234567
54 | Invia log
55 | Invia i log del dispositivo allo sviluppatore.
56 | Da fare solo se richiesto.
57 | Avvia SendLog
58 | SendLog raccoglierà i log del dispositivo e li invierà allo sviluppatore.
59 | Si avrà la possibilità di controllare e modificare i dati da inviare.
60 | Installa SendLog
61 | Installa l\'applicazione gratuita SendLog per raccogliere i log del dispositivo ed inviarli allo sviluppatore.
62 |
63 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-pt/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
20 | Este é um conector WebSMS.\nA única forma de o utilizar é com o WebSMS.
21 | WebSMS: envio...
22 | Envio:
23 | Erro
24 | A ligação foi fechada ou expirou. Se a ligação estiver a funcionar, é provável que exista um problema com o serviço. Saiba mais informações no twitter ou no sítio web da aplicação.
25 | Falha: HTTP
26 | Endereço eletrónico ou senha inválido(a)!
27 | Nome de utilizador ou senha inválido(a)!
28 | Remetente inválido! Defina um prefixo internacional válido. (Ex.:+351123456789)
29 | O remetente deve estar registado e confirmado pelo serviço.
30 | Falha: Resposta do servidor:
31 | O serviço web está desligado! Este erro não deve estar relacionado com o conector. Tente mais tarde. Saiba mais informações no twitter ou no sítio web da aplicação.
32 | Captcha inválido. Tente mais tarde.
33 | Erro nos dados introduzidos!
34 | Cabeçalho: Content-Length inexistente!
35 | Só pode utilizar este conector durante 15 minutos!
36 | Saldo insuficiente!
37 | Destinatário inválido!
38 | Mensagem inválida!
39 | Ocultar subconector \"com remetente\"
40 | Ocultar subconector \"com remetente\" da seleção.
41 | Ocultar subconector \"sem remetente\"
42 | Ocultar subconector \"sem remetente\" da seleção.
43 | Ocultar subconector \"gratuito\" da seleção.
44 | Ignorar erros SSL
45 | Ignorar erros SSL. Alguns dispositivos não possuem os certificados necesssários instalados. Esta opção comporta riscos de segurança.
46 | Nome de utilizador
47 | Senha
48 | Criar conta
49 | Utilizar remetente padrão
50 | Utilizar remetente disponibilizado pelo WebSMS.
51 | Remetente personalizado
52 | Prefixo internacional - +351123456789
53 | Enviar registos
54 | Enviar registos do dispositivo ao programador.\nNão o faça a menos que seja solicitado.
55 | Executar SendLog
56 | O SendLog irá recolher e enviar os registos do dispositivo ao programador.\nPode rever e alterar os dados enviados.
57 | Instalar SendLog
58 | Instale a aplicação SendLog para recolher e enviar os registos do dispositivo ao programador.
59 | Atualização de conector disponível
60 | A titularidade deste conector foi alterada.\nClique aqui para obter a nova aplicação.
61 | Sem rede de dados disponível. Verifique as definições de rede.
62 | Ocultar subconector \"gratuito\"
63 |
64 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-ro/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
23 |
24 | Acesta este un Conector WebSMS.\nUnica modalitate de a-l folosi este cu ajutorul aplicației WebSMS.
25 | WebSMS: trimitere
26 | Trimitere:
27 | EROARE
28 | Conexiune terminată/întârziată. Dacă aveți o conexiune care lucrează, cel mai probabil e o problemă a serviciului țintă. Verificați situl web al aplicației sau canalul Twitter pentru statut.
29 | EȘUARE: HTTP
30 | Adresa electronică sau parola sunt greșite!
31 | Numele de utilizator sau parola sunt greșite!
32 | Expeditor invalid! Setați-l în formă internațională, spre exemplu: +37369111111.
33 | Expeditorul trebuie să fie înregistrat și confirmat de către providerul Dvs.
34 | EȘUARE: RăspunsServer:
35 | Serviciul web e inaccesibil. Mai probabil nu e problema a Conectorului. Încercați mai târziu. Verificați situl web al aplicației sau canalul Twitter pentru statut.
36 | Codul captcha e greșit. Încercați încă o dată.
37 | Eroare în textul introdus!
38 | Header: Lipsște câmpul „Content-Length”!
39 | Conectorul Dvs. suportă doar intervale de 15 minute!
40 | Ascunde SubConectorul „cu expeditor”
41 | Ascunde SubConectorul „cu expeditor” din selecție.
42 | Ascunde SubConectorul „fără expeditor”
43 | Ascunde SubConectorul „fără expeditor” din selecție.
44 | Ascunde SubConectorul „gratis”
45 | Ascunde SubConectorul „gratis” din selecție.
46 | Ignoră erorile de conectare SSL
47 | Ignoră erorile de „handshake” SSL (conectare inițială). Unor modele de telefoane le lipsesc certificatele. Opțiunea dată duce la insecuritate.
48 | Nume
49 | Parolă
50 | Creează cont
51 | Expeditor implicit
52 | Folosește expeditorul implicit din WebSMS.
53 | Expeditor modificat
54 | Număr de telefon internațional, ex.: +37369111111
55 | Trimite jurnale
56 | Trimite jurnalele folosirii aplicației către dezvoltatorul acesteia. Bifați această opțiune doar dacă ați fost rugat s-o faceți.
57 | Rulează SendLog
58 | SendLog va colecta jurnalele telefonului și le va trimite dezvoltatorului aplicației. Veți putea modifica și redacta datele înainte de a fi trimise.
59 | Instalează SendLog
60 | Instealează aplicația gratuită SendLog pentru a colecta jurnalele telefonului și a le trimite dezvoltatorului aplicației.
61 | Actualizare disponibilă
62 | Proprietarul acestui Conector s-a schimbat.\nApăsați aici pentru a instala noua Aplicație.
63 |
64 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
23 |
24 | WebSMS: Отправка
25 | Отправка:
26 | ОШИБКА
27 | ОШИБКА: HTTP
28 | Неверный e-mail адрес или пароль!
29 | Неверное имя пользователя или пароль!
30 | Неверный номер отправителя! Введите в международном формате, напр. +79261234567.
31 | Данные отправителя должны быть зарегистрированы у Вашего провайдера.
32 | ОШИБКА: Ответ сервера:
33 | Сервис не доступен! Попробуйте позже.
34 | Неверная капча. Попробуйте снова.
35 | Ошибка ввода!
36 | Заголовок: неверное содержание-длина!
37 | Ваш коннектор поддерживает только полные 15 минут!
38 | Имя пользователя
39 | Пароль
40 | Создать аккаунт
41 | Использовать отправителя по умолчанию
42 | Использовать данные отправителя по умолчанию изнастроек WebSMS.
43 | Задать отправителя
44 | Номер телефона, напр. +79261234567
45 | Отправить журналы
46 | Отправить журналы устройства разработчику.\nОтправляйте только в том случае, если Вас об этом попросят.
47 | Запустить SendLog
48 | SendLog получит журнал устройства и отправит его разработчику.\nУ Вас будет возможность просмотреть и изменить отправляемые данные.
49 | Установить SendLog
50 | Установить бесплатное приложение SendLog для получения журнала устройства и отправки его разработчику.
51 | Подключение прекращено/истекло время ожидания. Если Ваше подключение работает, то, скорее всего, не работает целевая служба. Посмотрите список проблем на веб-сайте приложения и Twitter.
52 | Недостаточный баланс!
53 | Неверный получатель!
54 | Неверное сообщение!
55 | Доступно обновление Коннектора
56 | Изменился собственник этого Коннектора.\nПожалуйста, нажмите здесь для установки нового приложения.
57 | Сеть недоступна. Проверьте настройки сети.
58 | Это WebSMS Коннектор.\nЕдинственный способ использовать его, это совместный запуск с WebSMS.
59 | Игнорировать ошибки подтверждения SSL
60 | Игнорировать ошибки во время подтверждения SSL. Некоторые телефоны не имеют необходимых установленных сертификатов. Это приводит к незащищенности.
61 | Скрыть подчиненные коннекторы \"с отправителем\"
62 | Скрыть в выбранном подчиненные коннекторы \"с отправителем\".
63 | Скрыть подчиненные коннекторы \"без отправителя\"
64 | Скрыть в выбранном подчиненные коннекторы \"без отправителя\".
65 | Скрыть \"бесплатные\" подчиненные коннекторы
66 | Скрыть в выбранном \"бесплатные\" подчиненные коннекторы.
67 |
68 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-sk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values-tr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/WebSMSAPI/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
19 |
20 |
21 | This is a WebSMS Connector.\nThe only way to use it, is lauching it with WebSMS.
22 | WebSMS: sending
23 | Sending:
24 | ERROR
25 | Connection terminated/timed out. If your connection is working, it\'s most likely a downtime of the target service. Check the app\'s website issues and twitter for status.
26 | FAILURE: HTTP
27 | Wrong mail address or password given!
28 | Wrong username or password given!
29 | Wrong sender! Set it in international form like +4917012345678.
30 | Sender must be registered and confirmed your provider.
31 | FAILURE: Serverresponse:
32 | Webservice is down! This is most likely not a problem of the connector. Please try again later. Check the app\'s website\'s issues and twitter for status.
33 | Captcha was wrong. Please try again.
34 | Error in user input!
35 | Header: Content-Length is missing!
36 | Only full 15minutes are supported by your connector!
37 | Insufficant balance!
38 | Invalid recipient!
39 | Invalid message!
40 |
41 | Hide "with sender" SubConnector
42 | Hide "with sender" SubConnector from selection.
43 | Hide "without sender" SubConnector
44 | Hide "without sender" SubConnector from selection.
45 | Hide "free" SubConnector
46 | Hide "free" SubConnector from selection.
47 | Ignore SSL handshake errors
48 | Ignore errors during SSL handshake. Some phones do not have the needed certificates installed. Using this leads to insecurity.
49 |
50 | Username
51 | Password
52 | Create account
53 | Use default sender
54 | Use default sender provided by WebSMS.
55 | Custom sender
56 | Int. phonenumber e.g. +4917912345678
57 |
58 | Send logs
59 | Send your device\'s logs to the developer.\nDo this only if you was asked to do so.
60 | Run SendLog
61 | SendLog will collect the device log and send it to the developer.\nYou will have an opportunity to review and modify the data being sent.
62 | Install SendLog
63 | Install the free SendLog application to collect the device log and send it to the developer.
64 |
65 | Connector update available
66 | The ownership of this Connector has changed.\nPlease click here, to get the new App installed.
67 | No data network available. Check your network settings.
68 |
69 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | task wrapper(type: Wrapper) {
4 | gradleVersion = '2.2.1'
5 | }
6 |
--------------------------------------------------------------------------------
/doc/DeveloperFAQ.md:
--------------------------------------------------------------------------------
1 | # FAQ for developers
2 |
3 | ## How should I install a Connector on the emulator/device?
4 |
5 | When it comes to deploying the connectors to the emulator,
6 | I just run the adb install -r from shell.
7 | I don't know, how to install it from eclipse directly, because there is no activity (in fact there is the shared info screen) to run.
8 | If someone knows a better way, please contact me.
9 |
10 | ## How do I get the running ConnectorSpec?
11 |
12 | Just use:
13 |
14 | ConnectorSpec c = this.getSpec(context);
15 |
16 | Eg. to set balance you could use this code:
17 |
18 | String balance = getBalanceFromWebService(); // TODO implement me
19 | ConnectorSpec c = this.getSpec(context);
20 | c.setBalance(balance);
21 | Log.d(TAG, "balance: " + c.getBalance());
22 |
23 | ## In updateSpec() I get a ConnectorSpec object and I assumed that this is where I can update the balance since there is an setBalance method. As I do not have a ConnectorSpec object in doUpdate, I have to store the reference when updateSpec() initSpec() gets called and reuse it in doUpdate(). That might be the problem, but I haven't found another way so far. Is that the right method?
24 |
25 | Wrong.
26 | You must not do any network IO in `updateSpec()` or `initSpec()`.
27 | Just set the basic capabilities, features and settings in `updateSpec()` and `initSpec()`.
28 |
29 | Get the `ConnectorSpec` reference with `this.getSpec(context)` as mentioned above.
30 |
31 | ## More details
32 |
33 | See [DeveloperHelp](https://github.com/felixb/websms-api/blob/master/doc/DeveloperHelp.md) for more details.
34 |
--------------------------------------------------------------------------------
/doc/DeveloperHelp.md:
--------------------------------------------------------------------------------
1 | # If you want to code your own Connector, please read this page.
2 |
3 | ## Introduction
4 |
5 | WebSMS is built modular. This makes it very easy to implement new Connectors.
6 |
7 | Each Connector is installed separately.
8 | This makes it very easy to build your own Connector and even deploy it on your own!
9 |
10 | ## API
11 |
12 | You will need the public API of WebSMS's Connector framework.
13 |
14 | For examples, just check out the code on any of the connectors hosted on [github][1].
15 | Just pick the one, that fits you best.
16 | Some are using XML, some are using custom HTTP methods, some are using very simple HTTP APIs.
17 |
18 | Basically you just need to inherit the [Connector class][3] or even simpler the [BasicConnector class][4].
19 | But see the example or any other Connector for more details.
20 |
21 | With all this, you should be able to build and deploy your own Connector.
22 | If something is unclear. Do not hesitate to ask me.
23 |
24 | ## Architecture
25 |
26 | Here is a sequence diagram showing how the inner communication is working:
27 |
28 | ![Seqence diagram][5]
29 |
30 | The main app is just an activity with all it's GUI and logic behind.
31 | There is nothing special.
32 | But: It is not able to communicate with any web service without a Connector.
33 | Each connector is installed as single apk (only the GSM SMS Connector is shipped with WebSMS.apk).
34 | Each connector is living in it's own context.
35 |
36 | Communication is done with [Broadcasts][6].
37 | The WebSMS app is sending broadcast to the specific connector when running the update, bootstrap or send command,
38 | The connectors context will spawn here, if it's not alife anymore.
39 | The connector spawns (in most cases) a [Service][7], that may run in background without disturbing the user.
40 | This service runs a [AsyncTask][8] to do the network IO.
41 | At this point the API ends, this is where the `doBootstrap()`, `doUpdate()` or `doSend()` methods are called.
42 |
43 | As you might have seen, there are some more methods you could overwrite:
44 | * `initSpec()` is run once to initialisize some strings and stuff on spawning.
45 | * `getSpec()` is run, everytime it is needed. The Connector context will cache the actual instance.
46 |
47 | On startup, WebSMS will check, if the number of installed connectors has changed.
48 | If not: it will use the cached instances of all installed connectors.
49 | If it changed: it will clear the cache and run a broadcast (info request) to all connectors.
50 | They will spawn, run `initSpec()` and `getSpec()` and send back the instance to WebSMS. That's why no IO should be done in either of these methods.
51 |
52 | ## FAQ
53 |
54 | Please have a look on the [DeveloperFAQ][2].
55 |
56 | [1]: https://github.com/felixb/
57 | [2]: https://github.com/felixb/websms-sms/blob/master/doc/DeveloperFAQ.md
58 | [3]: https://github.com/felixb/websms-api/blob/master/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/Connector.java
59 | [4]: https://github.com/felixb/websms-api/blob/master/WebSMSAPI/src/main/java/de/ub0r/android/websms/connector/common/BasicConnector.java
60 | [5]: https://raw.githubusercontent.com/felixb/websms-api/master/doc/sequence.png
61 | [6]: http://developer.android.com/reference/android/content/BroadcastReceiver.html
62 | [7]: http://developer.android.com/reference/android/app/Service.html
63 | [8]: http://developer.android.com/reference/android/os/AsyncTask.html
64 |
--------------------------------------------------------------------------------
/doc/sequence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/doc/sequence.png
--------------------------------------------------------------------------------
/hi-res/promo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/hi-res/promo.png
--------------------------------------------------------------------------------
/hi-res/promo.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/hi-res/promo.xcf
--------------------------------------------------------------------------------
/hi-res/websms-connector-icon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/hi-res/websms-connector-icon-512x512.png
--------------------------------------------------------------------------------
/hi-res/websms-connector-icon-512x512_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/hi-res/websms-connector-icon-512x512_white.png
--------------------------------------------------------------------------------
/hi-res/websms-connector-icon.svgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/felixb/websms-api/3104ed0d2b20e9d4ec6a881f68ceaecd0ddb057a/hi-res/websms-connector-icon.svgz
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':WebSMSAPI'
2 |
--------------------------------------------------------------------------------