├── .gitignore
├── LICENSE.md
├── README.md
├── examples
├── SmsHomeStackApp
│ ├── .idea
│ │ ├── codeStyles
│ │ │ ├── Project.xml
│ │ │ └── codeStyleConfig.xml
│ │ ├── encodings.xml
│ │ ├── gradle.xml
│ │ ├── misc.xml
│ │ ├── render.experimental.xml
│ │ ├── runConfigurations.xml
│ │ └── vcs.xml
│ ├── README.md
│ ├── app
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── telefonica
│ │ │ │ └── lucferbux
│ │ │ │ └── homestacksms
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── telefonica
│ │ │ │ │ └── lucferbux
│ │ │ │ │ └── homestacksms
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ └── smsstack
│ │ │ │ │ ├── SmsStackRaspController.kt
│ │ │ │ │ └── SmsStackRaspLayer.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ │ ├── drawable
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ └── ic_lightbulb_outline_black_24dp.xml
│ │ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ └── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── telefonica
│ │ │ └── lucferbux
│ │ │ └── homestacksms
│ │ │ └── ExampleUnitTest.kt
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
└── sms-home-stack
│ ├── README.md
│ ├── requirements.txt
│ ├── sms_broadcaster.py
│ ├── sms_layer_rasp.py
│ ├── sms_stack_controller.py
│ └── stack_sms_base.py
├── paper
├── StackSMSPaper_v7.pdf
└── StackSMSPaper_v7_eng.pdf
├── sms-stack-android
├── .gitignore
├── .idea
│ ├── caches
│ │ └── build_file_checksums.ser
│ ├── encodings.xml
│ ├── gradle.xml
│ ├── misc.xml
│ ├── runConfigurations.xml
│ └── vcs.xml
├── LICENSE
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── lucferbux
│ │ │ └── smstcpsdk
│ │ │ └── ExampleInstrumentedTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── lucferbux
│ │ │ │ └── smstcpsdk
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── SMSTCPMessageApp.java
│ │ │ │ └── SMSTCPMessageLayer.java
│ │ └── res
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable
│ │ │ └── ic_launcher_background.xml
│ │ │ ├── layout
│ │ │ ├── activity_main.xml
│ │ │ └── content_main.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── lucferbux
│ │ └── smstcpsdk
│ │ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── smstcplibrary
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── example
│ │ └── smstcplibrary
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── smstcplibrary
│ │ │ ├── AESCipher.java
│ │ │ ├── BadKeyException.java
│ │ │ ├── SMSTCP.java
│ │ │ ├── SMSTCPAppLayer.java
│ │ │ ├── SMSTCPController.java
│ │ │ ├── SMSTCPLayer.java
│ │ │ ├── SMSTCPReceiver.java
│ │ │ ├── SMSTCPSender.java
│ │ │ └── SmsBroadcastReceiver.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── smstcplibrary
│ └── ExampleUnitTest.java
├── sms-stack-python
├── .gitignore
├── LICENSE
├── README.md
├── __init__.py
├── setup.py
└── sms_stack
│ ├── __init__.py
│ ├── cipher.py
│ ├── debug
│ ├── __init__.py
│ ├── sms_broadcast_im.py
│ ├── sms_mt_controller.py
│ └── sms_mt_layer.py
│ ├── sms_broadcaster.py
│ ├── sms_controller_observer.py
│ ├── sms_tcp.py
│ ├── sms_tcp_controller.py
│ ├── sms_tcp_layer.py
│ ├── sms_tcp_layer_formatter.py
│ ├── sms_tcp_receiver.py
│ ├── sms_tcp_sender.py
│ └── test
│ ├── __init__.py
│ ├── test_main.py
│ ├── test_sms_tcp_layer.py
│ └── test_sms_tcp_receiver.py
└── sms-stack-typescript
├── .gitignore
├── .prettierrc
├── README.md
├── jestconfig.json
├── package-lock.json
├── package.json
├── src
├── __tests__
│ └── Main.test.ts
├── arrayExt.ts
├── index.ts
├── smsTcp.ts
├── smsTcpAppLayer.ts
├── smsTcpController.ts
├── smsTcpControllerObserver.ts
├── smsTcpLayer.ts
├── smsTcpReceiver.ts
└── smsTcpSender.ts
├── tsconfig.json
└── tslint.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 |
27 | # PyInstaller
28 | # Usually these files are written by a python script from a template
29 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
30 | *.manifest
31 | *.spec
32 |
33 | # Installer logs
34 | pip-log.txt
35 | pip-delete-this-directory.txt
36 |
37 | # Unit test / coverage reports
38 | htmlcov/
39 | .tox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *,cover
46 |
47 | # Translations
48 | *.mo
49 | *.pot
50 |
51 | # Django stuff:
52 | *.log
53 |
54 | # Sphinx documentation
55 | docs/_build/
56 |
57 | # PyBuilder
58 | target/
59 |
60 | *.vscode
61 |
62 | # Logs
63 | logs
64 | *.log
65 | npm-debug.log*
66 | yarn-debug.log*
67 | yarn-error.log*
68 |
69 | # Runtime data
70 | pids
71 | *.pid
72 | *.seed
73 | *.pid.lock
74 |
75 | # Directory for instrumented libs generated by jscoverage/JSCover
76 | lib-cov
77 |
78 | # Coverage directory used by tools like istanbul
79 | coverage
80 |
81 | # nyc test coverage
82 | .nyc_output
83 |
84 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
85 | .grunt
86 |
87 | # Bower dependency directory (https://bower.io/)
88 | bower_components
89 |
90 | # node-waf configuration
91 | .lock-wscript
92 |
93 | # Compiled binary addons (https://nodejs.org/api/addons.html)
94 | build/Release
95 |
96 | # Dependency directories
97 | node_modules/
98 | jspm_packages/
99 |
100 | # TypeScript v1 declaration files
101 | typings/
102 |
103 | # Optional npm cache directory
104 | .npm
105 |
106 | # Optional eslint cache
107 | .eslintcache
108 |
109 | # Optional REPL history
110 | .node_repl_history
111 |
112 | # Output of 'npm pack'
113 | *.tgz
114 |
115 | # Yarn Integrity file
116 | .yarn-integrity
117 |
118 | # dotenv environment variables file
119 | .env
120 | .env.test
121 |
122 | # parcel-bundler cache (https://parceljs.org/)
123 | .cache
124 |
125 | # next.js build output
126 | .next
127 |
128 | # nuxt.js build output
129 | .nuxt
130 |
131 | # vuepress build output
132 | .vuepress/dist
133 |
134 | # Serverless directories
135 | .serverless/
136 |
137 | # FuseBox cache
138 | .fusebox/
139 |
140 | # DynamoDB Local files
141 | .dynamodb/
142 | \.vscode/
143 |
144 | lib/
145 |
146 | \.DS_Store
147 |
148 |
149 |
150 | *.iml
151 | .gradle
152 | /local.properties
153 | /.idea/libraries
154 | /.idea/modules.xml
155 | /.idea/workspace.xml
156 | /.DS_Store
157 | /build
158 | /captures
159 | /.externalNativeBuild
160 |
161 |
162 | /examples/SmsHomeStackApp/local.properties
163 | /examples/SmsHomeStackApp/.idea/caches
164 | /examples/SmsHomeStackApp/.idea/libraries
165 | /examples/SmsHomeStackApp/.idea/modules.xml
166 | /examples/SmsHomeStackApp/.idea/workspace.xml
167 | /examples/SmsHomeStackApp/.idea/navEditor.xml
168 | /examples/SmsHomeStackApp/.idea/assetWizardSettings.xml
169 | /examples/SmsHomeStackApp//build
170 | /examples/SmsHomeStackApp//captures
171 | /examples/SmsHomeStackApp//.externalNativeBuild
172 |
173 |
174 | paper/~\$ackSMSPaper\.docx
175 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # **SMS Stack**
4 | Sms Stack is a Framework to provide TPC/IP based characteristics to the GSM Short Message Service.
5 |
6 | This framework works in multiple environments to provide a full stack integration in a service.
7 |
8 | The main layer features techniques to control the order and the number of sms for a given stream, and a layer of security with AES + CTR cypher.
9 |
10 | You can easily implement your own protocol on the top of the stack of Sms Stack and add new features to an sms based communication between devices.
11 |
12 | # Prerequisites
13 | You can download and use sms-stack in multiple environments in order to implement it in multiple scenarios.
14 |
15 | ## Typescript
16 | Npm - https://www.npmjs.com
17 |
18 | Nodejs - https://nodejs.org/en/
19 |
20 | Typescript - https://www.typescriptlang.org/#download-links
21 |
22 | ## Python
23 | Python 3.4 or higher - https://www.python.org/downloads/
24 |
25 | Pip - https://pypi.org/project/pip/
26 |
27 | ## Android
28 | Android API 23 (6.0) or higher - https://developer.android.com/about/versions/marshmallow/android-6.0
29 |
30 | Android Studio + Gradle (With JUnit) - https://developer.android.com/studio/install
31 |
32 | # Usage
33 | Simply add the framework in one of each repositories given in your repository.
34 |
35 | ## Typescript
36 | ```npm install sms-stack 1.x.x```
37 |
38 | ## Python
39 | ```pip install sms-stack 1.x.x```
40 |
41 | ## Android
42 | Add in the gradle app file
43 | ```implementation 'com.example.smstcplibrary:smsstack:1.x.x'```
44 |
45 | For further implementation, please use the given wiki
46 |
47 | # SMS Stack scheme
48 |
49 |
50 |
51 |
52 | # License
53 |
54 | This project is licensed under the GNU General Public License - see the LICENSE file for details
55 |
56 | # Contact
57 |
58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
59 |
60 | This software doesn't have a QA Process. This software is a Proof of Concept.
61 |
62 | If you have any problems, you can contact:
63 |
64 | - *Ideas Locas CDO - Telefónica*
65 |
66 | - *Ideas Locas CDO - Telefónica*
67 |
68 | - *Ideas Locas CDO - Telefónica*
69 |
70 | For more information please visit [https://www.elevenpaths.com](https://www.elevenpaths.com).
71 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | xmlns:android
14 |
15 | ^$
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | xmlns:.*
25 |
26 | ^$
27 |
28 |
29 | BY_NAME
30 |
31 |
32 |
33 |
34 |
35 |
36 | .*:id
37 |
38 | http://schemas.android.com/apk/res/android
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | .*:name
48 |
49 | http://schemas.android.com/apk/res/android
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | name
59 |
60 | ^$
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | style
70 |
71 | ^$
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | .*
81 |
82 | ^$
83 |
84 |
85 | BY_NAME
86 |
87 |
88 |
89 |
90 |
91 |
92 | .*
93 |
94 | http://schemas.android.com/apk/res/android
95 |
96 |
97 | ANDROID_ATTRIBUTE_ORDER
98 |
99 |
100 |
101 |
102 |
103 |
104 | .*
105 |
106 | .*
107 |
108 |
109 | BY_NAME
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/.idea/render.experimental.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/README.md:
--------------------------------------------------------------------------------
1 | # Home Stack Python
2 |
3 |
4 | ```
5 | _ _ _____ _ _
6 | | | | | / ____| | | | /\
7 | | |__| | ___ _ __ ___ ___ | (___ | |_ __ _ ___| | __ / \ _ __ _ __
8 | | __ |/ _ \| '_ ` _ \ / _ \ \___ \| __/ _` |/ __| |/ / / /\ \ | '_ \| '_ \
9 | | | | | (_) | | | | | | __/ ____) | || (_| | (__| < / ____ \| |_) | |_) |
10 | |_| |_|\___/|_| |_| |_|\___| |_____/ \__\__,_|\___|_|\_\ /_/ \_\ .__/| .__/
11 | | | | |
12 | |_| |_|
13 |
14 | Created with ♥ by: 'Ideas Locas (CDO Telefonica)'
15 | ```
16 |
17 | Home Stack App is the companion app to comunicate to sms-home-stack server for Raspberry
18 |
19 |
20 | # Prerequisite
21 |
22 | * [Android Studio](https://developer.android.com/studio)
23 | * [Kotlin](https://kotlinlang.org)
24 | * [Sms Stack Sdk](https://mvnrepository.com/artifact/com.example.smstcplibrary/smsstack)
25 |
26 | # Authors
27 |
28 | This project has been developed by the team of 'Ideas Locas' (CDO - Telefónica). To contact the authors:
29 |
30 | * **Pablo Gonzázlez Perez** -- [@pablogonzalezpe](https://twitter.com/pablogonzalezpe) -- pablo.gonzalezperez@telefonica.com
31 | * **Fran Ramirez** -- [@Cybercaronte](https://twitter.com/Cybercaronte) -- franciscojose.ramirezvicente@telefonica.com
32 | * **Lucas Fernández Aragón** -- [@lucferbux](https://twitter.com/lucferbux) -- lucas.fernandezaragon@telefonica.com
33 |
34 |
35 | # Disclaimer!
36 |
37 | THE SOFTWARE (for educational purpose only) IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 |
39 | This software doesn't have a QA Process.
40 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | compileSdkVersion 27
9 | defaultConfig {
10 | applicationId "com.telefonica.lucferbux.homestacksms"
11 | minSdkVersion 24
12 | targetSdkVersion 27
13 | versionCode 1
14 | versionName "1.0"
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | compileOptions {
24 | sourceCompatibility 1.8
25 | targetCompatibility 1.8
26 | }
27 | }
28 |
29 | dependencies {
30 | implementation fileTree(dir: 'libs', include: ['*.jar'])
31 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
32 | implementation 'com.android.support:appcompat-v7:27.1.1'
33 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
34 | testImplementation 'junit:junit:4.12'
35 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
36 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
37 |
38 | // SMS STACK
39 | implementation 'com.example.smstcplibrary:smsstack:0.1.4'
40 |
41 | // Anko
42 | implementation "org.jetbrains.anko:anko:$anko_version"
43 |
44 | // Appcompat-v7 (Anko Layouts)
45 | implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"
46 | implementation "org.jetbrains.anko:anko-coroutines:$anko_version"
47 |
48 | // CardView-v7
49 | implementation "org.jetbrains.anko:anko-cardview-v7:$anko_version"
50 |
51 | // Design
52 | implementation "org.jetbrains.anko:anko-design:$anko_version"
53 | implementation "org.jetbrains.anko:anko-design-coroutines:$anko_version"
54 | implementation "org.jetbrains.anko:anko-commons:$anko_version"
55 |
56 | // RecyclerView-v7
57 | implementation "org.jetbrains.anko:anko-recyclerview-v7:$anko_version"
58 | implementation "org.jetbrains.anko:anko-recyclerview-v7-coroutines:$anko_version"
59 |
60 | // Support-v4 (only Anko Commons)
61 | implementation "org.jetbrains.anko:anko-support-v4-commons:$anko_version"
62 |
63 | // Support-v4 (Anko Layouts)
64 | implementation "org.jetbrains.anko:anko-support-v4:$anko_version"
65 |
66 | // ConstraintLayout
67 | implementation "org.jetbrains.anko:anko-constraint-layout:$anko_version"
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/androidTest/java/com/telefonica/lucferbux/homestacksms/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.telefonica.lucferbux.homestacksms
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.telefonica.lucferbux.homestacksms", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/java/com/telefonica/lucferbux/homestacksms/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.telefonica.lucferbux.homestacksms
2 |
3 | import android.support.v7.app.AppCompatActivity
4 | import android.os.Bundle
5 | import android.os.Handler
6 | import android.view.View
7 | import com.telefonica.lucferbux.homestacksms.smsstack.SmsStackRaspController
8 | import kotlinx.android.synthetic.main.activity_main.*
9 | import org.jetbrains.anko.sdk27.coroutines.onClick
10 | import org.jetbrains.anko.toast
11 |
12 | class MainActivity : AppCompatActivity() {
13 |
14 | private lateinit var smsStackController: SmsStackRaspController
15 |
16 | override fun onCreate(savedInstanceState: Bundle?) {
17 | super.onCreate(savedInstanceState)
18 | setContentView(R.layout.activity_main)
19 |
20 | smsStackController = SmsStackRaspController(this) {
21 | toast("Action performed")
22 | }
23 |
24 | bt_yellow_led.onClick {
25 | changeButton(16)
26 | }
27 |
28 | bt_green_led.onClick {
29 | changeButton(18)
30 | }
31 |
32 | bt_red_led.onClick {
33 | changeButton(17)
34 | }
35 | }
36 |
37 | fun changeButton(port: Int) {
38 | smsStackController.sendMessage(port)
39 |
40 | when(port) {
41 | 16 -> {
42 | toast("Message sent to Yellow led")
43 | pb_yellow.visibility = View.VISIBLE
44 | bt_yellow_led.isEnabled = false
45 | Handler().postDelayed(
46 | {
47 | changeStatusText(port)
48 | },
49 | 9000 // value in milliseconds
50 | )
51 | }
52 |
53 | 17 -> {
54 | toast("Message sent to Red led")
55 | pb_red.visibility = View.VISIBLE
56 | bt_red_led.isEnabled = false
57 | Handler().postDelayed(
58 | {
59 | changeStatusText(port)
60 | },
61 | 9000 // value in milliseconds
62 | )
63 | }
64 |
65 | 18 -> {
66 | toast("Message sent to Green led")
67 | pb_green.visibility = View.VISIBLE
68 | bt_green_led.isEnabled = false
69 | Handler().postDelayed(
70 | {
71 | changeStatusText(port)
72 | },
73 | 9000 // value in milliseconds
74 | )
75 | }
76 |
77 | else -> {
78 |
79 | }
80 | }
81 | }
82 |
83 | fun changeStatusText(port: Int) {
84 |
85 |
86 | when(port) {
87 | 16 -> {
88 | tv_yellow.text = if(tv_yellow.text.equals("ON")) "OFF" else "ON"
89 | pb_yellow.visibility = View.INVISIBLE
90 | bt_yellow_led.isEnabled = true
91 | }
92 |
93 | 17 -> {
94 | tv_red.text = if(tv_red.text.equals("ON")) "OFF" else "ON"
95 | pb_red.visibility = View.INVISIBLE
96 | bt_red_led.isEnabled = true
97 | }
98 |
99 | 18 -> {
100 | tv_green.text = if(tv_green.text.equals("ON")) "OFF" else "ON"
101 | pb_green.visibility = View.INVISIBLE
102 | bt_green_led.isEnabled = true
103 | }
104 |
105 | }
106 | }
107 |
108 | fun messageReceived(port: Int) {
109 |
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/java/com/telefonica/lucferbux/homestacksms/smsstack/SmsStackRaspController.kt:
--------------------------------------------------------------------------------
1 | package com.telefonica.lucferbux.homestacksms.smsstack
2 |
3 | import android.support.v7.app.AppCompatActivity
4 | import android.util.Log
5 | import com.example.smstcplibrary.SMSTCPController
6 | import com.example.smstcplibrary.SMSTCPLayer
7 | import java.util.ArrayList
8 |
9 | class SmsStackRaspController (appCompatActivity: AppCompatActivity, val messageReceive: (SmsStackRaspLayer) -> Unit) {
10 |
11 | companion object {
12 | // Phone numbers to send the message
13 | val PHONE_NUMBERS = arrayOf("34646980422")
14 | }
15 |
16 | // Instantiation of the controller with AES CBC and Cipher key
17 | val smsStackController = SMSTCPController(appCompatActivity, 1 , "PATATA")
18 |
19 | init {
20 | val completionHandler = object: SMSTCPController.CompletionHandler {
21 | override fun handleMessageSent() {
22 |
23 | }
24 |
25 | // Methods handling the messages
26 | override fun handleFinalMessageReceived(p0: ArrayList?, p1: Array?) {
27 | val smsAppLayer = p0?.let {
28 | SmsStackRaspLayer(smsStackController.processMessages(p0))
29 | } ?: run {
30 | return
31 | }
32 |
33 | messageReceive(smsAppLayer)
34 | Log.d("SMSSent", smsAppLayer.toString())
35 | }
36 |
37 | override fun handleFinalMessageSent() {
38 |
39 | }
40 |
41 | override fun handleMessageReceived(p0: SMSTCPLayer?, p1: Array?) {
42 |
43 | }
44 |
45 | }
46 |
47 | smsStackController.setCompletionHandler(completionHandler)
48 | }
49 |
50 | /**
51 | * Send Message to the device
52 | *
53 | * @param device Device to target
54 | */
55 | fun sendMessage(device: Int) {
56 | val smsLayer = SmsStackRaspLayer(100, device, 0, 0, "")
57 | smsStackController.sendMessage(smsLayer.encodeSMSApp(), PHONE_NUMBERS)
58 | }
59 |
60 |
61 | }
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/java/com/telefonica/lucferbux/homestacksms/smsstack/SmsStackRaspLayer.kt:
--------------------------------------------------------------------------------
1 | package com.telefonica.lucferbux.homestacksms.smsstack
2 |
3 | import com.example.smstcplibrary.SMSTCPAppLayer
4 | import com.example.smstcplibrary.SMSTCPLayer
5 |
6 | import java.math.BigInteger
7 |
8 | class SmsStackRaspLayer : SMSTCPAppLayer {
9 |
10 | companion object {
11 | val HEADER_SIZE = 6
12 | val HEADER_SIZE_BIN = HEADER_SIZE * 4
13 | }
14 |
15 | var idOrigin = 0b0
16 | var idTarget = 0b0
17 | var mod = 0b0
18 | var status = 0b0
19 | var data = ""
20 |
21 | constructor(idOrigin: Int, idTarget: Int, mod: Int, status: Int, data: String) {
22 | this.idOrigin = idOrigin
23 | this.idTarget = idTarget
24 | this.mod = mod
25 | this.status = status
26 | this.data = data
27 | }
28 |
29 | constructor(sms: String) {
30 | decodeSMSApp(sms)
31 | }
32 |
33 | override fun decodeSMSApp(s: String) {
34 | val headerMessage = SMSTCPLayer.fillHeader(hexToBinary(s.substring(0, HEADER_SIZE)), HEADER_SIZE_BIN)
35 | val dataMessage = s.substring(HEADER_SIZE, s.length)
36 | this.idOrigin = Integer.parseInt(headerMessage.substring(0, 8), 2)
37 | this.idTarget = Integer.parseInt(headerMessage.substring(8, 16), 2)
38 | this.mod = Integer.parseInt(headerMessage.substring(16, 21), 2)
39 | this.data = dataMessage
40 | }
41 |
42 | override fun encodeSMSApp(): String {
43 | val idOriginMessage = SMSTCPLayer.fillHeader(this.idOrigin, 8)
44 | val idTargetMessage = SMSTCPLayer.fillHeader(this.idTarget, 8)
45 | val modMessage = SMSTCPLayer.fillHeader(this.mod, 5)
46 | val statusMessage = SMSTCPLayer.fillHeader(this.status, 3)
47 |
48 | val headersBinary = idOriginMessage + idTargetMessage + modMessage + statusMessage
49 | val headersHexa =
50 | SMSTCPLayer.fillHeader(java.lang.Long.toHexString(java.lang.Long.parseLong(headersBinary, 2)), HEADER_SIZE)
51 |
52 | return headersHexa + this.data
53 | }
54 |
55 | override fun hexToBinary(s: String): String {
56 | return BigInteger(s, 16).toString(2)
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/drawable/ic_lightbulb_outline_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #00A9E0
4 | #007AAE
5 | #5BC500
6 | #EC6839
7 | #F59C00
8 | #ffffff
9 | #fcfcfc
10 | #000000
11 | #50535a
12 | #86888C
13 | #F8EC03
14 | #2C8D1D
15 | #E91414
16 |
17 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | HomeStackSms
3 |
4 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/app/src/test/java/com/telefonica/lucferbux/homestacksms/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.telefonica.lucferbux.homestacksms
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.21'
5 | ext.anko_version='0.10.8'
6 | repositories {
7 | google()
8 | jcenter()
9 |
10 | }
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:3.5.0'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 |
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Kotlin code style for this project: "official" or "obsolete":
15 | kotlin.code.style=official
16 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/examples/SmsHomeStackApp/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Nov 20 08:53:24 CET 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/examples/SmsHomeStackApp/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/examples/sms-home-stack/README.md:
--------------------------------------------------------------------------------
1 | # Home Stack Python
2 |
3 |
4 | ```
5 | _ _ _____ _ _ ______ _ _
6 | | | | | / ___|| | | | | ___ \ | | | |
7 | | |_| | ___ _ __ ___ ___ \ `--. | |_ __ _ ___ | | __ | |_/ / _ _ | |_ | |__ ___ _ __
8 | | _ | / _ \ | '_ ` _ \ / _ \ `--. \| __| / _` | / __|| |/ / | __/ | | | || __|| '_ \ / _ \ | '_ \
9 | | | | || (_) || | | | | || __/ /\__/ /| |_ | (_| || (__ | < | | | |_| || |_ | | | || (_) || | | |
10 | \_| |_/ \___/ |_| |_| |_| \___| \____/ \__| \__,_| \___||_|\_\ \_| \__, | \__||_| |_| \___/ |_| |_|
11 | __/ |
12 | |___/
13 |
14 | Created with ♥ by: 'Ideas Locas (CDO Telefonica)'
15 | ```
16 |
17 | Home Stack for Python is a tool that enables a second communication channel in any IoT device thanks to Sms Stack and a GSM Socket for Raspberry Pi.
18 |
19 |
20 | # Prerequisite
21 |
22 | * [GPIO board](https://sourceforge.net/projects/raspberry-gpio-python/)
23 | * [Python 3](https://www.python.org/download/releases/3.0/)
24 | * [Sms Stack Python](https://github.com/ElevenPaths/SDK-SMS-Stack)
25 |
26 |
27 | # Install
28 |
29 | * ```pip install -r requirements.txt```
30 |
31 |
32 | # Authors
33 |
34 | This project has been developed by the team of 'Ideas Locas' (CDO - Telefónica). To contact the authors:
35 |
36 | * **Pablo Gonzázlez Perez** -- [@pablogonzalezpe](https://twitter.com/pablogonzalezpe) -- pablo.gonzalezperez@telefonica.com
37 | * **Fran Ramirez** -- [@Cybercaronte](https://twitter.com/Cybercaronte) -- franciscojose.ramirezvicente@telefonica.com
38 | * **Lucas Fernández Aragón** -- [@lucferbux](https://twitter.com/lucferbux) -- lucas.fernandezaragon@telefonica.com
39 |
40 |
41 |
42 |
43 |
44 | # Disclaimer!
45 |
46 | THE SOFTWARE (for educational purpose only) IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
47 |
48 | This software doesn't have a QA Process.
49 |
--------------------------------------------------------------------------------
/examples/sms-home-stack/requirements.txt:
--------------------------------------------------------------------------------
1 | RPi.GPIO==0.7.0
2 | sms-stack
--------------------------------------------------------------------------------
/examples/sms-home-stack/sms_broadcaster.py:
--------------------------------------------------------------------------------
1 | from sms_stack.sms_broadcaster import SmsBroadcaster
2 | import time, sys
3 |
4 | class SmsBroadcast(SmsBroadcaster):
5 |
6 | def __init__(self, serial):
7 | """Implementation class of broadcaster, it sends the message through serial port encoding
8 |
9 | Args:
10 | serial (int): Serial code used to send the message
11 | """
12 |
13 | self.serial_port = serial
14 | self.send_message = 'AT+CMGS="{}"\r'
15 |
16 |
17 | def send_sms(self, sms, recipient):
18 | """Send and sms to a given recipient
19 |
20 | Args:
21 | sms (string): Sms Stack encoded sms
22 | recipient (string): Recipient of the sms
23 | """
24 |
25 | self.serial_port.write(str.encode(self.send_message.format(recipient)))
26 | time.sleep(1)
27 | self.serial_port.write(str.encode(sms + chr(26)))
28 | time.sleep(1)
29 |
30 |
--------------------------------------------------------------------------------
/examples/sms-home-stack/sms_layer_rasp.py:
--------------------------------------------------------------------------------
1 | from sms_stack.sms_tcp_layer_formatter import SmsTcpLayerFormatter
2 |
3 | class SmsTcpLayerRasp:
4 |
5 | def __init__(self, sms='', id_origin=None, id_target=None, mod=None, status=None, data=""):
6 | """Sms Stack Layer implementation
7 | sms (str, optional): Defaults to ''. Sms to decoded
8 | id_origin (int, optional): Defaults to None. Identifier of the origin device
9 | id_target (int, optional): Defaults to None. Identifier of the targeted device
10 | mod (int, optional): Defaults to None. ???
11 | status (int, optional): Defaults to None. [description]
12 | data (str, optional): Defaults to "". Data to send, currently unavailable
13 | """
14 |
15 | if(sms != ''):
16 | self._decode_sms(sms)
17 | elif(id_origin != None, id_target != None, mod != None, status != None,):
18 | self.id_origin = id_origin
19 | self.id_target = id_target
20 | self.mod = mod
21 | self.status = status
22 | self.data = data
23 |
24 |
25 | def _decode_sms(self, sms):
26 | """Decodes the sms received
27 |
28 | Args:
29 | sms (string): Encoded sms
30 | """
31 |
32 | try:
33 | header_sms = SmsTcpLayerFormatter.fill_header_string(SmsTcpLayerFormatter.hex_to_binary(sms[0:6]), 24)
34 | self.data = sms[6:]
35 | self.id_origin = int(header_sms[0:8], 2)
36 | self.id_target = int(header_sms[8:16], 2)
37 | self.mod = int(header_sms[16:21], 2)
38 | self.status = int(header_sms[21:], 2)
39 | except Exception as e:
40 | print("Bad length exception --->" + e)
41 |
42 |
43 | def enconde_sms(self):
44 | """Encode the Sms Stack Layer into a string sms
45 |
46 | Returns:
47 | str: Sms Encoded
48 | """
49 |
50 | id_origin = SmsTcpLayerFormatter.fill_header_binary(self.id_origin, 8)
51 | id_target = SmsTcpLayerFormatter.fill_header_binary(self.id_target, 8)
52 | mod = SmsTcpLayerFormatter.fill_header_binary(self.mod, 5)
53 | status = SmsTcpLayerFormatter.fill_header_binary(self.status, 3)
54 |
55 | headers_binary = id_origin + id_target + mod + status
56 | headers_hexa = SmsTcpLayerFormatter.fill_header_string(SmsTcpLayerFormatter.binary_to_hex(headers_binary), 6)
57 |
58 | return headers_hexa + self.data
59 |
60 |
--------------------------------------------------------------------------------
/examples/sms-home-stack/sms_stack_controller.py:
--------------------------------------------------------------------------------
1 | from sms_stack.sms_controller_observer import SmsControllerObserver
2 | from sms_stack.sms_tcp_controller import SmsTcpController
3 | from sms_stack.sms_tcp_layer import SmsTcpLayer
4 |
5 | class SmsStackController(SmsControllerObserver):
6 |
7 | def __init__(self, broadcast_send, callback_message):
8 | """Implementation of Sms Stack Controller
9 |
10 | Args:
11 | broadcast_send (BroadcastSender): The broadcast object to send sms
12 | callback_message (function): Callback function to retrieve the message
13 | """
14 |
15 | super().__init__()
16 | # Initialize the controller with the chipher key PATATA in AES CBC
17 | self.controller = SmsTcpController(self, broadcast_send, cipher_mode=1, cipher_key='PATATA')
18 | self.callback_message = callback_message
19 |
20 | # Handler message methods
21 | def handle_final_message_received(self, messages, sender):
22 | message = self.controller.process_message(messages)
23 | self.callback_message(message)
24 |
25 |
26 | def handle_message_received(self, layer, sender):
27 | return
28 |
29 |
30 | def handle_final_message_sent(self, messages, recipient):
31 | return
32 |
33 |
34 | def handle_message_sent(self, layer, recipient):
35 | return
36 |
37 | def send_message(self, sms, recipient="", recipients=[]):
38 | """Send message to a number
39 |
40 | Args:
41 | sms (string): Sms Stack encoded sms
42 | recipient (str, optional): Defaults to "". Recipient to send the message
43 | recipients (list, optional): Defaults to []. List of recipients to send the message
44 | """
45 | sms_layer = SmsTcpLayer(sms=sms)
46 | message = sms_layer.enconde_sms()
47 |
48 | recipients.append(recipient)
49 | for rec in recipients:
50 | self.controller.send_message(message, rec)
51 |
52 | def message_received(self, sms, sender):
53 | """Method to control a new message received
54 |
55 | Args:
56 | sms (string): Message encoded
57 | sender (string): Number of the sender
58 | """
59 | self.controller.receive_message(sms, sender)
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/examples/sms-home-stack/stack_sms_base.py:
--------------------------------------------------------------------------------
1 | # Ideas Locas CDO
2 | # SMS Stack test server
3 | # Based on SIMSMS1.py
4 | # http://www.python-exemplary.com/
5 |
6 | import RPi.GPIO as GPIO
7 | import serial
8 | import time, sys
9 | import datetime
10 | import re
11 |
12 | from sms_stack_controller import SmsStackController
13 | from sms_broadcaster import SmsBroadcast
14 | from sms_layer_rasp import SmsTcpLayerRasp
15 |
16 | # GPIO management
17 | P_BUTTON = 24 # Example, response wiring button GPIO
18 |
19 | # Serial port
20 | #SERIAL_PORT = "/dev/ttyAMA0" # Raspberry Pi 2
21 | SERIAL_PORT = "/dev/ttyS0" # Raspberry Pi 3
22 |
23 | class StackServerSMS(object):
24 |
25 | def __init__(self):
26 | self.text_mode = 'AT+CMGF=1\r'
27 | self.read_first_message = 'AT+CMGR=1\r'
28 | self.del_all_message = 'AT+CMGDA="DEL ALL"\r'
29 | self.read_unread_messages = 'AT+CMGL="REC UNREAD"\r'
30 | self.del_read_messages = 'AT+CMGD=0,1\r'
31 | self.lightbull = False
32 | self.serial_port = serial.Serial(SERIAL_PORT, baudrate = 9600, timeout = 5)
33 | self.sender = SmsBroadcast(self.serial_port)
34 | self.sms_stack_controller = SmsStackController(self.sender, self.message_processed)
35 | self.enable_sms()
36 |
37 | # GPIO initialization and definitions
38 | def setup_gpio(self):
39 | GPIO.setmode(GPIO.BOARD)
40 | GPIO.setup(P_BUTTON, GPIO.IN, GPIO.PUD_UP)
41 |
42 | def enable_sms(self):
43 | """Enables all the sms capabilities in the GPIO base
44 | """
45 |
46 | # GPIO Initialization
47 | self.setup_gpio() # init
48 | self.serial_port.write(str.encode(self.text_mode)) # set to text mode
49 | time.sleep(1)
50 | self.serial_port.write(str.encode(self.del_all_message))
51 | time.sleep(1)
52 | self.serial_port.read(self.serial_port.inWaiting()) # Clean buf
53 |
54 | def receive_sms(self):
55 | print("Listening for incomming Stack SMS...")
56 | while True:
57 | try:
58 | self.serial_port.write(str.encode(self.read_unread_messages))
59 | time.sleep(1)
60 | reply = self.serial_port.read(self.serial_port.inWaiting()).decode()
61 |
62 | if "CMGL:" in reply:
63 | self.process_messages(reply)
64 | self.delete_messages()
65 |
66 | time.sleep(1)
67 | except KeyboardInterrupt:
68 | break
69 |
70 | def process_messages(self, reply):
71 | response_list = self.parse_sms(reply)
72 | for response in response_list:
73 | self.sms_stack_controller.message_received(response[0], response[1])
74 |
75 |
76 | @staticmethod
77 | def message_processed(message):
78 | """Process message received
79 |
80 | Args:
81 | message (str): Message received
82 | """
83 |
84 | stack_layer = SmsTcpLayerRasp(sms=message)
85 | print("Hemos recibido id_origin: {}".format(stack_layer.id_origin))
86 | print("Hemos recibido id_sender: {}".format(stack_layer.id_target))
87 | print("Hemos recibido mod: {}".format(stack_layer.mod))
88 | print("Hemos recibido status: {}".format(stack_layer.status))
89 |
90 |
91 | def delete_messages(self):
92 | """Delete a message once is read
93 | """
94 |
95 | self.serial_port.write(str.encode(self.del_read_messages)) # delete read nessages
96 | time.sleep(1)
97 | self.serial_port.read(self.serial_port.inWaiting()) # Clear buf
98 |
99 |
100 | def parse_sms(self, sms):
101 | """Due to bad formatting in GPIO, parsing method to retrieve the actual message
102 |
103 | Args:
104 | sms (str): Bad formatted messsage
105 |
106 | Returns:
107 | str: Message retrieved
108 | """
109 |
110 | res = []
111 | match = re.findall("\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\n(.+)\n", sms)
112 |
113 | for each in match:
114 | res.append((each[5], each[2][1:-1]))
115 | return res
116 |
117 | if __name__ == "__main__":
118 | print("Stack SMS server, initializing ...")
119 | stacksms=StackServerSMS()
120 |
121 | stacksms.receive_sms()
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/paper/StackSMSPaper_v7.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/paper/StackSMSPaper_v7.pdf
--------------------------------------------------------------------------------
/paper/StackSMSPaper_v7_eng.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/paper/StackSMSPaper_v7_eng.pdf
--------------------------------------------------------------------------------
/sms-stack-android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/libraries
5 | /.idea/modules.xml
6 | /.idea/workspace.xml
7 | .DS_Store
8 | /build
9 | /captures
10 | .externalNativeBuild
11 |
12 | \.idea/caches/gradle_models\.ser
13 |
--------------------------------------------------------------------------------
/sms-stack-android/.idea/caches/build_file_checksums.ser:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/.idea/caches/build_file_checksums.ser
--------------------------------------------------------------------------------
/sms-stack-android/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/sms-stack-android/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/sms-stack-android/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/sms-stack-android/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sms-stack-android/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/sms-stack-android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/sms-stack-android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 27
5 | defaultConfig {
6 | applicationId "com.example.lucferbux.smstcpsdk"
7 | minSdkVersion 24
8 | targetSdkVersion 27
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | testOptions {
20 | unitTests.returnDefaultValues = true
21 | }
22 | compileOptions {
23 | sourceCompatibility JavaVersion.VERSION_1_8
24 | targetCompatibility JavaVersion.VERSION_1_8
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(dir: 'libs', include: ['*.jar'])
30 | implementation 'com.android.support:appcompat-v7:27.1.1'
31 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
32 | implementation 'com.android.support:design:27.1.1'
33 | testImplementation 'junit:junit:4.12'
34 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
35 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
36 | implementation project(path: ':smstcplibrary')
37 | }
38 |
--------------------------------------------------------------------------------
/sms-stack-android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/androidTest/java/com/example/lucferbux/smstcpsdk/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.lucferbux.smstcpsdk;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.example.lucferbux.smstcpsdk", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/java/com/example/lucferbux/smstcpsdk/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.lucferbux.smstcpsdk;
2 |
3 | import android.content.pm.PackageManager;
4 | import android.os.Bundle;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.support.design.widget.FloatingActionButton;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.support.v7.widget.Toolbar;
10 | import android.view.Menu;
11 | import android.view.MenuItem;
12 | import android.view.View;
13 | import android.widget.Switch;
14 | import android.widget.TextView;
15 | import android.widget.Toast;
16 |
17 | import com.example.smstcplibrary.SMSTCPController;
18 | import com.example.smstcplibrary.SMSTCPLayer;
19 |
20 | public class MainActivity extends AppCompatActivity {
21 |
22 | String message;
23 | TextView mSMSTextView;
24 | TextView mSMSTextDestinataryView;
25 |
26 | SMSTCPMessageApp smsListener;
27 | TextView mSMSDisplayID;
28 | TextView mSMSDisplayKey;
29 |
30 | TextView mSMSDisplaySyn;
31 | TextView mSMSDisplayAck;
32 | TextView mSMSDisplayPsh;
33 | TextView mSMSDisplayFin;
34 | TextView mSMSDisplaySbegin;
35 | TextView mSMSDisplayCipher;
36 |
37 | Switch mAckSWitch;
38 |
39 |
40 | TextView mSMSDisplayData;
41 |
42 |
43 | @Override
44 | protected void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | setContentView(R.layout.activity_main);
47 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
48 | setSupportActionBar(toolbar);
49 |
50 | mSMSTextView = (TextView) findViewById(R.id.tv_sms_content);
51 | mSMSTextDestinataryView = (TextView) findViewById(R.id.tv_sms_dest);
52 | mSMSDisplayID = (TextView) findViewById(R.id.tv_id_display);
53 | mSMSDisplayKey = (TextView) findViewById(R.id.tv_key_display);
54 | mSMSDisplayData = (TextView) findViewById(R.id.tv_data_app_display);
55 | mSMSDisplaySyn = (TextView) findViewById(R.id.tv_syn_display);
56 | mSMSDisplayAck = (TextView) findViewById(R.id.tv_ack_display);
57 | mSMSDisplayPsh = (TextView) findViewById(R.id.tv_psh_display);
58 | mSMSDisplayFin = (TextView) findViewById(R.id.tv_fin_display);
59 | mSMSDisplaySbegin = (TextView) findViewById(R.id.tv_sBegin_display);
60 | mSMSDisplayCipher = (TextView) findViewById(R.id.tv_cipher_display);
61 | mAckSWitch = findViewById((R.id.response_switch));
62 |
63 |
64 | String[] phoneNo = {mSMSTextDestinataryView.getText().toString()};
65 |
66 | smsListener = new SMSTCPMessageApp(this,0);
67 |
68 | smsListener.setListener(new SMSTCPMessageApp.ListenerApp() {
69 | @Override
70 | public void onTextProcessed(final String message) {
71 | new Handler(Looper.getMainLooper()).post(new Runnable() {
72 | @Override
73 | public void run() {
74 | mSMSDisplayData.setText(message);
75 | }
76 | });
77 |
78 | }
79 | @Override
80 | public void onSMSRecived(SMSTCPLayer smstcpLayer) {
81 | mSMSDisplayID.setText(Integer.toString(smstcpLayer.id));
82 | mSMSDisplayKey.setText(Integer.toString(smstcpLayer.key));
83 | mSMSDisplaySyn.setText(Integer.toString(smstcpLayer.syn));
84 | mSMSDisplayAck.setText(Integer.toString(smstcpLayer.ack));
85 | mSMSDisplayPsh.setText(Integer.toString(smstcpLayer.psh));
86 | mSMSDisplayFin.setText(Integer.toString(smstcpLayer.fin));
87 | mSMSDisplaySbegin.setText(Integer.toString(smstcpLayer.sBegin));
88 | mSMSDisplayCipher.setText(Integer.toString(smstcpLayer.cipher));
89 | }
90 | });
91 |
92 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
93 | fab.setOnClickListener(new View.OnClickListener() {
94 | @Override
95 | public void onClick(View view) {
96 | sendSMS();
97 | }
98 | });
99 | }
100 |
101 | private void sendSMS() {
102 | String[] phoneNo = {mSMSTextDestinataryView.getText().toString()};
103 | smsListener.sendNewMessage(mSMSTextView.getText().toString(), phoneNo, mAckSWitch.isChecked());
104 | }
105 |
106 | @Override
107 | public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
108 | switch (requestCode) {
109 | case 0: {
110 | if (grantResults.length > 0
111 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
112 | Toast.makeText(getApplicationContext(),
113 | "Permission Granted", Toast.LENGTH_LONG).show();
114 | } else {
115 | Toast.makeText(getApplicationContext(),
116 | "Request failed, please accept to make the app work", Toast.LENGTH_LONG).show();
117 |
118 | }
119 | return;
120 | }
121 | }
122 |
123 | }
124 |
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/java/com/example/lucferbux/smstcpsdk/SMSTCPMessageApp.java:
--------------------------------------------------------------------------------
1 | package com.example.lucferbux.smstcpsdk;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.widget.Toast;
5 |
6 | import com.example.smstcplibrary.SMSTCPController;
7 | import com.example.smstcplibrary.SMSTCPLayer;
8 |
9 | import java.util.ArrayList;
10 |
11 | public class SMSTCPMessageApp {
12 |
13 | private String[] phoneNumbers;
14 | private ListenerApp listener;
15 | private SMSTCPController smsTCPController;
16 | private AppCompatActivity activity;
17 |
18 | public SMSTCPMessageApp(AppCompatActivity activitySms, int cipherMode){
19 | this.activity = activitySms;
20 | this.smsTCPController = new SMSTCPController(activitySms, 1, "PATATA");
21 |
22 | smsTCPController.setCompletionHandler(new SMSTCPController.CompletionHandler() {
23 |
24 | @Override
25 | public void handleFinalMessageReceived(ArrayList messages, String[] senderNumber) {
26 | try{
27 | String message = smsTCPController.processMessages(messages);
28 | listener.onTextProcessed(message);
29 | } catch (Exception e) {
30 |
31 | }
32 |
33 | }
34 |
35 | @Override
36 | public void handleMessageReceived(SMSTCPLayer smsTCP, String[] senderNumber) {
37 | try {
38 | listener.onSMSRecived(smsTCP);
39 | } catch (Exception e) {
40 | e.printStackTrace();
41 | }
42 | }
43 |
44 | @Override
45 | public void handleFinalMessageSent() {
46 | try {
47 | onMessageSent();
48 | } catch (Exception e) {
49 | e.printStackTrace();
50 | }
51 |
52 | }
53 |
54 | @Override
55 | public void handleMessageSent() {
56 |
57 | }
58 | });
59 | }
60 |
61 |
62 | public void sendNewMessage(String text, String[] phoneNo, Boolean ackBack) {
63 | smsTCPController.sendMessage(text, phoneNo, ackBack);
64 | }
65 |
66 | public void onMessageSent() {
67 | Toast.makeText(this.activity.getApplicationContext(), "SMS sent.",
68 | Toast.LENGTH_LONG).show();
69 | }
70 |
71 | public void setListener(ListenerApp listener) {
72 | this.listener = listener;
73 | }
74 |
75 | public interface ListenerApp {
76 | void onTextProcessed(String message);
77 | void onSMSRecived(SMSTCPLayer smstcpLayer);
78 | }
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/java/com/example/lucferbux/smstcpsdk/SMSTCPMessageLayer.java:
--------------------------------------------------------------------------------
1 | package com.example.lucferbux.smstcpsdk;
2 |
3 | import com.example.smstcplibrary.SMSTCPAppLayer;
4 | import com.example.smstcplibrary.SMSTCPLayer;
5 |
6 | import java.math.BigInteger;
7 |
8 | public class SMSTCPMessageLayer implements SMSTCPAppLayer {
9 |
10 | public int mode = 0b0;
11 | public int ack = 0b0;
12 | public int status = 0b0;
13 | public int sBegin = 0b0;
14 | public int id = 0b0;
15 | public String data;
16 |
17 | public SMSTCPMessageLayer(int mode, int ack, int status, int sBegin, int id, String data) {
18 | this.mode = mode;
19 | this.ack = ack;
20 | this.status = status;
21 | this.sBegin = sBegin;
22 | this.id = id;
23 | this.data = data;
24 | }
25 |
26 | public SMSTCPMessageLayer(String sms) {
27 | decodeSMSApp(sms);
28 | }
29 |
30 | @Override
31 | public void decodeSMSApp(String s) {
32 | String headerMessage = SMSTCPLayer.fillHeader(hexToBinary(s.substring(0, 4)), 16);
33 | String dataMessage = s.substring(4, s.length());
34 | this.mode = Integer.parseInt(headerMessage.substring(0,4), 2);
35 | this.ack = Integer.parseInt(headerMessage.substring(4,5), 2);
36 | this.status = Integer.parseInt(headerMessage.substring(5,6), 2);
37 | this.sBegin = Integer.parseInt(headerMessage.substring(6,12), 2);
38 | this.id = Integer.parseInt(headerMessage.substring(12,16), 2);
39 | this.data = dataMessage;
40 | }
41 |
42 |
43 | @Override
44 | public String encodeSMSApp() {
45 | String modeMessage = SMSTCPLayer.fillHeader(this.mode, 4);
46 | String ackMessage = SMSTCPLayer.fillHeader(this.ack, 1);
47 | String statusMessage = SMSTCPLayer.fillHeader(this.status, 1);
48 | String sBeginMessage = SMSTCPLayer.fillHeader(this.sBegin, 6);
49 | String idMessage = SMSTCPLayer.fillHeader(this.id, 4);
50 |
51 | String headersBinary = modeMessage + ackMessage + statusMessage + sBeginMessage + idMessage;
52 | String headersHexa = SMSTCPLayer.fillHeader(Long.toHexString(Long.parseLong(headersBinary, 2)), 4);
53 |
54 | return headersHexa + this.data;
55 | }
56 |
57 | @Override
58 | public String hexToBinary(String s) {
59 | return new BigInteger(s, 16).toString(2);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 16dp
3 |
4 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SmsTcpSDK
3 | MainActivity
4 |
5 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/sms-stack-android/app/src/test/java/com/example/lucferbux/smstcpsdk/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.lucferbux.smstcpsdk;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/sms-stack-android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.21'
5 |
6 | repositories {
7 | google()
8 | jcenter()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.4.0'
12 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
13 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
15 |
16 | // NOTE: Do not place your application dependencies here; they belong
17 | // in the individual module build.gradle files
18 | }
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | google()
24 | jcenter()
25 | }
26 | }
27 |
28 | task clean(type: Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/sms-stack-android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
--------------------------------------------------------------------------------
/sms-stack-android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/sms-stack-android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri May 03 13:02:32 CEST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/sms-stack-android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/sms-stack-android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/sms-stack-android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':smstcplibrary'
2 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android-extensions'
3 | apply plugin: 'kotlin-android'
4 |
5 | android {
6 | compileSdkVersion 27
7 |
8 |
9 |
10 | defaultConfig {
11 | minSdkVersion 24
12 | targetSdkVersion 27
13 | versionCode 13
14 | versionName "1.1.0"
15 |
16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
17 |
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | testOptions {
27 | unitTests.returnDefaultValues = true
28 | }
29 | compileOptions {
30 | sourceCompatibility JavaVersion.VERSION_1_8
31 | targetCompatibility JavaVersion.VERSION_1_8
32 | }
33 |
34 | }
35 |
36 | ext {
37 | bintrayRepo = 'SmsStack'
38 | bintrayName = 'SmsStack'
39 |
40 | publishedGroupId = 'com.example.smstcplibrary'
41 | libraryName = 'SmsStack'
42 | artifact = 'smsstack'
43 |
44 | libraryDescription = 'TCP layer over SMS'
45 |
46 | siteUrl = 'https://github.com/ElevenPaths/SDK-SMS-Stack'
47 | gitUrl = 'https://github.com/ElevenPaths/SDK-SMS-Stack.git'
48 |
49 | libraryVersion = '1.1.0'
50 |
51 | developerId = 'lucferbux'
52 | developerName = 'Lucas Fernandez'
53 | developerEmail = 'lucas.fernandezaragon@telefonica.com'
54 |
55 | licenseName = 'GNU General Public License v3.0'
56 | licenseUrl = 'https://www.gnu.org/licenses/gpl-3.0.en.html'
57 | allLicenses = ["GPL-3.0"]
58 | }
59 |
60 |
61 | dependencies {
62 | implementation fileTree(dir: 'libs', include: ['*.jar'])
63 |
64 | implementation 'com.android.support:appcompat-v7:27.1.1'
65 | implementation 'com.scottyab:aescrypt:0.0.1'
66 | testImplementation 'junit:junit:4.12'
67 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
68 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
69 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
70 | }
71 |
72 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
73 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'
74 | repositories {
75 | mavenCentral()
76 | }
77 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/androidTest/java/com/example/smstcplibrary/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.example.smstcplibrary.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/AESCipher.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import android.util.Base64;
4 |
5 | import java.io.UnsupportedEncodingException;
6 | import java.lang.reflect.Array;
7 | import java.security.GeneralSecurityException;
8 | import java.security.MessageDigest;
9 | import java.security.NoSuchAlgorithmException;
10 | import java.security.SecureRandom;
11 | import java.util.Arrays;
12 |
13 | import javax.crypto.Cipher;
14 | import javax.crypto.SecretKey;
15 | import javax.crypto.spec.IvParameterSpec;
16 | import javax.crypto.spec.SecretKeySpec;
17 |
18 | public class AESCipher {
19 |
20 | /**
21 | * Decrypt an AES/CTR wit No Padding message
22 | * @param secret AES Secret
23 | * @param buffer Message in bytes
24 | * @return Message decrypted
25 | * @throws GeneralSecurityException
26 | */
27 | public static byte[] decryptAES(SecretKey secret, byte[] buffer) throws GeneralSecurityException {
28 | Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
29 | int n = cipher.getBlockSize();
30 | byte[] ivData = Arrays.copyOf(buffer, n);
31 | cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivData));
32 | byte[] clear = cipher.doFinal(buffer, n, buffer.length - n);
33 |
34 | return clear;
35 | }
36 |
37 | /**
38 | * Decrypt an AES/CTR wit No Padding message
39 | * @param secret AES Secret
40 | * @param message Message String
41 | * @return Message decrypted
42 | * @throws GeneralSecurityException
43 | * @throws UnsupportedEncodingException
44 | */
45 | public static String decryptAES(String secret, String message) throws GeneralSecurityException, UnsupportedEncodingException {
46 | byte[] encodedString = Base64.decode(message, Base64.DEFAULT);
47 | SecretKey secretKey = generateSecretKey(secret);
48 | byte[] decodedMessage = decryptAES(secretKey, encodedString);
49 | return new String(decodedMessage, "UTF-8");
50 | }
51 |
52 |
53 | /**
54 | * Encrypt an AES/CTR wit No Padding message
55 | * @param secret AES Secret
56 | * @param buffer Message in bytes
57 | * @return Message encrypted
58 | * @throws GeneralSecurityException
59 | */
60 | public static byte[] encryptAES(SecretKey secret, byte[] buffer) throws GeneralSecurityException {
61 | Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
62 | SecureRandom rng = new SecureRandom();
63 | byte[] ivData = new byte[cipher.getBlockSize()];
64 | rng.nextBytes(ivData);
65 | cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(ivData));
66 | byte[] ciphertext = cipher.doFinal(buffer);
67 | return concatenate(ivData, ciphertext);
68 | }
69 |
70 |
71 | /**
72 | * Encrypt an AES/CTR wit No Padding message
73 | * @param secret AES Secret
74 | * @param message Message String
75 | * @return Message encrypted
76 | * @throws GeneralSecurityException
77 | * @throws UnsupportedEncodingException
78 | */
79 | public static String encryptAES(String secret, String message) throws GeneralSecurityException, UnsupportedEncodingException {
80 | SecretKey secretKey = generateSecretKey(secret);
81 | byte[] finalMessage = message.getBytes();
82 | byte[] encodedMessage = encryptAES(secretKey, finalMessage);
83 | return Base64.encodeToString(encodedMessage, Base64.DEFAULT);
84 | }
85 |
86 |
87 | /**
88 | * Generates a new Secret Key of 16 bytes
89 | * @param secretKey
90 | * @return
91 | * @throws UnsupportedEncodingException
92 | */
93 | public static SecretKey generateSecretKey(String secretKey) throws UnsupportedEncodingException, NoSuchAlgorithmException {
94 | byte[] key = secretKey.getBytes("UTF-8");
95 | MessageDigest sha = MessageDigest.getInstance("SHA-256");
96 | key = sha.digest(key);
97 | //key = Arrays.copyOf(key, 16);
98 | return new SecretKeySpec(key, "AES");
99 |
100 | }
101 |
102 |
103 | /**
104 | * Concatenate two arrays of T type
105 | * @param a
106 | * @param b
107 | * @param
108 | * @return
109 | */
110 | public static T concatenate(T a, T b) {
111 | if (!a.getClass().isArray() || !b.getClass().isArray()) {
112 | throw new IllegalArgumentException();
113 | }
114 |
115 | Class> resCompType;
116 | Class> aCompType = a.getClass().getComponentType();
117 | Class> bCompType = b.getClass().getComponentType();
118 |
119 | if (aCompType.isAssignableFrom(bCompType)) {
120 | resCompType = aCompType;
121 | } else if (bCompType.isAssignableFrom(aCompType)) {
122 | resCompType = bCompType;
123 | } else {
124 | throw new IllegalArgumentException();
125 | }
126 |
127 | int aLen = Array.getLength(a);
128 | int bLen = Array.getLength(b);
129 |
130 | @SuppressWarnings("unchecked")
131 | T result = (T) Array.newInstance(resCompType, aLen + bLen);
132 | System.arraycopy(a, 0, result, 0, aLen);
133 | System.arraycopy(b, 0, result, aLen, bLen);
134 |
135 | return result;
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/BadKeyException.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | public class BadKeyException extends Exception {
4 |
5 | public BadKeyException() {
6 | super("Bad Key found.");
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/SMSTCP.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import android.Manifest;
4 | import android.content.IntentFilter;
5 | import android.content.pm.PackageManager;
6 | import android.provider.Telephony;
7 | import android.support.v4.app.ActivityCompat;
8 | import android.support.v4.content.ContextCompat;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.telephony.SmsManager;
11 | import android.util.Base64;
12 |
13 | import java.io.UnsupportedEncodingException;
14 | import java.math.BigInteger;
15 | import java.nio.charset.StandardCharsets;
16 | import java.security.GeneralSecurityException;
17 | import java.util.Random;
18 |
19 | public class SMSTCP {
20 |
21 | public static final int ID = 0;
22 | public static final int SMS_PERMISSION_CODE = 0;
23 | public static final int SMSLENGTH = 140;
24 | public static final int HEADERLENGTH = 14;
25 | public static final int DATALENGHT = SMSLENGTH - HEADERLENGTH;
26 | public AppCompatActivity activity;
27 | public SmsBroadcastReceiver smsBroadcastReceiver;
28 | public String privateKey;
29 | public int cipherMode;
30 |
31 | /**
32 | * Parent class, handle all methods of the SMSBroadcastReceiver as well as sending SMS
33 | * @param activity AppCompatActivity that implements the object
34 | */
35 | public SMSTCP(AppCompatActivity activity, int cipherMode, String privateKey) {
36 | this.activity = activity;
37 | this.cipherMode = cipherMode;
38 | this.privateKey = privateKey;
39 | this.smsBroadcastReceiver = new SmsBroadcastReceiver();
40 | this.registerReciver();
41 |
42 | if (!isPermissionGranted(Manifest.permission.READ_SMS) || !isPermissionGranted(Manifest.permission.READ_PHONE_STATE)) {
43 | requestReadAndSendSmsPermission(new String[]{Manifest.permission.READ_SMS, Manifest.permission.READ_PHONE_STATE});
44 | }
45 | }
46 |
47 |
48 | // SMSBroadcastReceiver handler ------------------
49 | /**
50 | * Send sms to a single or multiple addresses
51 | * @param smstcpLayer sms to send
52 | * @param phoneNo phone numbers to send the sms
53 | */
54 | public void sendSms(SMSTCPLayer smstcpLayer, String[] phoneNo) {
55 | String smsResponse = smstcpLayer.encondeSMS();
56 | for(int i = 0; i < phoneNo.length; i++){
57 | SmsManager smsManager = SmsManager.getDefault();
58 | smsManager.sendTextMessage(phoneNo[i], null, smsResponse, null, null);
59 | }
60 | }
61 |
62 | /**
63 | * Check wheter the permission of sending and reading SMS is enabled
64 | * @param permission Type of permission
65 | * @return Boolean with the response
66 | */
67 | public boolean isPermissionGranted(String permission) {
68 | return ContextCompat.checkSelfPermission(this.activity, permission) == PackageManager.PERMISSION_GRANTED;
69 | }
70 |
71 | /**
72 | * Request the permissions of sending and reading SMS
73 | * @param permissions Type of permission
74 | */
75 | public void requestReadAndSendSmsPermission(String[] permissions) {
76 | ActivityCompat.requestPermissions(this.activity, permissions, SMS_PERMISSION_CODE);
77 | }
78 |
79 | // SMSTCP Utils -------------------
80 |
81 | /**
82 | * Encode a String into base64 String
83 | * @param base64Text String to conver
84 | * @return String in base64
85 | */
86 | public static String encodeBase64(String base64Text) {
87 | byte[] data = base64Text.getBytes(StandardCharsets.UTF_8);
88 | return Base64.encodeToString(data, Base64.DEFAULT);
89 | }
90 |
91 | /**
92 | * Decode a base64 string into regular encoding
93 | * @param base64Text String in bas64
94 | * @return Decoded string
95 | */
96 | public static String decodeBase64(String base64Text) {
97 | byte[] data = Base64.decode(base64Text, Base64.DEFAULT);
98 | String text = new String(data, StandardCharsets.UTF_8);
99 | return text;
100 | }
101 |
102 | /**
103 | * Encode hexadecimal string into binary
104 | * @param hex Hexadecimal string
105 | * @return binary string
106 | */
107 | public static String hexToBinary(String hex) {
108 | return new BigInteger(hex, 16).toString(2);
109 | }
110 |
111 | /**
112 | * Generate a random key
113 | * @return Random key
114 | */
115 | public int generateRandKey() {
116 | Random rand = new Random();
117 | return rand.nextInt(254);
118 | }
119 |
120 |
121 | public String cipherAES(String message) throws UnsupportedEncodingException, GeneralSecurityException {
122 | return AESCipher.encryptAES(privateKey, message);
123 | }
124 |
125 | public String decipherAES(String AESMesage) throws UnsupportedEncodingException, GeneralSecurityException {
126 | return AESCipher.decryptAES(privateKey, AESMesage);
127 | }
128 |
129 |
130 | public void unregisterReciver() {
131 | this.activity.unregisterReceiver(smsBroadcastReceiver);
132 | }
133 |
134 | public void registerReciver() {
135 | this.activity.registerReceiver(smsBroadcastReceiver, new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION));
136 | }
137 |
138 |
139 | }
140 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/SMSTCPAppLayer.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | public interface SMSTCPAppLayer {
4 |
5 | /**
6 | * Decode an SMS String onto a SMSTCPAppLayer object, obtaining headers and data.
7 | * @param sms sms with the data
8 | */
9 | public void decodeSMSApp(String sms);
10 |
11 | /**
12 | * Encode an SMSTCPAppLayer object onto an SMS String
13 | * @return
14 | */
15 | public String encodeSMSApp();
16 |
17 | /**
18 | * Transform an hexadecimal string into a binary string
19 | * @param hex header in hexadecimal
20 | * @return header in binary
21 | */
22 | public String hexToBinary(String hex);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/SMSTCPController.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import android.Manifest;
4 | import android.content.IntentFilter;
5 | import android.content.pm.PackageManager;
6 | import android.provider.Telephony;
7 | import android.support.v4.app.ActivityCompat;
8 | import android.support.v4.content.ContextCompat;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.telephony.SmsManager;
11 | import android.util.Base64;
12 | import android.widget.Toast;
13 |
14 | import java.io.UnsupportedEncodingException;
15 | import java.math.BigInteger;
16 | import java.nio.charset.StandardCharsets;
17 | import java.security.GeneralSecurityException;
18 | import java.util.ArrayList;
19 | import java.util.Iterator;
20 | import java.util.Random;
21 | import java.util.Timer;
22 | import java.util.TimerTask;
23 |
24 | public class SMSTCPController {
25 |
26 | public CompletionHandler completionHandler;
27 | private AppCompatActivity activitySms;
28 | private SMSTCPReceiver smstcpReceiver;
29 | private SMSTCPSender smstcpSender;
30 | private String privateKey;
31 | private int cipherMode;
32 |
33 |
34 | /**
35 | * Object that controlls all the activity of the SMSTCP Protocol, new implementations
36 | * must use this
37 | * @param activitySms Activity that implements the protocol
38 | * @param cipherMode Cipher Mode
39 | */
40 | public SMSTCPController(AppCompatActivity activitySms, int cipherMode, String privateKey) {
41 | this.activitySms = activitySms;
42 | this.cipherMode = cipherMode;
43 | this.privateKey = privateKey;
44 | this.smstcpReceiver = new SMSTCPReceiver(activitySms, cipherMode, privateKey);
45 | this.smstcpSender = new SMSTCPSender(activitySms, cipherMode, privateKey);
46 |
47 | smstcpSender.setCompletionHandler(new SMSTCPSender.CompletionHandler() {
48 | @Override
49 | public void handleMessage() {
50 | completionHandler.handleMessageSent();
51 | }
52 |
53 | @Override
54 | public void handleFinalMessage() {
55 | completionHandler.handleFinalMessageSent();
56 | }
57 | });
58 |
59 | smstcpReceiver.setCompletionHandler(new SMSTCPReceiver.CompletionHandler() {
60 | @Override
61 | public void handleFinalMessage(ArrayList messages, String[] senderNumber) {
62 | completionHandler.handleFinalMessageReceived(messages, senderNumber);
63 | }
64 |
65 | @Override
66 | public void handleMessage(SMSTCPLayer smsTCP, String[] senderNumber) {
67 | completionHandler.handleMessageReceived(smsTCP, senderNumber);
68 | }
69 | });
70 | }
71 |
72 | public SMSTCPController(AppCompatActivity activitySms) {
73 | this(activitySms, 0, "");
74 | }
75 |
76 | /**
77 | * Send new message
78 | * @param sms sms to send
79 | * @param phoneNo phone number of the receiver
80 | */
81 | public void sendMessage(String sms, String[] phoneNo) {
82 | smstcpSender.createNewConverstaion(sms, phoneNo, true);
83 | }
84 |
85 |
86 | /**
87 | * Send new message
88 | * @param sms sms to send
89 | * @param phoneNo phone number of the receiver
90 | * @param phoneNo whether there's response or not to the petition
91 | */
92 | public void sendMessage(String sms, String[] phoneNo, Boolean ackBack) {
93 | smstcpSender.createNewConverstaion(sms, phoneNo, ackBack);
94 | }
95 |
96 | // UTILS ------------------------------
97 |
98 | /**
99 | * Process the message sent
100 | * @param messages message received
101 | * @return
102 | */
103 | public String processMessages(ArrayList messages) throws BadKeyException {
104 | String finalMessage = "";
105 | for (String stringM : messages) {
106 | finalMessage += stringM;
107 | }
108 |
109 | switch(cipherMode){
110 | case 0:
111 | return SMSTCP.decodeBase64(finalMessage);
112 | case 1:
113 | try {
114 | return AESCipher.decryptAES(privateKey, finalMessage);
115 | } catch (GeneralSecurityException | UnsupportedEncodingException e) {
116 | e.printStackTrace();
117 | throw new BadKeyException();
118 | }
119 | default:
120 | return "";
121 | }
122 | }
123 |
124 |
125 | public void unregisterRec() {
126 | smstcpReceiver.unregisterReciver();
127 | smstcpSender.unregisterReciver();
128 | }
129 |
130 | public void registerRec() {
131 | smstcpReceiver.registerReciver();
132 | smstcpSender.registerReciver();
133 | }
134 |
135 | public interface CompletionHandler {
136 | public void handleFinalMessageReceived(ArrayList messages, String[] senderNumber);
137 | public void handleMessageReceived(SMSTCPLayer smsTCP, String[] senderNumber);
138 | public void handleMessageSent();
139 | public void handleFinalMessageSent();
140 | }
141 |
142 | public void setCompletionHandler(CompletionHandler h) {
143 | this.completionHandler = h;
144 | }
145 |
146 |
147 |
148 |
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/SMSTCPLayer.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import java.math.BigInteger;
4 |
5 | public class SMSTCPLayer {
6 |
7 |
8 | public int id = 0b0;
9 | public int key = 0b0;
10 | public int syn = 0b0;
11 | public int ack = 0b0;
12 | public int psh = 0b0;
13 | public int fin = 0b0;
14 | public int sBegin = 0b0;
15 | public int cipher = 0b0;
16 | public int checkSum = 0b0;
17 | public String data;
18 |
19 |
20 |
21 | /**
22 | * Explicit constructor of SMSTCPLayer Class
23 | * @param id Protocol identifier
24 | * @param key Random key generated in a new conversation
25 | * @param syn Synchronized the sequence numbers in a new session/conversation
26 | * @param ack Flag indicating the acknowledgement of a message
27 | * @param psh Flag indicating the receiver that must push the data as soon as possible
28 | * @param fin End of session
29 | * @param sBegin Packet position
30 | * @param cipher Type of cypher
31 | * @param data Data of the message
32 | */
33 | public SMSTCPLayer(int id, int key, int syn, int ack, int psh, int fin, int sBegin, int cipher, String data){
34 | this.id = id;
35 | this.key = key;
36 | this.syn = syn;
37 | this.ack = ack;
38 | this.psh = psh;
39 | this.fin = fin;
40 | this.sBegin = sBegin;
41 | this.cipher = cipher;
42 | this.data = data;
43 | }
44 |
45 |
46 | /**
47 | * Entire sms to be decoded
48 | * @param sms smstcp given
49 | */
50 | public SMSTCPLayer(String sms) {
51 | decodeSMS(sms);
52 | }
53 |
54 | /**
55 | * Check if the message is well decrypted
56 | * @return Boolean with the result of the decryption
57 | */
58 | public Boolean checkIntegrity() {
59 | return this.id == 0;
60 | }
61 |
62 |
63 | /**
64 | * Decode an smstcp packet
65 | * @param sms smstcp given
66 | */
67 | private void decodeSMS(String sms) {
68 | String headersSms = fillHeader(hexToBinary(sms.substring(0,14)), 56);
69 | String dataSMS = sms.substring(14, sms.length());
70 | this.id = Integer.parseInt(headersSms.substring(0,1), 2);
71 | this.key = Integer.parseInt(headersSms.substring(1,9), 2);
72 | this.syn = Integer.parseInt(headersSms.substring(9,10), 2);
73 | this.ack = Integer.parseInt(headersSms.substring(10,11), 2);
74 | this.psh = Integer.parseInt(headersSms.substring(11,12), 2);
75 | this.fin = Integer.parseInt(headersSms.substring(12,13), 2);
76 | this.sBegin = Integer.parseInt(headersSms.substring(13,21), 2);
77 | this.cipher = Integer.parseInt(headersSms.substring(21,24), 2);
78 | this.checkSum = Integer.parseInt(headersSms.substring(24,56), 2);
79 | this.data = dataSMS;
80 | }
81 |
82 |
83 | /**
84 | * Encode an smstcp packet
85 | * @return message coded
86 | */
87 | public String encondeSMS() {
88 | String idSMS = fillHeader(this.id, 1);
89 | String keySMS = fillHeader(this.key, 8);
90 | String synSMS = fillHeader(this.syn, 1);
91 | String ackSMS = fillHeader(this.ack, 1);
92 | String pshSMS = fillHeader(this.psh, 1);
93 | String finSMS = fillHeader(this.fin, 1);
94 | String sBeginSMS = fillHeader(this.sBegin, 8);
95 | String cipherSMS = fillHeader(this.cipher, 3);
96 | String checkSumSMS = fillHeader(this.checkSum, 32);
97 |
98 | String headersBinary = idSMS + keySMS + synSMS + ackSMS + pshSMS + finSMS + sBeginSMS + cipherSMS + checkSumSMS;
99 | String headersHexa = fillHeader(Long.toHexString(Long.parseLong(headersBinary, 2)), 14);
100 |
101 | return headersHexa + this.data;
102 | }
103 |
104 |
105 | /**
106 | * Transforms an hexadecimal string to a binary string
107 | * @param hex message in hexadecimal
108 | * @return binary string representation
109 | */
110 | public static String hexToBinary(String hex) {
111 | return new BigInteger(hex, 16).toString(2);
112 | }
113 |
114 |
115 | /**
116 | * Fill the header parameters with 0
117 | * @param header header parameter
118 | * @param requiredSize size of the parameter
119 | * @return parameter with padding
120 | */
121 | public static String fillHeader(int header, int requiredSize) {
122 | String headerToString = Integer.toBinaryString(header);
123 | String filler = "";
124 | try {
125 | filler = new String(new char[requiredSize - headerToString.length()]).replace("\0", "0");
126 | } catch (Exception e) {
127 | e.printStackTrace();
128 | }
129 | return filler + headerToString;
130 | }
131 |
132 | /**
133 | * Fill the header parameters with 0
134 | * @param header header parameter
135 | * @param requiredSize size of the parameter
136 | * @return parameter with padding
137 | */
138 | public static String fillHeader(String header, int requiredSize) {
139 | String filler = "";
140 | try {
141 | filler = new String(new char[requiredSize - header.length()]).replace("\0", "0");
142 | } catch (Exception e) {
143 | e.printStackTrace();
144 | }
145 | return filler + header;
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/SMSTCPReceiver.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Iterator;
7 | import java.util.Optional;
8 | import java.util.Timer;
9 | import java.util.TimerTask;
10 |
11 | public class SMSTCPReceiver extends SMSTCP {
12 |
13 | private final int FIN_CHECK_DELAY = 500;
14 | private ArrayList messagesReceived = new ArrayList();
15 | private ArrayList addresses = new ArrayList();
16 | public CompletionHandler completionHandler;
17 |
18 | /**
19 | * Send SMSTCP messages and control the volume depending of the data length
20 | * @param activity Activity in wich the listener is applied
21 | */
22 | public SMSTCPReceiver(AppCompatActivity activity, int cipherMode, String privateKey) {
23 | super(activity, cipherMode, privateKey);
24 |
25 | smsBroadcastReceiver.setListener(new SmsBroadcastReceiver.Listener() {
26 | @Override
27 | public void onTextReceived(String text, String receiver) {
28 | addNewMessage(text, receiver);
29 | }
30 | });
31 | }
32 |
33 | // Receiver Methods ----------------------------------
34 |
35 | /**
36 | * Listen to new message in order to fetch de sms
37 | * @param sms Data with part of the sms sent
38 | * @param receiver Addresses that sent the sms
39 | */
40 | public void addNewMessage(final String sms, String receiver){
41 | final String[] phoneNo = new String[]{receiver};
42 | SMSTCPLayer smsTCP = null;
43 | try {
44 | smsTCP = new SMSTCPLayer(sms);
45 | } catch (Exception e) {
46 | e.printStackTrace();
47 | }
48 |
49 | if (smsTCP != null && smsTCP.checkIntegrity()){
50 |
51 | if(smsTCP.ack == 1) {
52 | // TOD0: Implement receive when error occurs
53 | return;
54 | }
55 |
56 | this.messagesReceived.add(smsTCP);
57 | this.completionHandler.handleMessage(smsTCP, phoneNo);
58 | final SMSTCPLayer smsTCPFinal = smsTCP;
59 | if (smsTCP.fin == 1 && smsTCP.ack == 0) {
60 | new Timer().schedule(new TimerTask() {
61 | @Override
62 | public void run() {
63 | checkSMSTCPSTream(smsTCPFinal, phoneNo);
64 | }
65 | }, 5000);
66 | }
67 | }
68 | }
69 |
70 |
71 |
72 |
73 | /**
74 | * Check the stream of the SMSTCP to detect if all the messages have been sent
75 | * @param sms Final sms sent
76 | * @param phoneNo Addresses that sent the sms
77 | */
78 | private void checkSMSTCPSTream(final SMSTCPLayer sms, String[] phoneNo){
79 | ArrayList messages = new ArrayList();
80 | for(int i = 0; i <= sms.sBegin; i++) {
81 | SMSTCPLayer smsTCP = getSMSTCPByPos(i, sms.key);
82 | if (smsTCP != null) {
83 | messages.add(smsTCP.data);
84 | } else {
85 | responseConversation(sms, phoneNo, i, 0, 1, 0, 0);
86 | removeSMSByKey(sms.key, i);
87 | return;
88 | }
89 | }
90 | if(sms.psh == 0) {
91 | responseConversation(sms, phoneNo, sms.sBegin, 0, 1, 0, 1);
92 | removeSMSByKey(sms.key);
93 | }
94 | this.completionHandler.handleFinalMessage(messages, phoneNo);
95 | }
96 |
97 | /**
98 | * Response to a conversation with the given flag headers
99 | * @param sms Data to send
100 | * @param phoneNo Addresses to send the message
101 | * @param sBeginResponse sBegin flag
102 | * @param synResponse Syn flag
103 | * @param ackResponse Ack flag
104 | * @param pshResponse Psh flag
105 | * @param finResponse Fin flag
106 | */
107 | private void responseConversation(SMSTCPLayer sms, String[] phoneNo, int sBeginResponse, int synResponse, int ackResponse, int pshResponse, int finResponse) {
108 | int keyResponse = sms != null ? sms.key : 0;
109 | int cipherResponse = sms != null ? sms.cipher : 0;
110 | String message = "";
111 | SMSTCPLayer smsTCP = new SMSTCPLayer(ID, keyResponse, synResponse, ackResponse, pshResponse, finResponse,
112 | sBeginResponse, cipherResponse, message);
113 | sendSms(smsTCP, phoneNo);
114 | }
115 |
116 | // TODO - Implement cipher AES
117 | private void handleCipherAES() {
118 |
119 | }
120 |
121 |
122 | // SMS Utils ----------------------------------------
123 |
124 | /**
125 | * Remove SMS from list of received by SMSTCPLayer key
126 | * @param key SMSTCPLayer id
127 | */
128 | private void removeSMSByKey(int key) {
129 | Iterator it = messagesReceived.iterator();
130 | while(it.hasNext()){
131 | SMSTCPLayer smsIt = it.next();
132 | if(smsIt.key == key){
133 | it.remove();
134 | }
135 | }
136 | }
137 |
138 | /**
139 | * Remove SMS from a given index by SMSTCPLayer key
140 | * @param key SMSTCPLayer id
141 | * @param startingIndex Index
142 | */
143 | private void removeSMSByKey(int key, int startingIndex) {
144 | Iterator it = messagesReceived.iterator();
145 | while(it.hasNext()){
146 | SMSTCPLayer smsIt = it.next();
147 | if(smsIt.key == key && smsIt.sBegin >= startingIndex){
148 | it.remove();
149 | }
150 | }
151 | }
152 |
153 | /**
154 | * Get the SMSTCPLayer Object by id and key
155 | * @param id index of the object
156 | * @param key key of the sms stream
157 | * @return SMSTCPLayer object or null
158 | */
159 | private SMSTCPLayer getSMSTCPByPos(int id, int key) {
160 | Optional smsTCP = messagesReceived.stream().filter(p -> (p.sBegin == id && p.key == key)).findFirst();
161 | return smsTCP.orElse(null);
162 | }
163 |
164 |
165 | // Completion Handler -----------------------------------
166 | /**
167 | * Completion handler to manage some of the behaviours of the app
168 | */
169 | public interface CompletionHandler {
170 | void handleFinalMessage(ArrayList messages, String[] senderNumber);
171 | void handleMessage(SMSTCPLayer smsTCP, String[] senderNumber);
172 | }
173 |
174 | /**
175 | * Set the completion handler of the class
176 | * @param h Completion handler of the class
177 | */
178 | public void setCompletionHandler(CompletionHandler h) {
179 | this.completionHandler = h;
180 | }
181 |
182 | }
183 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/SMSTCPSender.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import android.Manifest;
4 | import android.support.v7.app.AppCompatActivity;
5 |
6 | import java.io.UnsupportedEncodingException;
7 | import java.security.GeneralSecurityException;
8 | import java.util.ArrayList;
9 |
10 | public class SMSTCPSender extends SMSTCP {
11 |
12 | private ArrayList messagesToSend = new ArrayList();
13 | private ArrayList addresses = new ArrayList();
14 | public CompletionHandler completionHandler;
15 |
16 | /**
17 | * Send SMSTCP messages and control the volume depending of the data length
18 | * @param activity Activity in wich the listener is applied
19 | */
20 | public SMSTCPSender(AppCompatActivity activity, int cipherMode, String privateKey) {
21 | super(activity, cipherMode, privateKey);
22 | }
23 |
24 | // Sender methods ------------------------------------
25 | /**
26 | * Create new conversation to send to a single or multiple addressses
27 | * @param sms String with the message to send
28 | * @param phoneNo Phone number(s)
29 | */
30 | public void createNewConverstaion(String sms, String[] phoneNo, Boolean ackBack) {
31 | if (!isPermissionGranted(Manifest.permission.SEND_SMS) || !isPermissionGranted(Manifest.permission.READ_PHONE_STATE)){
32 | requestReadAndSendSmsPermission(new String[]{Manifest.permission.READ_SMS, Manifest.permission.READ_PHONE_STATE});
33 | return;
34 | }
35 |
36 | int key = generateRandKey();
37 | String textSMS = "";
38 | switch(super.cipherMode){
39 | case 0:
40 | textSMS = encodeBase64(sms);
41 | break;
42 | case 1:
43 | try {
44 | textSMS = cipherAES(sms);
45 | } catch (UnsupportedEncodingException | GeneralSecurityException e) {
46 | e.printStackTrace();
47 | }
48 | break;
49 | default:
50 | textSMS = encodeBase64(sms);
51 | break;
52 | }
53 |
54 | // TOD0: CHANGE THAT TO STORE MESSAGE IN CASE IT NEED TO BE SENT
55 | this.messagesToSend = splitMessage(textSMS);
56 |
57 | for (int i = 0; i < this.messagesToSend.size(); i++ ) {
58 | String message = this.messagesToSend.get(i);
59 | int fin = i == (this.messagesToSend.size() - 1) ? 1 : 0;
60 | int syn = i == (this.messagesToSend.size() - 1) ? 0 : 1;
61 | int psh = ackBack ? 0: 1;
62 | SMSTCPLayer smsTCP = new SMSTCPLayer(ID, key, syn, 0,
63 | psh, fin, i, 0, message);
64 | sendSms(smsTCP, phoneNo);
65 | this.completionHandler.handleMessage();
66 | }
67 | this.completionHandler.handleFinalMessage();
68 | }
69 |
70 | //AES-CTR
71 |
72 |
73 | /**
74 | * Split the message in order to adapt the data to the SMS limit (may vary in each country)
75 | * @param base64Text Text to split
76 | * @return Array List with all the parts splitted
77 | */
78 | public ArrayList splitMessage(String base64Text) {
79 | ArrayList strings = new ArrayList();
80 | int index = 0;
81 | int offset = DATALENGHT;
82 | while (index < base64Text.length()) {
83 | strings.add(base64Text.substring(index, Math.min(index + offset,base64Text.length())));
84 | index += offset;
85 | }
86 | return strings;
87 | }
88 |
89 | // Completion Handler ---------------------------
90 |
91 | /**
92 | * Completion handler to manage some of the behaviours of the app
93 | */
94 | public interface CompletionHandler {
95 | public void handleMessage();
96 | public void handleFinalMessage();
97 | }
98 |
99 | /**
100 | * Set the completion handler of the class
101 | * @param h Completion Handler
102 | */
103 | public void setCompletionHandler(CompletionHandler h) {
104 | this.completionHandler = h;
105 | }
106 |
107 |
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/java/com/example/smstcplibrary/SmsBroadcastReceiver.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.provider.Telephony;
7 | import android.telephony.SmsMessage;
8 |
9 | public class SmsBroadcastReceiver extends BroadcastReceiver {
10 |
11 | private Listener listener;
12 |
13 | public SmsBroadcastReceiver() {
14 | //this.serviceProviderNumbers = serviceProvderNumbers;
15 | }
16 |
17 | @Override
18 | public void onReceive(Context context, Intent intent) {
19 | if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
20 | String smsSender = "";
21 | String smsBody = "";
22 |
23 | for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
24 | smsSender = smsMessage.getDisplayOriginatingAddress();
25 | smsBody += smsMessage.getMessageBody();
26 | }
27 |
28 | if (listener != null) {
29 | listener.onTextReceived(smsBody, smsSender);
30 | }
31 | }
32 | }
33 |
34 | void setListener(Listener listener) {
35 | this.listener = listener;
36 | }
37 |
38 | interface Listener {
39 | void onTextReceived(String text, String receiver);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SmsTcpLibrary
3 |
4 |
--------------------------------------------------------------------------------
/sms-stack-android/smstcplibrary/src/test/java/com/example/smstcplibrary/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.smstcplibrary;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void smstcpLayer_form() {
15 | SMSTCPLayer smsTest = new SMSTCPLayer(0, 17, 1, 1, 1, 1, 0, 0, "hola que tal");
16 |
17 | assertEquals(smsTest.encondeSMS(), "08f80000000000hola que tal");
18 | }
19 |
20 | /*
21 | @Test
22 | public void encodeBase64() {
23 | assertEquals(SMSTCP.encodeBase64("Hello World"), "SGVsbG8gd29ybGQ=");
24 | }
25 | */
26 |
27 |
28 | }
--------------------------------------------------------------------------------
/sms-stack-python/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | *.vscode
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *,cover
47 |
48 | # Translations
49 | *.mo
50 | *.pot
51 |
52 | # Django stuff:
53 | *.log
54 |
55 | # Sphinx documentation
56 | docs/_build/
57 |
58 | # PyBuilder
59 | target/
60 |
--------------------------------------------------------------------------------
/sms-stack-python/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [year] [fullname]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/sms-stack-python/README.md:
--------------------------------------------------------------------------------
1 | # Sms Stack Python
2 |
3 | SDK for Sms Stack in python-
4 |
5 | ## Uses
6 |
7 | You can controll SMS as if they were a tcp streaming data, with flow and loss control.
8 |
9 | ## Implementation
10 |
11 | Create a controller class, inheriting form ```SmsControllerObserver``` and then a layer class.
12 |
13 | Give the listener and de broadcaster to the controller and start the sms flow.
14 |
--------------------------------------------------------------------------------
/sms-stack-python/__init__.py:
--------------------------------------------------------------------------------
1 | name = "sms_stack_python"
--------------------------------------------------------------------------------
/sms-stack-python/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 |
3 | s = [
4 | 'pytest'
5 | ]
6 |
7 | with open("README.md", "r") as fh:
8 | long_description = fh.read()
9 |
10 | setuptools.setup(
11 | name="sms-stack",
12 | version="1.1.0",
13 | author="Lucas Fernandez",
14 | author_email="lucas.fernandezaragon@telefonica.com",
15 | description="Sms Stack SDK for python",
16 | long_description=long_description,
17 | long_description_content_type="text/markdown",
18 | url="",
19 | keywords=[
20 | 'sms-stack',
21 | 'tcp',
22 | 'protocol'
23 | ],
24 | packages=setuptools.find_packages(),
25 | classifiers=[
26 | "Programming Language :: Python :: 3",
27 | "License :: OSI Approved :: MIT License",
28 | "Operating System :: OS Independent",
29 | ],
30 | )
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-python/sms_stack/__init__.py
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/cipher.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import hashlib
3 | import binascii
4 | import os
5 | from Crypto.Cipher import AES
6 | from Crypto import Random
7 | from Crypto.Util import Counter
8 |
9 |
10 |
11 | class AESCipher:
12 | #TOCHECK *** ¿Se podrían dejar como estáticos para no necesitar instanciar la clase?
13 | def int_of_string(self, s):
14 | return int(binascii.hexlify(s), 16)
15 |
16 |
17 |
18 | def encrypt_message(self, key, plaintext):
19 | """Encode a message with AES CTR No Padding methodd
20 |
21 | Args:
22 | key (string): Key to cipher the operatoin
23 | plaintext (string): Plain text to encode
24 |
25 | Returns:
26 | string: Message encoded with AES cypher
27 | """
28 | iv = Random.new().read(AES.block_size)
29 | key_enc = self.generate_key(key)
30 | ctr = Counter.new(128, initial_value=int.from_bytes(iv, byteorder='big'))
31 | aes = AES.new(key_enc, AES.MODE_CTR, counter=ctr)
32 | return base64.b64encode(iv + aes.encrypt(plaintext.encode())).decode("ascii")
33 |
34 |
35 |
36 | def decrypt_message(self, key, ciphertext):
37 | """Decode message with AES CTR No Padding method
38 |
39 | Args:
40 | key (string): Key to decipher the operation
41 | ciphertext (string): Encoded message
42 |
43 | Returns:
44 | string: Plain text decoded
45 | """
46 |
47 |
48 | enc = base64.b64decode(ciphertext)
49 | iv, encrypted = enc[:AES.block_size], enc[AES.block_size:]
50 | key_enc = self.generate_key(key)
51 | ctr = Counter.new(128, initial_value=int.from_bytes(iv, byteorder='big'))
52 | aes = AES.new(key_enc, AES.MODE_CTR, counter=ctr)
53 | return aes.encrypt(encrypted).decode('utf-8')
54 |
55 | def generate_key(self, key):
56 | """Generate the key with SHA256 Hash
57 |
58 | Args:
59 | key (string): Plain text key
60 |
61 | Returns:
62 | byte: Hash of the key
63 | """
64 |
65 | return hashlib.sha256(key.encode()).digest()
66 |
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/debug/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-python/sms_stack/debug/__init__.py
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/debug/sms_broadcast_im.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-python/sms_stack/debug/sms_broadcast_im.py
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/debug/sms_mt_controller.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-python/sms_stack/debug/sms_mt_controller.py
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/debug/sms_mt_layer.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-python/sms_stack/debug/sms_mt_layer.py
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/sms_broadcaster.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 |
3 | class SmsBroadcaster(ABC):
4 |
5 | @abstractmethod
6 | def send_sms(self, sms, sender):
7 | """Abstract method to implement in child class to work with the framework
8 |
9 | Args:
10 | sms (str): message to send
11 | sender (str): sender number
12 | """
13 | return NotImplemented
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/sms_controller_observer.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 |
3 | class SmsControllerObserver(ABC):
4 |
5 | @abstractmethod
6 | def handle_final_message_received(self, messages, sender):
7 | """Handle the final message received, endpoint to retreive the message received, use process_message() of SmsTcpController to unwrap them
8 |
9 | Args:
10 | messages ([str]): List of messages returned
11 | sender ([str]): List of senders
12 | """
13 |
14 | return NotImplemented
15 |
16 | @abstractmethod
17 | def handle_message_received(self, layer, sender):
18 | """Called each time a packet is received
19 |
20 | Args:
21 | layer (SmsTcpLayer): Packet
22 | sender ([str]): List of senders
23 | """
24 |
25 | return NotImplemented
26 |
27 | @abstractmethod
28 | def handle_final_message_sent(self, messages, sender):
29 | """Called when a stream of messages is sent
30 |
31 | Args:
32 | messages ([str]): list of messages
33 | sender ([str]): List of senders
34 | """
35 |
36 | return NotImplemented
37 |
38 | @abstractmethod
39 | def handle_message_sent(self, layer, sender):
40 | """Called each time a message is sent
41 |
42 | Args:
43 | layer ([str]): layer
44 | sender ([str]): List of senders
45 | """
46 |
47 | return NotImplemented
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/sms_tcp.py:
--------------------------------------------------------------------------------
1 | import base64
2 | from .sms_tcp_layer import SmsTcpLayer
3 | from .sms_broadcaster import SmsBroadcaster
4 | from .sms_tcp_layer import SmsTcpLayer
5 | from random import randint
6 | # from debug.test import TestBrod
7 |
8 |
9 | class SmsTcp(object):
10 |
11 | def __init__(self, cipher_mode, cipher_key, sms_broadcaster):
12 | """Base class with some utility methods
13 |
14 | Args:
15 | cipher_mode (int): Cipher mode of the controller (0 Base64 | 1 AES CTR)
16 | cipher_key (str): Pre shared key in the AES cipher
17 | broadcast_send (SmsTcpBroadcaster): Class to send messages
18 | """
19 |
20 | self.sms_lenght = 140
21 | self.header_lenght = 14
22 | self.data_lenght = self.sms_lenght - self.header_lenght
23 | self.cipher_mode = cipher_mode
24 | self.cipher_key = cipher_key
25 | self.sms_broadcaster = sms_broadcaster
26 |
27 | def send_sms(self, tcp_layer, phone):
28 | """Send message throught the broadcaster
29 |
30 | Args:
31 | tcp_layer (SmsTcpLayer): Packet of sms stack
32 | phone ([str]): List of senders
33 | """
34 |
35 | sms_response = tcp_layer.enconde_sms()
36 | self.sms_broadcaster.send_sms(sms_response, phone)
37 |
38 | def generate_random_key(self):
39 | """Generate a random key
40 |
41 | Returns:
42 | int: Key
43 | """
44 |
45 | return randint(0, 254)
46 |
47 | @staticmethod
48 | def encode_base_64(text):
49 | return base64.b64encode(bytes(text, "utf-8")).decode("ascii")
50 |
51 | @staticmethod
52 | def decode_base_64(text):
53 | return base64.b64decode(text).decode("ascii")
54 |
55 | @staticmethod
56 | def decode_base_64_byte(text):
57 | return base64.b64decode(text)
58 |
59 |
60 |
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/sms_tcp_controller.py:
--------------------------------------------------------------------------------
1 | from .sms_tcp_receiver import SmsTcpReceiver
2 | from .sms_tcp_sender import SmsTcpSender
3 | from .sms_tcp import SmsTcp
4 | from .cipher import AESCipher
5 |
6 | class SmsTcpController:
7 |
8 | def __init__(self, observer, broadcaster_send, cipher_mode=0, cipher_key=""):
9 | """Controller of the framework, runs a sender and receiver to controll the stream of sms
10 |
11 | Args:
12 | observer (SmsTcpObserver): Inherits from SmsControllerObserver implementing the methods to controll the flow of messages
13 | broadcaster_send (SmsBroadcaster): Class that implements send_message in order to send messages to a sender
14 | cipher_mode (int, optional): Defaults to 0. Cipher mode of the controller (0 Base64 | 1 AES CTR)
15 | cipher_key (str, optional): Defaults to "". Pre shared key in the AES cipher
16 | """
17 | self.cipher_mode = cipher_mode
18 | self.cipher_key = cipher_key
19 | self._observer = observer
20 | self._receiver = SmsTcpReceiver(cipher_mode, cipher_key, self, broadcaster_send)
21 | self._sender = SmsTcpSender(cipher_mode, cipher_key, self, broadcaster_send)
22 |
23 | def handle_final_message_received(self, messages, sender):
24 | self._observer.handle_final_message_received(messages, sender)
25 |
26 | def handle_message_received(self, layer, sender):
27 | self._observer.handle_message_received(layer, sender)
28 |
29 |
30 | def handle_final_message_sent(self, messages, sender):
31 | self._observer.handle_final_message_sent(messages, sender)
32 |
33 | def handle_message_sent(self, layer, sender):
34 | self._observer.handle_message_sent(layer, sender)
35 |
36 | def send_message(self, sms, sender, ack_back = True):
37 | self._sender.create_new_conversation(sms, sender, ack_back)
38 |
39 | def receive_message(self, sms, receiver):
40 | self._receiver.add_new_message(sms, receiver)
41 |
42 |
43 | def process_message(self, message):
44 | """Process stream of messages received and decode them with the required cipher method
45 |
46 | Args:
47 | message ([str]): List of messages received for the stream
48 |
49 | Returns:
50 | str: Text message decoded and joined
51 | """
52 |
53 | final_messge = ''.join(message)
54 | try:
55 | if(self.cipher_mode == 0):
56 | return SmsTcp.decode_base_64(final_messge)
57 | elif(self.cipher_mode == 1):
58 | aes_cypher = AESCipher()
59 | clear_text = aes_cypher.decrypt_message(self.cipher_key, final_messge)
60 | return clear_text
61 | else:
62 | return ""
63 | except Exception as e:
64 | print(e)
65 | return ""
66 |
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/sms_tcp_layer.py:
--------------------------------------------------------------------------------
1 | from .sms_tcp_layer_formatter import SmsTcpLayerFormatter
2 |
3 | class SmsTcpLayer:
4 |
5 | def __init__(self, sms='', id=None, key=None, syn=None, ack=None, psh=None, fin=None, s_begin=None, cipher=None, check_sum=None, data=""):
6 | """Layer class of SmsTcp with all the flags
7 | sms (str, optional): Defaults to ''. String codign the layer
8 | id (int, optional): Defaults to None. Flag for de id type
9 | key (int, optional): Defaults to None. Flag for the random key of a stream
10 | syn (int, optional): Defaults to None. Flag control the initialization of a connection
11 | ack (int, optional): Defaults to None. Flag control the acknowledgment
12 | psh (int, optional): Defaults to None. Flag control the push of a stream
13 | fin (int, optional): Defaults to None. Flag control the end of a stream
14 | s_begin (int, optional): Defaults to None. Flag control the stream position
15 | cipher (int, optional): Defaults to None. Flag control the cipher
16 | check_sum (int, optional): Defaults to None. Padding to implement
17 | data (str, optional): Defaults to "". Message to include in the packet
18 | """
19 | if(sms != ''):
20 | self._decode_sms(sms)
21 | elif(id != None, key != None, syn != None, ack != None, psh != None, fin != None, s_begin != None, cipher != None, check_sum != None):
22 | self.id = id
23 | self.key = key
24 | self.syn = syn
25 | self.ack = ack
26 | self.psh = psh
27 | self.fin = fin
28 | self.s_begin = s_begin
29 | self.cipher = cipher
30 | self.check_sum = check_sum
31 | self.data = data
32 |
33 |
34 | def _decode_sms(self, sms):
35 | """Decode the string with the layer
36 |
37 | Args:
38 | sms (str): String with the layer coded
39 | """
40 |
41 | try:
42 | header_sms = SmsTcpLayerFormatter.fill_header_string(SmsTcpLayerFormatter.hex_to_binary(sms[0:14]), 56)
43 | self.data = sms[14:]
44 | self.id = int(header_sms[0:1], 2)
45 | self.key = int(header_sms[1:9], 2)
46 | self.syn = int(header_sms[9:10], 2)
47 | self.ack = int(header_sms[10:11], 2)
48 | self.psh = int(header_sms[11:12], 2)
49 | self.fin = int(header_sms[12:13], 2)
50 | self.s_begin = int(header_sms[13:21], 2)
51 | self.cipher = int(header_sms[21:24], 2)
52 | self.check_sum = int(header_sms[24:], 2)
53 | except Exception as e:
54 | print("Bad length exception")
55 | print(e)
56 |
57 |
58 | def enconde_sms(self):
59 | """Encode the layer to send it in a string
60 |
61 | Returns:
62 | str: Layer encoded
63 | """
64 |
65 | id_sms = SmsTcpLayerFormatter.fill_header_binary(self.id, 1)
66 | key_sms = SmsTcpLayerFormatter.fill_header_binary(self.key, 8)
67 | syn_sms = SmsTcpLayerFormatter.fill_header_binary(self.syn, 1)
68 | ack_sms = SmsTcpLayerFormatter.fill_header_binary(self.ack, 1)
69 | psh_sms = SmsTcpLayerFormatter.fill_header_binary(self.psh, 1)
70 | fin_sms = SmsTcpLayerFormatter.fill_header_binary(self.fin, 1)
71 | s_begin_sms = SmsTcpLayerFormatter.fill_header_binary(self.s_begin, 8)
72 | cipher_sms = SmsTcpLayerFormatter.fill_header_binary(self.cipher, 3)
73 | check_sum_sms = SmsTcpLayerFormatter.fill_header_binary(self.check_sum, 32)
74 |
75 | headers_binary = id_sms + key_sms + syn_sms + ack_sms + psh_sms + fin_sms + s_begin_sms + cipher_sms + check_sum_sms
76 | headers_hexa = SmsTcpLayerFormatter.fill_header_string(SmsTcpLayerFormatter.binary_to_hex(headers_binary), 14)
77 |
78 | return headers_hexa + self.data
79 |
80 | @staticmethod
81 | def message_packet_lost(layer, s_begin= None):
82 | """Create a packet with the los position
83 |
84 | Args:
85 | layer (SmsTcpLayer): Last packet with information before the one lost
86 | s_begin (int, optional): Defaults to None. Position of the packet lost
87 |
88 | Returns:
89 | SmsTcpLayer: SmsTcpLayer packet with lost flag
90 | """
91 |
92 | idx = s_begin if s_begin is not None else layer.s_begin
93 | return SmsTcpLayer(id=layer.id, key=layer.key, syn=0, ack=1, psh=0, fin=0, s_begin=idx, cipher=layer.cipher, check_sum=layer.check_sum, data="")
94 |
95 | @staticmethod
96 | def message_packet_fin(layer):
97 | """Create a packet with fin
98 |
99 | Args:
100 | layer (SmsTcpLayer): Packet of the stream
101 |
102 | Returns:
103 | SmsTcpLayer: SmsTcpLayer packet with fin flag
104 | """
105 |
106 | return SmsTcpLayer(id=layer.id, key=layer.key, syn=0, ack=1, psh=0, fin=1, s_begin=layer.s_begin, cipher=layer.cipher, check_sum=layer.check_sum, data="")
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/sms_tcp_layer_formatter.py:
--------------------------------------------------------------------------------
1 | import binascii
2 |
3 | class SmsTcpLayerFormatter:
4 | #TOCHECK *** ¿Deberiamos comprobar si es hexadecimal, o binario antes de proceder? (try..catch)
5 |
6 | @staticmethod
7 | def hex_to_binary(hex):
8 | """Convert hex string to binary string
9 |
10 | Args:
11 | hex (str): Hex string
12 |
13 | Returns:
14 | str: Binary string
15 | """
16 | try:
17 | binary = bin(int(hex, 16))[2:]
18 | except:
19 | binary = None
20 | print("Error converting hexadecimal to binary... input: {}".format(hex))
21 |
22 | return binary
23 |
24 | @staticmethod
25 | def binary_to_hex(bin):
26 | """Convert bin string to hex string
27 |
28 | Args:
29 | bin (str): Binary strign
30 |
31 | Returns:
32 | str: Hex string
33 | """
34 | try:
35 | hexa = hex(int(bin, 2))[2:]
36 | except:
37 | hexa = None
38 | print("Error converting binary to hexadecimal... input: {}".format(hex))
39 |
40 | return hexa
41 |
42 | @staticmethod
43 | def dec_to_binary(dec):
44 | """Convert decimal number to binary string
45 |
46 | Args:
47 | dec (int): Decimal Number
48 |
49 | Returns:
50 | str: Binary string
51 | """
52 | try:
53 | binary = "{0:b}".format(dec)
54 | except:
55 | binary = None
56 | print("Error converting decimal to binary... input: {}".format(hex))
57 |
58 | return binary
59 |
60 | @staticmethod
61 | def fill_header_string(header, req_size):
62 | """Fill a binary header with requiered zeroes
63 |
64 | Args:
65 | header (str): Binary string
66 | req_size (int): Lenght required for the binary string
67 |
68 | Returns:
69 | str: Binary string filled with zeroes
70 | """
71 | return header.zfill(req_size)
72 |
73 | @staticmethod
74 | def fill_header_binary(header, req_size):
75 | """Fill a binary header with requiered zeroes
76 |
77 | Args:
78 | header (binary): Binary header
79 | req_size (int): Lenght requiered
80 |
81 | Returns:
82 | str: Binary string filled with zeroes
83 | """
84 |
85 | header_to_string = SmsTcpLayerFormatter.dec_to_binary(header)
86 | return header_to_string.zfill(req_size)
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/sms_tcp_receiver.py:
--------------------------------------------------------------------------------
1 | from .sms_tcp import SmsTcp
2 | from .sms_tcp_layer import SmsTcpLayer
3 | from threading import Timer
4 | # from sms_tcp_layer import TcpLayer
5 |
6 | class SmsTcpReceiver(SmsTcp):
7 |
8 | def __init__(self, cipher_mode, cipher_key, controller, broadcast_send):
9 | """Handle the reception of the sms stream, checking the streams and constructing the packet
10 |
11 | Args:
12 | cipher_mode (int): Cipher mode of the controller (0 Base64 | 1 AES CTR)
13 | cipher_key (str): Pre shared key in the AES cipher
14 | controller (SmsTcpController): Controller class to call the functions
15 | broadcast_send (SmsTcpBroadcaster): Class to send messages
16 | """
17 |
18 | super().__init__(cipher_mode, cipher_key, broadcast_send)
19 | self._controller = controller
20 | self._message_received = []
21 |
22 | def add_new_message(self, sms, receiver):
23 | """Add new message to the stream list
24 |
25 | Args:
26 | sms (str): String with a SmsTcpLayer coded
27 | receiver ([str]): list of senders
28 | """
29 |
30 | try:
31 | sms_layer = SmsTcpLayer(sms=sms)
32 | self._message_received.append(sms_layer)
33 | if(self._controller != None):
34 | # check the name of methods
35 | self._controller.handle_message_received(sms_layer, receiver)
36 |
37 | if(sms_layer.fin == 1 and sms_layer.ack == 0):
38 | t = Timer(0.5, self.check_sms_tcp_stream, args=(sms_layer, receiver))
39 | t.start()
40 | except Exception as e:
41 | print("Error implementing sms layer {}".format(e))
42 | return
43 |
44 | def check_sms_tcp_stream(self, sms, receiver):
45 | """Check the end of the strem in order to detect packet losss
46 |
47 | Args:
48 | sms (SmsTcpLayer): Layer with the fin flag
49 | receiver ([str]): List of senders
50 | """
51 |
52 | sms_stream = sorted((x for x in self._message_received if x.key == sms.key),
53 | key=lambda x: x.s_begin
54 | )
55 | missing = self.missing_numbers(sms_stream)
56 | if(len(missing) > 0):
57 | response_failed = SmsTcpLayer.message_packet_lost(sms, missing[0])
58 | super().send_sms(response_failed, receiver)
59 | self._message_received = self.remove_sms_by(sms.key, missing[0])
60 | return
61 | # Control the ack
62 | if(sms.psh == 0):
63 | response = SmsTcpLayer.message_packet_lost(sms)
64 | super().send_sms(response, receiver)
65 | self._message_received = self.remove_sms_by(sms.key)
66 | self._controller.handle_final_message_received([x.data for x in sms_stream], receiver)
67 |
68 |
69 | def missing_numbers(self, num_list):
70 | """Get the position of the packet lost in the stream
71 |
72 | Args:
73 | num_list ([SmsTcpLayer]): List with all the packets of the stream
74 |
75 | Returns:
76 | set(int): Set with the numbers of the lost packets
77 | """
78 |
79 | sms_index = [x.s_begin for x in num_list]
80 | data = []
81 | if sms_index:
82 | original_list = [x for x in range(sms_index[0], sms_index[-1] + 1)]
83 | sms_index_set = set(sms_index)
84 | data = (list(sms_index_set ^ set(original_list)))
85 |
86 | return data
87 |
88 | def remove_sms_by(self, key, s_begin=None):
89 | """Removes the stream of sms by a given key
90 |
91 | Args:
92 | key (int): Key to identify the stream of sms
93 | s_begin (int, optional): Defaults to None. Position in which the stream must be deleted
94 |
95 | Returns:
96 | [SmsTcpLayer]: List without the stream of packets
97 | """
98 |
99 | if(s_begin != None):
100 | return [x for x in self._message_received if x.key != key and x.s_begin >= s_begin]
101 | else:
102 | return [x for x in self._message_received if x.key != key]
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/sms_tcp_sender.py:
--------------------------------------------------------------------------------
1 | from .sms_tcp import SmsTcp
2 | from .sms_tcp_layer import SmsTcpLayer
3 | from .cipher import AESCipher
4 |
5 | class SmsTcpSender(SmsTcp):
6 |
7 | def __init__(self, cipher_mode, cipher_key, controller, broadcast_send):
8 | """Control the flow of a new conversation, dividing the message into n packets and creating an stream of data
9 |
10 | Args:
11 | cipher_mode (int): Cipher mode of the controller (0 Base64 | 1 AES CTR)
12 | cipher_key (str): Pre shared key in the AES cipher
13 | controller (SmsTcpController): Controller class to call the functions
14 | broadcast_send (SmsTcpBroadcaster): Class to send messages
15 | """
16 |
17 | super().__init__(cipher_mode, cipher_key, broadcast_send)
18 | self._controller = controller
19 |
20 |
21 | def create_new_conversation(self, sms, sender, ack_back = True):
22 | """Create a new conversation of a given message, sending the packets into the network
23 |
24 | Args:
25 | sms (string): String to send
26 | sender ([string]): list of senders
27 | """
28 |
29 | key = super().generate_random_key()
30 | ciphered_text = self.cipher_text(sms)
31 | message_to_send = self.split_message(ciphered_text)
32 | #TOCHECK *** yo miraría antes de hacer el split [ciphered_text]
33 | if(message_to_send is None):
34 | return
35 | for idx, message in enumerate(message_to_send):
36 | self.send_message(message, key, idx, idx == len(message_to_send) -1, sender, ack_back)
37 | self._controller.handle_final_message_sent(message_to_send, sender)
38 |
39 | def send_message(self, text, key, s_begin, is_fin, sender, ack_back):
40 | """Send a single packet
41 |
42 | Args:
43 | text (str): String to send
44 | key (int): Flag of the key
45 | s_begin (int): flag of the position of the packet
46 | is_fin (bool): To determine the flag of fin
47 | sender ([str]): List of sender
48 | """
49 |
50 | sms_layer = SmsTcpLayer(id=0, key=key, syn= + (not is_fin), ack=0, psh=+ (not ack_back), fin=+is_fin, s_begin=s_begin, cipher=self.cipher_mode, check_sum=0, data=text)
51 | self.send_sms(sms_layer, sender)
52 | self._controller.handle_message_sent(sms_layer, sender)
53 |
54 | def cipher_text(self, text):
55 | """Encode the message with the given cipher methdo
56 |
57 | Args:
58 | text (str): Message to encode
59 |
60 | Returns:
61 | str: Message encoded
62 | """
63 |
64 | cipher_text = ""
65 | if(self.cipher_mode == 0):
66 | cipher_text = SmsTcp.encode_base_64(text)
67 | elif (self.cipher_mode == 1):
68 | aes_cypher = AESCipher()
69 | cipher_text = aes_cypher.encrypt_message(self.cipher_key, text)
70 | else:
71 | cipher_text = SmsTcp.encode_base_64(text)
72 |
73 | return cipher_text
74 |
75 | def split_message(self, cipher_text):
76 | """Split message in n given parts
77 |
78 | Args:
79 | cipher_text (str): Encoded message to split
80 |
81 | Returns:
82 | [str]: List with all parts splitted
83 | """
84 |
85 | sms_len = self.data_lenght
86 | return [cipher_text[i:i+sms_len] for i in range(0, len(cipher_text), sms_len)]
87 |
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/test/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Telefonica/SDK-SMS-Stack/05aa8bc99152b163dd38d9db3597efb8f9496034/sms-stack-python/sms_stack/test/__init__.py
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/test/test_main.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 |
4 | import sys, os
5 | current_path = os.path.dirname(os.path.abspath(__file__))
6 | sys.path.insert(0, current_path + "/../")
7 |
8 | from ..sms_tcp_layer import SmsTcpLayer
9 | from ..sms_tcp import SmsTcp
10 |
11 |
12 | def test_sms_tcp_layer_encode():
13 | result = SmsTcpLayer(id=0,
14 | key=17,
15 | syn=1,
16 | ack=1,
17 | psh=1,
18 | fin=1,
19 | s_begin=0,
20 | cipher=0,
21 | check_sum=0,
22 | data="hola que tal").enconde_sms()
23 |
24 | assert result == '08f80000000000hola que tal'
25 |
26 | def test_sms_tcp_layer_decode():
27 | sms_tcp = SmsTcpLayer()
28 | sms_tcp._decode_sms('08f80000000000hola que tal')
29 | assert sms_tcp.id == 0
30 | assert sms_tcp.key == 17
31 | assert sms_tcp.syn == 1
32 | assert sms_tcp.ack == 1
33 | assert sms_tcp.psh == 1
34 | assert sms_tcp.fin == 1
35 | assert sms_tcp.s_begin == 0
36 | assert sms_tcp.cipher == 0
37 | assert sms_tcp.check_sum == 0
38 | assert sms_tcp.data == "hola que tal"
39 |
40 | def test_sms_tcp_encode_base64():
41 | assert SmsTcp.encode_base_64("Hello world") == "SGVsbG8gd29ybGQ="
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/test/test_sms_tcp_layer.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 |
4 | import sys, os
5 | current_path = os.path.dirname(os.path.abspath(__file__))
6 | sys.path.insert(0, current_path + "/../")
7 |
8 | from ..sms_tcp_layer_formatter import SmsTcpLayerFormatter
9 |
10 |
11 | def test_hex_to_binary():
12 | test1 = SmsTcpLayerFormatter.hex_to_binary("abcd1234")
13 | test2 = SmsTcpLayerFormatter.hex_to_binary("noHex")
14 | assert (test1 is not None) and (test2 is None)
15 |
16 |
17 | def test_binary_to_hex():
18 | test1 = SmsTcpLayerFormatter.binary_to_hex("011001")
19 | test2 = SmsTcpLayerFormatter.binary_to_hex(12390)
20 | assert (test1 is not None) and (test2 is None)
21 |
22 | def test_dec_to_binary():
23 | test1 = SmsTcpLayerFormatter.dec_to_binary(1323)
24 | test2 = SmsTcpLayerFormatter.dec_to_binary("ab1d")
25 | assert (test1 is not None) and (test2 is None)
26 |
27 | def test_fill_header_string():
28 | b = "010110"
29 | length = 10
30 | response = SmsTcpLayerFormatter.fill_header_string(b, length)
31 | assert len(response) == length
32 |
33 | def test_fill_header_binary():
34 | b = "010110"
35 | length = 59
36 | response = SmsTcpLayerFormatter.fill_header_string(b, length)
37 | assert len(response) == length
--------------------------------------------------------------------------------
/sms-stack-python/sms_stack/test/test_sms_tcp_receiver.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 |
4 | import sys, os
5 | current_path = os.path.dirname(os.path.abspath(__file__))
6 | sys.path.insert(0, current_path + "/../")
7 |
8 | from ..sms_tcp_receiver import SmsTcpReceiver
9 | from ..sms_tcp_layer import SmsTcpLayer
10 |
11 |
12 | def test_add_message(capsys):
13 | mock = SmsTcpReceiver(0, "key", None, None)
14 | before = len(mock._message_received)
15 | hex = "12fab"
16 | mock.add_new_message(hex, "receiver")
17 | captured = capsys.readouterr()
18 | assert len(mock._message_received) > before
19 | assert "Error" not in captured.out
20 |
21 |
22 | def test_add_message_launch_exception(capsys):
23 | mock = SmsTcpReceiver(1, "key", None, None)
24 | not_hex = "ZZZ"
25 | mock.add_new_message(not_hex, "receiver")
26 | captured = capsys.readouterr()
27 | assert "Error implementing sms layer" in captured.out
28 | assert "Error converting hexadecimal to binary... input: {}".format(not_hex) in captured.out
29 |
30 | def test_missing_number_null():
31 | mock = SmsTcpReceiver(1, "key", None, None)
32 | mock.missing_numbers([])
33 | assert len(mock.missing_numbers([])) == 0
34 |
35 | def test_missing_number_fail_2():
36 | mock = SmsTcpReceiver(1, "key", None, None)
37 | my_list = [SmsTcpLayer(s_begin = 3), SmsTcpLayer(s_begin=1)]
38 | data_len = len(mock.missing_numbers(my_list))
39 | assert data_len == 2
--------------------------------------------------------------------------------
/sms-stack-typescript/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 | .env.test
60 |
61 | # parcel-bundler cache (https://parceljs.org/)
62 | .cache
63 |
64 | # next.js build output
65 | .next
66 |
67 | # nuxt.js build output
68 | .nuxt
69 |
70 | # vuepress build output
71 | .vuepress/dist
72 |
73 | # Serverless directories
74 | .serverless/
75 |
76 | # FuseBox cache
77 | .fusebox/
78 |
79 | # DynamoDB Local files
80 | .dynamodb/
81 | \.vscode/
82 |
83 | lib/
84 |
85 | \.DS_Store
86 |
--------------------------------------------------------------------------------
/sms-stack-typescript/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "trailingComma": "all",
4 | "singleQuote": true
5 | }
--------------------------------------------------------------------------------
/sms-stack-typescript/README.md:
--------------------------------------------------------------------------------
1 | # SMS Stack Typescript
2 |
--------------------------------------------------------------------------------
/sms-stack-typescript/jestconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "transform": {
3 | "^.+\\.(t|j)sx?$": "ts-jest"
4 | },
5 | "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
6 | "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"]
7 | }
--------------------------------------------------------------------------------
/sms-stack-typescript/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sms-stack",
3 | "version": "1.1.1",
4 | "description": "Sms Stack for Typescript",
5 | "main": "lib/index.js",
6 | "types": "lib/index.d.ts",
7 | "scripts": {
8 | "test": "jest --config jestconfig.json",
9 | "build": "tsc",
10 | "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
11 | "lint": "tslint -p tsconfig.json",
12 | "prepare": "npm run build",
13 | "prepublishOnly": "npm test",
14 | "preversion": "npm run lint",
15 | "version": "npm run format && git add -A src",
16 | "postversion": "git push && git push --tags"
17 | },
18 | "keywords": [
19 | "SMS",
20 | "Stack",
21 | "SMSStack",
22 | "Elevenpaths",
23 | "Telefonica"
24 | ],
25 | "author": "Lucas Fernandez",
26 | "license": "ISC",
27 | "devDependencies": {
28 | "@types/jest": "^23.3.10",
29 | "jest": "^23.6.0",
30 | "prettier": "^1.15.3",
31 | "ts-jest": "^23.10.5",
32 | "tslint": "^5.12.0",
33 | "tslint-config-prettier": "^1.17.0",
34 | "typescript": "^3.2.2"
35 | },
36 | "files": [
37 | "lib/**/*"
38 | ],
39 | "dependencies": {
40 | "axios": "^0.18.0",
41 | "buffer": "^5.2.1",
42 | "request": "^2.88.0",
43 | "request-promise-native": "^1.0.5",
44 | "rxjs": "^6.3.3"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/sms-stack-typescript/src/__tests__/Main.test.ts:
--------------------------------------------------------------------------------
1 | // import { SMSStack } from '../index';
2 | // test('New Sms', () => {
3 | // expect(SMSStack('Hola que tal')).toBe('Hola que tal');
4 | // });
5 |
6 | import { SMSTCPlayer, TcpLayer } from '../smsTcpLayer';
7 | test('Encode Tcp Layer', () => {
8 | const layerTest: TcpLayer = {id: 0, key: 17, syn: 1, ack: 1, psh: 1, fin: 1, sBegin: 0, cipher: 0, checkSum: 0, data: "hola que tal" };
9 | expect(SMSTCPlayer.encodeSMS(layerTest)).toBe('08f80000000000hola que tal');
10 | });
11 |
12 | test('Decode Tcp Layer', () => {
13 | const layerTest: TcpLayer = {id: 0, key: 17, syn: 1, ack: 1, psh: 1, fin: 1, sBegin: 0, cipher: 0, checkSum: 0, data: "hola que tal" };
14 | expect(SMSTCPlayer.decodeSMS('08f80000000000hola que tal')).toEqual(layerTest);
15 | })
16 |
17 |
18 | import { SMSTCP } from '../smsTcp';
19 | test('Encode Base64', () => {
20 | expect(SMSTCP.encodeBase64('Hello world')).toBe('SGVsbG8gd29ybGQ=');
21 | })
22 |
--------------------------------------------------------------------------------
/sms-stack-typescript/src/arrayExt.ts:
--------------------------------------------------------------------------------
1 | export class ArrayExt extends Array {
2 | /**
3 | * Generates an array of numbers between a ragne
4 | *
5 | * @param from Starting number of the range
6 | * @param to End of the range
7 | * @param step Steps between the count
8 | */
9 | public static range(from: number, to: number, step: number): number[] {
10 | return Array.from(Array(~~((to - from) / step) + 1)).map(
11 | (v, k) => from + k * step
12 | );
13 | }
14 | }
--------------------------------------------------------------------------------
/sms-stack-typescript/src/index.ts:
--------------------------------------------------------------------------------
1 | export { SMSTCPlayer } from "./smsTcpLayer";
2 | export { SmsTcpController } from "./smsTcpController";
3 | export { SmsTcpAppLayer } from "./smsTcpAppLayer";
4 | export { SmsTcpControllerObserver } from "./smsTcpControllerObserver";
5 |
6 | // Interface to implement in order to be able to send sms
7 | export interface SmsBroadcaster {
8 | sendSms(sms: string, sender: string): void;
9 | }
10 |
11 | // Interface to implement in order to receive messages
12 | export interface SmsReceived {
13 | Originator: string,
14 | MessageText: string
15 | }
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/sms-stack-typescript/src/smsTcp.ts:
--------------------------------------------------------------------------------
1 | import { Buffer } from 'buffer';
2 | import { SmsBroadcaster } from './index';
3 | import { SMSTCPlayer, TcpLayer } from './smsTcpLayer'
4 |
5 | export class SMSTCP {
6 |
7 | public cipherKey: string;
8 | public chipherMode: number;
9 | protected readonly smsLenght: number = 140;
10 | protected readonly headerLength: number = 14;
11 | private readonly dataLeghth: number;
12 | private smsBroadcaster: SmsBroadcaster;
13 |
14 | /**
15 | * Base class with blueprints to handle the sms stream
16 | * @param cipherMode Cipher mode | 0, Base64 | 1, PSK AES CBC
17 | * @param cipherKey Pre shared key for PSK AES CBC Mode
18 | * @param smsBroadcaster Broadcast object to send message
19 | */
20 | constructor(cipherMode: number, cipherKey: string, smsBroadcaster: SmsBroadcaster){
21 | this.dataLeghth = this.smsLenght - this.headerLength;
22 | this.cipherKey = cipherKey;
23 | this.chipherMode = cipherMode;
24 | this.smsBroadcaster = smsBroadcaster;
25 | }
26 |
27 |
28 | /**
29 | * Encodes a tcp layer and send it through the sms broadcaster
30 | * @param tcpLayer Layer of the sms stack protocol
31 | * @param phoneNo Address to send
32 | */
33 | public sendSms(tcpLayer: TcpLayer, phoneNo: string) {
34 | const smsResponse = SMSTCPlayer.encodeSMS(tcpLayer);
35 | this.smsBroadcaster.sendSms(smsResponse, phoneNo);
36 | }
37 |
38 | /**
39 | * Generates random key
40 | */
41 | public generateRandomKey(): number {
42 | return Math.floor(Math.random() * 254) + 1
43 | }
44 |
45 | /**
46 | * Encode the text in Base64
47 | * @param text Text to encode
48 | */
49 | public static encodeBase64(text: string): string {
50 | return Buffer.from(text, 'binary').toString('base64')
51 | }
52 |
53 | /**
54 | * Decode the Base64 text
55 | * @param base64 Text to decode
56 | */
57 | public static decodeBase64(base64: string): string{
58 | return Buffer.from(base64, 'base64').toString('binary');
59 | }
60 |
61 | // TODO - Implement cipher AES
62 |
63 | }
--------------------------------------------------------------------------------
/sms-stack-typescript/src/smsTcpAppLayer.ts:
--------------------------------------------------------------------------------
1 | //Abstract class with helper methods
2 | export abstract class SmsTcpAppLayer {
3 |
4 | /**
5 | * Convert hexadecimal string to binary string
6 | * @param hex Hexadecimal string
7 | */
8 | protected static hexToBinary(hex: string): string {
9 | if (!this.checkHex(hex)) throw 'Error parsing hexadecimal';
10 | return parseInt(hex, 16).toString(2);
11 | }
12 |
13 | /**
14 | * Convert Binary string to hexadecimal string
15 | * @param bin Binary string
16 | */
17 | protected static binaryToHex(bin: string): string {
18 | if(!this.checkBin(bin)) throw 'Error parsing binary';
19 | return parseInt(bin,2).toString(16);
20 | }
21 |
22 |
23 | /**
24 | * Checks if the Binary string is well formed
25 | * @param text Binary string
26 | */
27 | protected static checkBin(text: string): boolean{
28 | return/^[01]{1,64}$/.test(text);
29 | }
30 |
31 | /**
32 | * Checks if the Hexadecimal string is well formed
33 | * @param text Hexadecimal string
34 | */
35 | protected static checkHex(text: string): boolean {
36 | return /^[0-9A-Fa-f]{1,64}$/.test(text);
37 | }
38 |
39 | /**
40 | * Fill the binary header with required zeroes
41 | * @param header Binary header
42 | * @param requiredSize Requiered size of the header
43 | */
44 | protected static fillHeaderBinary(header: number, requiredSize: number): string {
45 | const headerToString = this.dec2Bin(header);
46 | return this.fillHeaderString(headerToString, requiredSize);
47 | }
48 |
49 | /**
50 | * Fill the binary string header with required zeroes
51 | * @param header Binary String header
52 | * @param requiredSize Requiered size of the header
53 | */
54 | protected static fillHeaderString(header: string, requiredSize: number): string {
55 | const filler = Array((requiredSize - header.length) + 1).join('0');
56 | return `${filler}${header}`;
57 | }
58 |
59 |
60 | /**
61 | * Transform decimal number to binary string
62 | * @param dec Decilmal number
63 | */
64 | protected static dec2Bin(dec: number): string{
65 | if(dec >= 0) {
66 | return dec.toString(2);
67 | }
68 | else {
69 | return (~dec).toString(2);
70 | }
71 | }
72 |
73 | }
--------------------------------------------------------------------------------
/sms-stack-typescript/src/smsTcpController.ts:
--------------------------------------------------------------------------------
1 | import { Observable } from 'rxjs';
2 | import { SmsTcpReceiver } from "./smsTcpReceiver";
3 | import { SMSTCPlayer } from "./smsTcpLayer";
4 | import { SmsTcpSender } from "./smsTcpSender";
5 | import { SmsBroadcaster, SmsReceived } from "./index";
6 | import { SmsTcpControllerObserver } from "./smsTcpControllerObserver";
7 | import { SMSTCP } from "./smsTcp";
8 |
9 |
10 | export class SmsTcpController {
11 | private receiver: SmsTcpReceiver;
12 | private sender: SmsTcpSender;
13 | private cipherMode: number;
14 | private cipherKey: string;
15 | private observer: SmsTcpControllerObserver;
16 |
17 | constructor(cipherMode: number = 0, cipherKey: string = "", observer: SmsTcpControllerObserver, broadcasterRec: Observable, broadcasterSend: SmsBroadcaster){
18 | this.cipherMode = cipherMode ;
19 | this.cipherKey = cipherKey;
20 | this.receiver = new SmsTcpReceiver(cipherMode, cipherKey, this, broadcasterRec, broadcasterSend);
21 | this.sender = new SmsTcpSender(cipherMode, cipherKey, this, broadcasterSend);
22 | this.observer = observer;
23 | }
24 |
25 |
26 | public handleFinalMessageReceived(messages: string[], sender: string){
27 | this.observer.handleFinalMessageReceived(messages, sender);
28 | }
29 |
30 | public handleMessageReceived(layer: SMSTCPlayer, sender: string) {
31 | this.observer.handleMessageReceived(layer, sender);
32 | }
33 |
34 | public handleFinalMessageSent(messages: string[], recipient: string){
35 | this.observer.handleFinalMessageSent(messages, recipient);
36 | }
37 |
38 | public handleMessageSent(layer: SMSTCPlayer, recipient: string) {
39 | this.observer.handleMessageSent(layer, recipient);
40 | }
41 |
42 | public sendMessage(sms: string, recipient: string, ackBack = true){
43 | this.sender.createNewConversation(sms, recipient, ackBack);
44 | }
45 |
46 | public processMessage(message: string[]): string {
47 | const finalMessage = message.join("");
48 | switch(this.cipherMode) {
49 | case 0:
50 | return SMSTCP.decodeBase64(finalMessage);
51 | case 1:
52 | //TODO - implement AES cipher
53 | return "";
54 | default:
55 | return "";
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/sms-stack-typescript/src/smsTcpControllerObserver.ts:
--------------------------------------------------------------------------------
1 | import { SMSTCPlayer } from "./smsTcpLayer";
2 |
3 | // Abstract class to inherit
4 | export abstract class SmsTcpControllerObserver {
5 | public handleFinalMessageReceived(messages: string[], sender: string){}
6 |
7 | public handleMessageReceived(layer: SMSTCPlayer, sender: string) {}
8 |
9 | public handleFinalMessageSent(messages: string[], recipient: string){}
10 |
11 | public handleMessageSent(layer: SMSTCPlayer, recipient: string) {}
12 | }
13 |
--------------------------------------------------------------------------------
/sms-stack-typescript/src/smsTcpLayer.ts:
--------------------------------------------------------------------------------
1 | import { SmsTcpAppLayer } from "./smsTcpAppLayer";
2 |
3 | // Abstract interface
4 | export interface TcpLayer {
5 | id: number;
6 | key: number;
7 | syn: number;
8 | ack: number;
9 | psh: number;
10 | fin: number;
11 | sBegin: number;
12 | cipher: number;
13 | checkSum: number;
14 | data: string;
15 | }
16 |
17 | export class SMSTCPlayer extends SmsTcpAppLayer {
18 |
19 | constructor() {
20 | super()
21 | }
22 |
23 | public static checkIntegrity(id: number) {
24 | return id === 0;
25 | }
26 |
27 | /**
28 | * Transform a coded string into a TcpLayer object
29 | * @param sms
30 | */
31 | public static decodeSMS(sms: string): TcpLayer {
32 | const headersSms = this.fillHeaderString(this.hexToBinary(sms.substr(0, 14)), 56);
33 | const dataSms = sms.substr(14, sms.length);
34 | const id = parseInt(headersSms.substr(0, 1), 2);
35 | const key = parseInt(headersSms.substr(1, 8), 2);
36 | const syn = parseInt(headersSms.substr(9, 1), 2);
37 | const ack = parseInt(headersSms.substr(10, 1), 2);
38 | const psh = parseInt(headersSms.substr(11, 1), 2);
39 | const fin = parseInt(headersSms.substr(12, 1), 2);
40 | const sBegin = parseInt(headersSms.substr(13, 8), 2);
41 | const cipher = parseInt(headersSms.substr(21, 3), 2);
42 | const checkSum = parseInt(headersSms.substr(24, 32), 2);
43 |
44 | const tcpLayer: TcpLayer = {id: id, key: key, syn: syn, ack: ack, psh: psh, fin: fin, sBegin: sBegin, cipher: cipher, checkSum: checkSum, data: dataSms};
45 | return tcpLayer;
46 | }
47 |
48 | /**
49 | * Encodes a Sms Stack layer object into a string
50 | * @param layer SmsStack layer
51 | */
52 | public static encodeSMS(layer: TcpLayer): string {
53 | const idSMS = this.fillHeaderBinary(layer.id, 1);
54 | const keySMS = this.fillHeaderBinary(layer.key, 8);
55 | const synSMS = this.fillHeaderBinary(layer.syn, 1);
56 | const ackSMS = this.fillHeaderBinary(layer.ack, 1);
57 | const pshSMS = this.fillHeaderBinary(layer.psh, 1);
58 | const finSMS = this.fillHeaderBinary(layer.fin, 1);
59 | const sBeginSMS = this.fillHeaderBinary(layer.sBegin, 8);
60 | const cipherSMS = this.fillHeaderBinary(layer.cipher, 3);
61 | const checkSumSMS = this.fillHeaderBinary(layer.checkSum, 32);
62 |
63 | const headersBinary: string = idSMS + keySMS + synSMS + ackSMS + pshSMS + finSMS + sBeginSMS + cipherSMS + checkSumSMS;
64 | const headersHexa = this.fillHeaderString(this.binaryToHex(headersBinary), 14);
65 |
66 | return headersHexa + layer.data;
67 | }
68 |
69 | /**
70 | * Constructs an Sms Stack packet with packet loss info
71 | * @param layer Base Tcp Layer
72 | * @param sBegin Index of missing packet
73 | */
74 | public static messagePacketLost(layer: TcpLayer, sBegin?: number): TcpLayer {
75 | const idx = sBegin !== null ? sBegin : layer.sBegin;
76 | const tcpLayer: TcpLayer = { id: layer.id, key: layer.key, syn: 0, ack: 1, psh: 0, fin: 0, sBegin: idx!, cipher: layer.cipher, checkSum: layer.checkSum, data: "" }
77 | return tcpLayer;
78 | }
79 |
80 | /**
81 | * Contructs an Sms Packet Fin layer fin packet
82 | * @param layer Base Tcp Layer
83 | */
84 | public static messagePacketFin(layer: TcpLayer): TcpLayer {
85 | const tcpLayer: TcpLayer = { id: layer.id, key: layer.key, syn: 0, ack: 1, psh: 0, fin: 1, sBegin: layer.sBegin, cipher: layer.cipher, checkSum: layer.checkSum, data: "" }
86 | return tcpLayer;
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/sms-stack-typescript/src/smsTcpReceiver.ts:
--------------------------------------------------------------------------------
1 | import { SMSTCP } from "./smsTcp";
2 | import { Observable, Subject } from 'rxjs';
3 | import { SMSTCPlayer, TcpLayer } from "./smsTcpLayer";
4 | import { SmsTcpController } from "./smsTcpController";
5 | import { SmsBroadcaster, SmsReceived } from "./index"
6 | import { ArrayExt } from "./arrayExt";
7 |
8 | export class SmsTcpReceiver extends SMSTCP {
9 |
10 | private controller?: SmsTcpController;
11 | private messageReceived: TcpLayer[] = [];
12 |
13 | /**
14 | * Class that handles the reception of Sms
15 | * @param cipherMode Cipher mode | 0, Base64 | 1, PSK AES CBC
16 | * @param cipherKey Pre shared key for PSK AES CBC Mode
17 | * @param controller Controller class
18 | * @param broadcasterRec Broadcast object to receive message
19 | * @param broadcasterSend Broadcast object to send message
20 | */
21 | constructor(cipherMode: number, cipherKey: string, controller:SmsTcpController, broadcasterRec: Observable, broadcasterSend: SmsBroadcaster) {
22 | super(cipherMode, cipherKey, broadcasterSend);
23 | this.controller = controller;
24 | broadcasterRec.subscribe(sms => {
25 | this.addNewMessage(sms.MessageText, sms.Originator);
26 | })
27 | }
28 |
29 | /**
30 | * Adds new message to the protocol stack
31 | * @param sms Sms received
32 | * @param Sender Sender number
33 | */
34 | public addNewMessage(sms: string, sender: string) {
35 | let smsLayer: TcpLayer;
36 | try {
37 | smsLayer = SMSTCPlayer.decodeSMS(sms);
38 | }
39 | catch(e) {
40 | console.log('Error:', e);
41 | return;
42 | }
43 | this.messageReceived.push(smsLayer);
44 | if(this.controller !== null){
45 | this.controller!.handleMessageReceived(smsLayer, sender)
46 | }
47 | if(smsLayer.fin === 1 && smsLayer.ack === 0){
48 | setTimeout(() => {
49 | this.checkSmsTcpStream(smsLayer, sender);
50 | }, 5000)
51 | }
52 | }
53 |
54 |
55 | /**
56 | * Checks the stream in order to detect loss in Stack
57 | * @param sms Sms Stack end packet
58 | * @param receiver Name of the receiver
59 | */
60 | private checkSmsTcpStream(sms: TcpLayer, receiver: string){
61 | const smsStream = this.messageReceived
62 | .filter(x => x.key === sms.key)
63 | .sort((x, y) => x.sBegin - y.sBegin);
64 | const messages = smsStream.map(x => x.data);
65 | const smsStreamIndex = smsStream.map(x => x.sBegin);
66 | const dataStream = ArrayExt.range(0, sms.sBegin, 1);
67 | const missing = dataStream.filter(item => smsStreamIndex.indexOf(item) < 0)
68 | if(missing.length > 0){
69 | const min = Math.min(...missing);
70 | const response_failed = SMSTCPlayer.messagePacketLost(sms, min);
71 | this.sendSms(response_failed, receiver)
72 | this.messageReceived = this.removeSmsBy(sms.key, min);
73 | return;
74 | }
75 | // Control no return
76 | if(sms.psh == 0){
77 | const response = SMSTCPlayer.messagePacketFin(sms);
78 | this.sendSms(response, receiver);
79 | }
80 | this.messageReceived = this.removeSmsBy(sms.key);
81 | this.controller!.handleFinalMessageReceived(messages, receiver);
82 | }
83 |
84 |
85 | /**
86 | * Removes an Sms Stream by its key identifier
87 | * @param key Key identifier of the stream
88 | * @param sBegin Number of layer to send
89 | */
90 | private removeSmsBy(key: number, sBegin?: number): TcpLayer[]{
91 | if(sBegin != null){
92 | return this.messageReceived.filter(sms => !(sms.key === key) && (sms.sBegin >= sBegin));
93 | } else {
94 | return this.messageReceived.filter(sms => !(sms.key === key));
95 | }
96 | }
97 |
98 | }
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/sms-stack-typescript/src/smsTcpSender.ts:
--------------------------------------------------------------------------------
1 | import { SMSTCP } from "./smsTcp";
2 | import { SmsBroadcaster } from "./index"
3 | import { SmsTcpController } from "./smsTcpController";
4 | import { TcpLayer } from "./smsTcpLayer";
5 |
6 | export class SmsTcpSender extends SMSTCP {
7 |
8 | private controller: SmsTcpController;
9 |
10 | constructor(cipherMode: number, cipherKey: string, controller: SmsTcpController, broadcastSend: SmsBroadcaster) {
11 | super(cipherMode, cipherKey, broadcastSend);
12 | this.controller = controller;
13 |
14 | }
15 |
16 | /**
17 | * Creates a new conversation with a given sms and recipient
18 | * @param sms Sms to send
19 | * @param recipient Phone number of the
20 | * @param ackBack
21 | */
22 | public createNewConversation(sms: string, recipient: string, ackBack = true) {
23 | const key = this.generateRandomKey();
24 | const cipherText = this.cipherText(sms);
25 | const messagesToSend = this.splitMessage(cipherText);
26 | if(messagesToSend == null){
27 | return;
28 | }
29 | messagesToSend!.forEach((item, index) => {
30 | this.sendMessage(item, key, index, index == messagesToSend.length - 1, recipient, ackBack);
31 | })
32 | this.controller.handleFinalMessageSent(messagesToSend, recipient);
33 | }
34 |
35 | /**
36 | * Sends a single message in an Sms Stack Packet
37 | * @param text Text to send
38 | * @param key Stream key
39 | * @param sBegin SBegin flag
40 | * @param isFin Indicates if the packet is Fin
41 | * @param recipient Recipient name
42 | * @param ackBack Wether if we want an acknowledgment or not
43 | */
44 | private sendMessage(text: string, key: number, sBegin: number, isFin: boolean, recipient: string, ackBack: Boolean) {
45 | const smsLayer: TcpLayer = { id: 0, key: key, syn: +!(sBegin == 0), ack: 0, psh: +!ackBack, fin: +isFin, sBegin: sBegin, cipher: this.chipherMode, checkSum: 0, data: text }
46 | this.sendSms(smsLayer, recipient);
47 | this.controller.handleMessageSent(smsLayer, recipient)
48 | }
49 |
50 | /**
51 | * Cipher text with the given method
52 | * @param text Text to cipher
53 | */
54 | private cipherText(text: string): string {
55 | let cipherText: string = "";
56 | switch(this.chipherMode) {
57 | case 0:
58 | cipherText = SMSTCP.encodeBase64(text);
59 | break;
60 | case 1:
61 | // AES CIPHER
62 | break;
63 | default:
64 | cipherText = SMSTCP.encodeBase64(text);
65 | break;
66 | }
67 | return cipherText;
68 | }
69 |
70 | /**
71 | * Split the message in n parts to fit the sms length restriction
72 | * @param cipherText Final text encoded to send
73 | */
74 | private splitMessage(cipherText: string): string[] | null {
75 | const length = this.smsLenght;
76 | return cipherText.match(new RegExp('(.|[\r\n]){1,' + length + '}', 'g'));
77 | }
78 |
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/sms-stack-typescript/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "declaration": true,
6 | "outDir": "./lib",
7 | "strict": true,
8 | "sourceMap": true,
9 | "lib": ["es5", "es2015", "dom", "scripthost"]
10 | },
11 | "include": ["src"],
12 | "exclude": ["node_modules", "**/__tests__/*"]
13 | }
--------------------------------------------------------------------------------
/sms-stack-typescript/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["tslint:recommended", "tslint-config-prettier"]
3 | }
--------------------------------------------------------------------------------