From 5b33c5a3d0239b52b3c616d6df5ea8b72705ae62 Mon Sep 17 00:00:00 2001 From: Zezombye Date: Wed, 29 May 2019 20:25:43 +0200 Subject: [PATCH] owo --- AndroidManifest.xml | 27 ++ CADDIT.g1a | Bin 0 -> 21208 bytes Casio-Android_communication_protocol.txt | 68 +++ MainActivity.java | 548 +++++++++++++++++++++++ activity_main.xml | 86 ++++ app-release.apk | Bin 0 -> 1182034 bytes fonts.c | 341 ++++++++++++++ fonts.h | 13 + main.c | 400 +++++++++++++++++ serial.src | 25 ++ 10 files changed, 1508 insertions(+) create mode 100755 AndroidManifest.xml create mode 100755 CADDIT.g1a create mode 100755 Casio-Android_communication_protocol.txt create mode 100755 MainActivity.java create mode 100755 activity_main.xml create mode 100755 app-release.apk create mode 100755 fonts.c create mode 100755 fonts.h create mode 100755 main.c create mode 100755 serial.src diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100755 index 0000000..09daf30 --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + diff --git a/CADDIT.g1a b/CADDIT.g1a new file mode 100755 index 0000000000000000000000000000000000000000..de7784ad66bfadb37d8ab00c3982504d37e680d0 GIT binary patch literal 21208 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 Application ######### + +All the commands are in the form xx; with x being a character. +This is because of a weird bug within the addin that, for some reason, messes up the bits +after the first 3-4 characters. Therefore 3 characters long commands must be the maximum. + +Here are the different commands. The first character represents the command, +the second character 'X' represents the argument. + +Subreddit: + +To connect to a specific subreddit, the command is sX; +Since only one character is allowed the different subs are hardcoded into the addin. +'t' = /r/TalesFromTechSupport +'r' = /r/TalesFromRetail +'n' = /r/NoSleep +'c' = /r/Caddit +'a' = /r/AskReddit +'v' = viedemerde.fr (to be implemented) + +Post: + +Once the user has selected a post, the addin sends the rank of the post, which is interpreted +by the application as its ID. +The command is pX; and the rank of the post is in the range A-Y (25 posts is the maximum). + +More characters: + +Due to the reception buffer limit of 1 ko, if the application sends that the transmission is not yet finished, +the addin sends ak; once it has finished storing the characters sent. + +Next page: + +If the application sends that there is more, the user can press a button to send np; which will prompt the +application to send the next 5000 o. The 5000 o limit is because of the RAM limit; there are long posts and the +addin may not be able to stock all the data, so it is transferred with a 5000 o max. + +######### Application -> Addin ######### + +The data read by the addin must be in some kind of weird custom xml format. + +################ +NOTE: ALL communications MUST be ended with a quote ("), to inform the addin that the transmission is finished. +Therefore you must replace all quotes (whether backslashed or not) with the 0x81 character. +If you still have data to send (reached buffer limit) end your communication with a '<' and then a quote. +If you have reached the 5000 o limit but still have data to send, end it with a ';' then a quote. +################ + +Since < and > are special characters, replace them with 0x7F and 0x80 respectively. +Don't replace them with > and <, they will be displayed as ">" and "<". + +Data for posts: + +

... + +You can customise the subreddit attribute and the contents, you can put whatever you want as long as it's not +a quote or a '>'. Example: + +

+ +Data for comments: + + <1 first level comment> <2 second level comment> <3 third level comment> <1 another first lvl comment> + +Basically the post data must be in the tag, and the comments must be in a numbered tag from 1 to 9. + diff --git a/MainActivity.java b/MainActivity.java new file mode 100755 index 0000000..bd2cc1a --- /dev/null +++ b/MainActivity.java @@ -0,0 +1,548 @@ +package com.kaanaxinc.portalstudio; + +import android.app.Activity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.ParcelUuid; +import android.os.StrictMode; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnKeyListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Set; + +public class MainActivity extends Activity { + // La chaîne de caractères par défaut + private final String defaut = "Le code d'accès est inscrit sur la notice."; + Toast myToast; + Button sendPost = null; + Button sendComment = null; + ImageButton logo = null; + TextView entrezCode = null; + TextView codeSurNotice = null; + TextView texteRecu = null; + Handler bluetoothIn; + boolean currentView = false; + final int handlerState = 0; + String messageFinal = "jmesoiejsmoi"; + + BluetoothAdapter blueAdapter = BluetoothAdapter.getDefaultAdapter(); + private OutputStream outputStream; + private InputStream inStream; + ArrayList postIds = new ArrayList(); + int postNumber = 0; + String subreddit = ""; + + String[] subreddits = {"talesfromtechsupport", "talesfromretail", "caddit", "askreddit", "nosleep"}; + char[] subCommands = {'t', 'r', 'c', 'a', 'n'}; + String messageAEnvoyer = ""; + int progressionEnvoi = 0; + int progressionPage = 0; + + String connectionError = "PortalStudio n'a pas pu se connecter au portail. Vérifiez votre connexion bluetooth. Tapez sur le logo pour réessayer la connexion."; + + //Initializes the Bluetooth connection. + //Important detail: it always connects to the device that is the lowest in your paired devices list. + private void init() throws IOException { + Thread connexionThread = new Thread(new Runnable() + { + public void run() { + try { + if (blueAdapter != null) { + if (blueAdapter.isEnabled()) { + Set bondedDevices = blueAdapter.getBondedDevices(); + + if(bondedDevices.size() > 0){ + BluetoothDevice bt2 = null; + for(BluetoothDevice bt : bondedDevices) { + bt2 = bt; + } + + + BluetoothDevice device = bt2; + ParcelUuid[] uuids = device.getUuids(); + BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuids[0].getUuid()); + socket.connect(); + outputStream = socket.getOutputStream(); + inStream = socket.getInputStream(); + } + + Log.e("error", "No appropriate paired devices."); + } else { + Log.e("error", "Bluetooth is disabled."); + } + } + } catch (IOException e) { + + } + } + }); + + connexionThread.start(); + + } + + //Writes a string to the bluetooth device. + public void write(String s) throws IOException, NullPointerException { + outputStream.write(s.getBytes()); + } + + //Once this method is called, begins listening for data. + //Note: always place this method in a if checking if inStream != null. Else it will crash. + void beginListenForData() { + Thread workerThread = new Thread(new Runnable() + { + public void run() { + + byte[] buffer = new byte[256]; + int bytes; + + while(!Thread.currentThread().isInterrupted()) { + try { + bytes = inStream.read(buffer); //read bytes from input buffer + String readMessage = new String(buffer, 0, bytes); + // Send the obtained bytes to the UI Activity via handler + bluetoothIn.obtainMessage(handlerState, bytes, -1, readMessage).sendToTarget(); + } catch (IOException e) { + break; + } catch (NullPointerException e) { + toast("Null pointer exception 3"); + break; + } + } + } + }); + + workerThread.start(); + } + + //Checks if the bluetooth is enabled, and tries connecting. + void checkBluetooth() { + //Prompt user to turn on Bluetooth if Bluetooth is disabled + if (!blueAdapter.isEnabled()) { + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + startActivityForResult(enableBtIntent, 1); + } + + try { + init(); + } catch (IOException e2) { + + } + } + + void toast(String str) { + myToast.setText(str); + myToast.show(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + myToast = Toast.makeText(getBaseContext(), "", Toast.LENGTH_SHORT); + sendPost = (Button)findViewById(R.id.sendPost); + sendComment = (Button)findViewById(R.id.sendComment); + codeSurNotice = (TextView)findViewById(R.id.codeSurNotice); + entrezCode = (TextView)findViewById(R.id.entrezCode); + texteRecu = (TextView)findViewById(R.id.texteRecu); + logo = (ImageButton)findViewById(R.id.logo); + logo.setOnClickListener(logoListener); + sendPost.setOnClickListener(sendPostListener); + sendComment.setOnClickListener(sendCommentListener); + + //This code allows connecting to the internet without doing so in a new thread. + if (android.os.Build.VERSION.SDK_INT > 9) { + StrictMode.ThreadPolicy policy = + new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(policy); + } + + //Handler that receives the data from the bluetooth device. + //Any manipulation of the received data must be done here (after the messageFinal assignment to msg.obj). + bluetoothIn = new Handler() { + public void handleMessage(android.os.Message msg) { + if (msg.what == handlerState) { + toast(messageFinal); + messageFinal += (String) msg.obj; //for some reason removing the + causes it to remove the first character + texteRecu.setText(messageFinal); + if (messageFinal.matches("[\\s\\S]*\\w\\w;[\\s\\S]*")) { + char command = messageFinal.charAt(messageFinal.indexOf(";")-2); + char arg = messageFinal.charAt(messageFinal.indexOf(";")-1); + toast("command = " + command + "\narg = " + arg); + if (command == 's') { + for (int i = 0; i < subCommands.length; i++) { + if (arg == subCommands[i]) { + subreddit = subreddits[i]; + } + } + getPost("https://reddit.com/r/"+subreddit+".json"); + + } + else if (command == 'p') { + postNumber = arg-65; + try { + getComments("https://reddit.com/" + postIds.get(postNumber) + ".json"); + toast("Post ID: "+ postIds.get(postNumber)); + } catch (ArrayIndexOutOfBoundsException e) { + toast("Couldn't find a valid post rank, defaulting to the first post."); + getComments("https://reddit.com/" + postIds.get(0) + ".json"); + } + } + else if (command == 'a' && arg == 'k') { + sendString(); + } + else if (command == 'n' && arg == 'p') { + /*if (messageAEnvoyer.substring(progressionPage).length() > 5000) { + progressionPage += 5000; + }*/ + progressionEnvoi = 0; + sendString(); + } + } + } + } + }; + + } + + @Override + public void onResume() { + super.onResume(); + // connection methods are best here in case program goes into the background etc + checkBluetooth(); + } + + + + //Tapping on the logo retries the connection if it failed. + private OnClickListener logoListener = new OnClickListener() { + @Override + public void onClick(View v) { + codeSurNotice.setText("Connexion en cours..."); + try { + init(); + } catch (IOException e2) { + + } + codeSurNotice.setText(defaut); + } + }; + + //Listener for the "send post" button. Is debug and planned to be removed. + private OnClickListener sendPostListener = new OnClickListener() { + @Override + public void onClick(View v) { + messageFinal = ""; + if (inStream != null) { + beginListenForData(); + + getPost("https://reddit.com/r/" + subreddit + ".json"); + sendString(); + + } else { + toast(connectionError); + } + + + } + }; + + //Listener for the "send comment" button, is also debug. + private OnClickListener sendCommentListener = new OnClickListener() { + @Override + public void onClick(View v) { + currentView = false; + messageFinal = ""; + if (inStream != null) { + beginListenForData(); + + try { + getComments("https://reddit.com/" + postIds.get(postNumber) + ".json"); + } catch (ArrayIndexOutOfBoundsException e) { + toast("Index out of bounds!"); + } + toast("Post ID: "+ postIds.get(postNumber)); + sendString(); + + } else { + toast(connectionError); + } + + + } + }; + + void sendString() { + String aEnvoyer = ""; + messageFinal = ""; + int progTotale = progressionEnvoi + progressionPage; + //progressionEnvoi = 0; + if (messageAEnvoyer.substring(progressionPage).length() > 1000 && progressionEnvoi < 4000 + && messageAEnvoyer.substring(progTotale, progTotale+1000).length() > 1000) { + aEnvoyer = messageAEnvoyer.substring( + progTotale, progTotale + 1000) + ",\""; + + progressionEnvoi += 1000; + } else if (messageAEnvoyer.length() > progressionPage+5000){ + int max = messageAEnvoyer.lastIndexOf(messageAEnvoyer.substring(progTotale,progTotale+1000),'>'); + boolean mettreChevron = false; + if (max == -1) { //no occurrence of '>' + max = messageAEnvoyer.lastIndexOf(messageAEnvoyer.substring(progTotale,progTotale+1000),'\n'); + if (max == -1) //no occurrence of '\n' + max = progressionEnvoi+progressionPage+1000; + mettreChevron = true; //there's no occurrence of '>' so we add one + } + + aEnvoyer = messageAEnvoyer.substring(progressionEnvoi+progressionPage, max); + if (mettreChevron) { + aEnvoyer += '>'; + //inserts a '<' after + messageAEnvoyer = messageAEnvoyer.substring(0, progTotale+max) + '<' + messageAEnvoyer.substring(progTotale+max+1); + } + aEnvoyer += ";\""; + progressionPage += messageAEnvoyer.lastIndexOf('>', progressionEnvoi+progressionPage); + } else { + aEnvoyer = messageAEnvoyer.substring(progressionEnvoi+progressionPage) + "\""; + } + try { + write(aEnvoyer); + } catch (IOException e) { + + } catch (NullPointerException e) { + toast(connectionError); + } + } + + //Parses the json from a reddit url containing comments. + //Don't try to understand this, it works, that's all you need to know. + void getComments(String url) { + + String str = "test"; + try { + str = getText(url); + } catch (Exception e) { + toast("Erreur de connexion"); + } + toast(str); + String result = ""; + String textPostContent = ""; + String commentText = ""; + String commentAuthor = ""; + String commentScore = ""; + String[] jsonAttributes = {"selftext", "title"}; + String[] cmtVars = {commentAuthor, commentScore, commentText}; + String[] cmtAttributes = {"replies", "author", "score", "body"}; + + ArrayList commentLvls = new ArrayList(); + int currentComment = -1; + //first, browse through the string + int commentLvl = 1; //that way it's set to 1 after the }}], "after" of the text post + + System.out.println("Beginning comment level analysis"); + for (int i = 10; i < str.length(); i++) { + if (str.startsWith("}}], \"after\"", i)) { + commentLvl--; + } else if (str.startsWith("[{\"kind\": \"t1\"", i)) { + commentLvl++; + commentLvls.add(commentLvl); + + } else if (str.startsWith(" {\"kind\": \"t1\"", i)) { + commentLvls.add(commentLvl); + } + + } + + + + for (int i = 0; i < str.length(); i++) { + if (str.startsWith("{\"kind\": \"t3\"", i)) { + int j = 0; + while (!str.substring(i - 1, i + 11).equals("}}], \"after\"")) { + i++; + if (j < jsonAttributes.length && str.startsWith("\"" + jsonAttributes[j] + "\": ", i)) { + i += jsonAttributes[j].length() + 4; + int end = 0; + i++; + end = i; + while (!str.substring(end - 1, end + 3).equals("\", \"")) { + end++; + } + end--; + if (j == 1) + textPostContent = str.substring(i, end) + "\n" + textPostContent; + else + textPostContent += str.substring(i, end); + j++; + } + } + result += " \n"; + } else if (str.startsWith("{\"kind\": \"t1\"", i)) { + currentComment++; + int l = i; + int j = 0; + int k = 0; + while (!str.substring(l - 1, l + 11).equals("}}], \"after\"") + && !str.substring(l - 1, l + 16).equals("}}, {\"kind\": \"t1\"")) { + l++; + if (j < cmtAttributes.length && str.startsWith("\"" + cmtAttributes[j] + "\": ", l)) { + l += cmtAttributes[j].length() + 4; + + int end = l; + if (j == 0) { + + l += 57; + do { + if (str.startsWith("{\"kind\": \"t1\"", l)) { + k++; + } + if (str.startsWith("}}], \"after\"", l)) { + k--; + } + if (str.startsWith("}}, {\"kind\": \"t1\"", l)) { + l += 10; + } + l++; + } while (k != 0); + l++; + } else { + if (j != 2) { + while (!str.substring(end - 1, end + 3).equals("\", \"")) { + end++; + } + end--; + l++; + } else { + end = str.indexOf(',', l); + } + cmtVars[j - 1] = str.substring(l, end); + } + j++; + } + } + result += "<" + commentLvls.get(currentComment) + " " + cmtVars[2] + + "\n/u/" + cmtVars[0] + " " + cmtVars[1] + " upvotes>"; + } + } + result = modifyText(result); + messageAEnvoyer = result; + progressionEnvoi = 0; + sendString(); + } + + //Parses the json of a reddit sub (which contains posts) + void getPost(String url) { + String str = "test"; + //connects to the given url + try { + str = getText(url); + } catch (Exception e) { + toast("Erreur de connexion"); + } + + String posts = ""; + String currentPostTitle = ""; + String currentPostUser = ""; + String currentPostId = ""; + String currentPostSub = ""; + String currentPostUrl = ""; + String currentPostScore = ""; + String currentPostCmts = ""; + String[] postAttributes = {currentPostUrl, currentPostSub, currentPostId, currentPostUser, currentPostScore, currentPostCmts, currentPostTitle}; + String[] jsonAttributes = {"domain", "subreddit", "id", "author", "score", "num_comments", "title"}; + + for (int i = 0; i < str.length(); i++) { //browses through the string + if (str.startsWith("{\"kind\": \"t3\"", i)) { //beginning of post + int j = 0; + while (!str.substring(i - 1, i + 27).equals("}}, {\"kind\": \"t3\", \"data\": {") //loops while post is not finished + && !str.substring(i - 1, i + 11).equals("}}], \"after\"")) { + i++; + if (j < jsonAttributes.length && str.startsWith("\"" + jsonAttributes[j] + "\": ", i)) { //assigns values of attributes to their variables + i += jsonAttributes[j].length() + 4; + int end = 0; + if (j == 4 || j == 5) + end = str.indexOf(',', i); + else { + i++; + end = i; + while (!str.substring(end - 1, end + 3).equals("\", \"")) { + end++; + } + end--; + } + postAttributes[j] = str.substring(i, end); + j++; + } + } + if (postAttributes[0].startsWith("self.")) + postAttributes[0] = "self"; + else + postAttributes[0] = "ext.link"; + + postIds.add(postAttributes[2]); + posts += "

\n"; + } + + } + + messageAEnvoyer = modifyText(posts); + progressionEnvoi = 0; + sendString(); + } + + //Connects to a given url + public String getText(String url) throws Exception { + URL website = new URL(url); + URLConnection connection = website.openConnection(); + connection.setRequestProperty("User-Agent", "android:com.zezombye.caddit:v1.0 (by /u/Zezombye)"); + BufferedReader in = new BufferedReader( + new InputStreamReader( + connection.getInputStream())); + + StringBuilder response = new StringBuilder(); + String inputLine; + + while ((inputLine = in.readLine()) != null) + response.append(inputLine); + + in.close(); + return response.toString(); + } + + //Replaces special characters in the json + static String modifyText(String str) { + str = str.replaceAll("\\\\\\\"", "&q;"); //replaces \" by &q + str = str.replaceAll("\\n", "\n"); //replaces \n by the LF character + str = str.replaceAll("\\\\\\\\", "\\\\"); //replaces \\ by \ + str = str.replaceAll("&", "&"); + return str; + } + +} \ No newline at end of file diff --git a/activity_main.xml b/activity_main.xml new file mode 100755 index 0000000..05eb49c --- /dev/null +++ b/activity_main.xml @@ -0,0 +1,86 @@ + + + + + +