Browse code

Inital commit of AUTO Uploader

Richard Cornwell (K9RCP) authored on 01/27/2022 11:20:25
Showing 8 changed files
1 1
new file mode 100644
2 2
Binary files /dev/null and b/NWJS-AUTO-UPLOADER/package.nw/images/bad.png differ
3 3
new file mode 100644
4 4
Binary files /dev/null and b/NWJS-AUTO-UPLOADER/package.nw/images/bg.jpg differ
5 5
new file mode 100644
6 6
Binary files /dev/null and b/NWJS-AUTO-UPLOADER/package.nw/images/good.png differ
7 7
new file mode 100644
8 8
Binary files /dev/null and b/NWJS-AUTO-UPLOADER/package.nw/images/upload.png differ
9 9
new file mode 100644
... ...
@@ -0,0 +1,220 @@
1
+<!DOCTYPE html>
2
+
3
+  <html lang="en">
4
+
5
+  <head>
6
+    <meta charset="UTF-8">
7
+    <title>Auto Upload SpotRep - K9RCP</title>
8
+<style>
9
+html { 
10
+  background: url('images/bg.jpg') no-repeat center center fixed; 
11
+  -webkit-background-size: cover;
12
+  -moz-background-size: cover;
13
+  -o-background-size: cover;
14
+  background-size: cover;
15
+}
16
+
17
+#status-bar {
18
+    position: absolute;
19
+    margin: 0 0 0 0;
20
+    left: 0px;
21
+    bottom: 0px;
22
+    z-index: 1;
23
+    padding: 0px;
24
+    width: 100%;
25
+	background-color: white;
26
+}
27
+#main{
28
+  -moz-border-radius:10px;
29
+  -webkit-border-radius:10px;
30
+  border-radius:10px;
31
+  background: #fff; /* fallback for browsers that don't understand rgba */
32
+  border: solid 10px #000; /* fallback for browsers that don't understand rgba */
33
+  background-color: rgba(255,255,255,0.8); /* slighly transparent white */
34
+  border-color: rgba(0,0,0,0.2); /*Very transparent black*/
35
+}
36
+</style>
37
+  </head>
38
+
39
+  <body>
40
+ 
41
+    <div id="main"><center>
42
+<table style="width:100%">
43
+  <tr>
44
+    <td>Callsign: <input type="text" id="callsign" onkeyup="updateCall()" name="name" required
45
+       minlength="3" maxlength="8" size="10" /><span id="file-status"></span></td>
46
+    <td><center><div id="status"></div></center></td>
47
+  </tr>
48
+  
49
+</table>
50
+<button onclick="gui.Shell.openExternal('http://k9rcp-server.local.mesh/spotrep/');">View Data</button>
51
+	</center>
52
+	</div>
53
+	<div id="status-bar"> Status: </div>
54
+	<script src="./md5.js"></script>
55
+    <script>
56
+	      var gui = require('nw.gui');
57
+        var win = gui.Window.get();
58
+        win.on('new-win-policy', function (frame, url, policy) {
59
+            policy.forceNewPopup();
60
+        });
61
+	function mf(formato) {
62
+    var hor, hor2, x;
63
+    var fechai = new Date();
64
+    var ano = fechai.getYear() + 1900;
65
+    var ano2 = ("" + (fechai.getYear() + 1900)).slice(-2);
66
+    var mes = ("0" + (fechai.getMonth() + 1)).slice(-2);
67
+    var dia = ("0" + fechai.getDate()).slice(-2);
68
+    hor = hor2 = ("0" + fechai.getHours()).slice(-2);
69
+    hor2 = fechai.getHours();
70
+	if (fechai.getHours() > 12) {
71
+        hor2 = fechai.getHours() - 12;
72
+	}
73
+	
74
+	
75
+    if (fechai.getHours() > 11) {
76
+             x = "PM";
77
+    } else {
78
+        x = "AM";
79
+    }
80
+    var min = ("0" + fechai.getMinutes()).slice(-2);
81
+    var seg = ("0" + fechai.getSeconds()).slice(-2);
82
+    var fecha = formato.reemplaza("YyMDHhISx".split(''), [ano, ano2, mes, dia, hor, hor2, min, seg, x]);
83
+    return fecha;
84
+}
85
+String.prototype.reemplaza = function(busca, reemplaza) {
86
+    var b = Array.isArray(busca);
87
+    var r = Array.isArray(reemplaza);
88
+    var ret = this;
89
+    if (b) {
90
+        for (var i in busca) {
91
+            var c = r ? (reemplaza[i] ? reemplaza[i] : "") : reemplaza;
92
+            ret = ret.replace(new RegExp(busca[i], 'g'), c);
93
+        }
94
+    } else {
95
+        var c = r ? reemplaza[0] : reemplaza;
96
+        ret = ret.replace(new RegExp(busca, 'g'), c);
97
+    }
98
+    return ret;
99
+}
100
+
101
+function memorySizeOf(obj) {
102
+    var bytes = 0;
103
+
104
+    function sizeOf(obj) {
105
+        if(obj !== null && obj !== undefined) {
106
+            switch(typeof obj) {
107
+            case 'number':
108
+                bytes += 8;
109
+                break;
110
+            case 'string':
111
+                bytes += obj.length * 2;
112
+                break;
113
+            case 'boolean':
114
+                bytes += 4;
115
+                break;
116
+            case 'object':
117
+                var objClass = Object.prototype.toString.call(obj).slice(8, -1);
118
+                if(objClass === 'Object' || objClass === 'Array') {
119
+                    for(var key in obj) {
120
+                        if(!obj.hasOwnProperty(key)) continue;
121
+                        sizeOf(obj[key]);
122
+                    }
123
+                } else bytes += obj.toString().length * 2;
124
+                break;
125
+            }
126
+        }
127
+        return bytes;
128
+    };
129
+
130
+    function formatByteSize(bytes) {
131
+        if(bytes < 1024) return bytes + " bytes";
132
+        else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KiB";
133
+        else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MiB";
134
+        else return(bytes / 1073741824).toFixed(3) + " GiB";
135
+    };
136
+
137
+    return formatByteSize(sizeOf(obj));
138
+};
139
+
140
+var updateXml, lastMd,callSign;
141
+
142
+function updateCall() {
143
+	callSign = document.getElementById("callsign").value.toUpperCase();
144
+	document.getElementById("callsign").value = document.getElementById("callsign").value.toUpperCase();
145
+	console.error(document.getElementById("callsign").value.toUpperCase());
146
+  if (fs.existsSync('/RMS Express/'+callSign+'/FormData/SPOTREP-2.txt')) {
147
+    		document.getElementById("file-status").innerHTML = ' <img src="./images/good.png" width="24px" />';
148
+		  		clearInterval(updateXml);
149
+		runapipull();
150
+		lastMd = 0;
151
+
152
+}
153
+if (!fs.existsSync('/RMS Express/'+callSign+'/FormData/SPOTREP-2.txt')) {
154
+document.getElementById("file-status").innerHTML = ' <img src="./images/bad.png" width="24px" />';
155
+document.getElementById("status-bar").innerHTML = 'Error: File does not exist: C:\\RMS Express\\'+callSign+'\\FormData\\SPOTREP-2.txt';
156
+		document.getElementById("status").innerHTML = '<h2>Upload Status</h2><img src="./images/bad.png" width="64px" />';
157
+  console.error(err);
158
+  		clearInterval(updateXml);
159
+}
160
+	
161
+	
162
+}
163
+const fs = require('fs')
164
+
165
+function runapipull() {
166
+
167
+try {
168
+  if (fs.existsSync('/RMS Express/'+callSign+'/FormData/SPOTREP-2.txt')) {
169
+    //file exists
170
+  }
171
+} catch(err) {
172
+  console.error(err)
173
+}
174
+
175
+fs.readFile('/RMS Express/'+callSign+'/FormData/SPOTREP-2.txt', 'utf8' , (err, data) => {
176
+  if (err) {
177
+    console.error(err)
178
+    return
179
+  }
180
+if (md5(data) != lastMd) {
181
+  var formData = new FormData();
182
+  formData.append('spotrep', data);
183
+  formData.append('callsign', callSign);
184
+
185
+
186
+    // Set up the request
187
+    var xhr = new XMLHttpRequest();
188
+
189
+    // Open the connection
190
+    xhr.open('POST', 'http://k9rcp-server.local.mesh/spotrep/upload.php', true);
191
+
192
+    // Set up a handler for when the task for the request is complete
193
+    xhr.onload = function () {
194
+	document.getElementById("status").innerHTML = '<h2>Upload Status</h2><img src="./images/upload.png" width="64px" />';
195
+      if (xhr.status == 200) {
196
+        console.log('Upload copmlete!');
197
+		document.getElementById("status-bar").innerHTML = 'Status: Last upload - '+mf("h:Ix")+' - '+memorySizeOf(data)+' - '+md5(data);
198
+		document.getElementById("status").innerHTML = '<h2>Upload Status</h2><img src="./images/good.png" width="64px" />';
199
+		lastMd = md5(data);
200
+		clearInterval(updateXml);
201
+		updateXml = setInterval( function(){ runapipull(); }, 5000 );
202
+      } else {
203
+        document.getElementById("status-bar").innerHTML = 'Status: Error with Status code: '+xhr.status;
204
+		document.getElementById("status").innerHTML = '<h2>Upload Status</h2><img src="./images/bad.png" width="64px" />';
205
+		clearInterval(updateXml);
206
+		updateXml = setInterval( function(){ runapipull(); }, 5000 );
207
+      }
208
+    };
209
+    // Send the data.
210
+		document.getElementById("status").innerHTML = '<h2>Upload Status</h2><img src="./images/bad.png" width="64px" />';
211
+        document.getElementById("status-bar").innerHTML = 'Status: Error Can\'t Access k9rcp-server.local.mesh';
212
+        xhr.send(formData);
213
+
214
+}})
215
+}
216
+        document.getElementById("status-bar").innerHTML = 'Please type your RMS Callsign in to Start';
217
+</script>
218
+  </body>
219
+
220
+</html>
0 221
\ No newline at end of file
1 222
new file mode 100644
... ...
@@ -0,0 +1,402 @@
1
+/*
2
+ * JavaScript MD5
3
+ * https://github.com/blueimp/JavaScript-MD5
4
+ *
5
+ * Copyright 2011, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * https://opensource.org/licenses/MIT
10
+ *
11
+ * Based on
12
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
13
+ * Digest Algorithm, as defined in RFC 1321.
14
+ * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
15
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
16
+ * Distributed under the BSD License
17
+ * See http://pajhome.org.uk/crypt/md5 for more info.
18
+ */
19
+
20
+/* global define */
21
+
22
+/* eslint-disable strict */
23
+
24
+;(function ($) {
25
+  'use strict'
26
+
27
+  /**
28
+   * Add integers, wrapping at 2^32.
29
+   * This uses 16-bit operations internally to work around bugs in interpreters.
30
+   *
31
+   * @param {number} x First integer
32
+   * @param {number} y Second integer
33
+   * @returns {number} Sum
34
+   */
35
+  function safeAdd(x, y) {
36
+    var lsw = (x & 0xffff) + (y & 0xffff)
37
+    var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
38
+    return (msw << 16) | (lsw & 0xffff)
39
+  }
40
+
41
+  /**
42
+   * Bitwise rotate a 32-bit number to the left.
43
+   *
44
+   * @param {number} num 32-bit number
45
+   * @param {number} cnt Rotation count
46
+   * @returns {number} Rotated number
47
+   */
48
+  function bitRotateLeft(num, cnt) {
49
+    return (num << cnt) | (num >>> (32 - cnt))
50
+  }
51
+
52
+  /**
53
+   * Basic operation the algorithm uses.
54
+   *
55
+   * @param {number} q q
56
+   * @param {number} a a
57
+   * @param {number} b b
58
+   * @param {number} x x
59
+   * @param {number} s s
60
+   * @param {number} t t
61
+   * @returns {number} Result
62
+   */
63
+  function md5cmn(q, a, b, x, s, t) {
64
+    return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b)
65
+  }
66
+  /**
67
+   * Basic operation the algorithm uses.
68
+   *
69
+   * @param {number} a a
70
+   * @param {number} b b
71
+   * @param {number} c c
72
+   * @param {number} d d
73
+   * @param {number} x x
74
+   * @param {number} s s
75
+   * @param {number} t t
76
+   * @returns {number} Result
77
+   */
78
+  function md5ff(a, b, c, d, x, s, t) {
79
+    return md5cmn((b & c) | (~b & d), a, b, x, s, t)
80
+  }
81
+  /**
82
+   * Basic operation the algorithm uses.
83
+   *
84
+   * @param {number} a a
85
+   * @param {number} b b
86
+   * @param {number} c c
87
+   * @param {number} d d
88
+   * @param {number} x x
89
+   * @param {number} s s
90
+   * @param {number} t t
91
+   * @returns {number} Result
92
+   */
93
+  function md5gg(a, b, c, d, x, s, t) {
94
+    return md5cmn((b & d) | (c & ~d), a, b, x, s, t)
95
+  }
96
+  /**
97
+   * Basic operation the algorithm uses.
98
+   *
99
+   * @param {number} a a
100
+   * @param {number} b b
101
+   * @param {number} c c
102
+   * @param {number} d d
103
+   * @param {number} x x
104
+   * @param {number} s s
105
+   * @param {number} t t
106
+   * @returns {number} Result
107
+   */
108
+  function md5hh(a, b, c, d, x, s, t) {
109
+    return md5cmn(b ^ c ^ d, a, b, x, s, t)
110
+  }
111
+  /**
112
+   * Basic operation the algorithm uses.
113
+   *
114
+   * @param {number} a a
115
+   * @param {number} b b
116
+   * @param {number} c c
117
+   * @param {number} d d
118
+   * @param {number} x x
119
+   * @param {number} s s
120
+   * @param {number} t t
121
+   * @returns {number} Result
122
+   */
123
+  function md5ii(a, b, c, d, x, s, t) {
124
+    return md5cmn(c ^ (b | ~d), a, b, x, s, t)
125
+  }
126
+
127
+  /**
128
+   * Calculate the MD5 of an array of little-endian words, and a bit length.
129
+   *
130
+   * @param {Array} x Array of little-endian words
131
+   * @param {number} len Bit length
132
+   * @returns {Array<number>} MD5 Array
133
+   */
134
+  function binlMD5(x, len) {
135
+    /* append padding */
136
+    x[len >> 5] |= 0x80 << len % 32
137
+    x[(((len + 64) >>> 9) << 4) + 14] = len
138
+
139
+    var i
140
+    var olda
141
+    var oldb
142
+    var oldc
143
+    var oldd
144
+    var a = 1732584193
145
+    var b = -271733879
146
+    var c = -1732584194
147
+    var d = 271733878
148
+
149
+    for (i = 0; i < x.length; i += 16) {
150
+      olda = a
151
+      oldb = b
152
+      oldc = c
153
+      oldd = d
154
+
155
+      a = md5ff(a, b, c, d, x[i], 7, -680876936)
156
+      d = md5ff(d, a, b, c, x[i + 1], 12, -389564586)
157
+      c = md5ff(c, d, a, b, x[i + 2], 17, 606105819)
158
+      b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330)
159
+      a = md5ff(a, b, c, d, x[i + 4], 7, -176418897)
160
+      d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426)
161
+      c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341)
162
+      b = md5ff(b, c, d, a, x[i + 7], 22, -45705983)
163
+      a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416)
164
+      d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417)
165
+      c = md5ff(c, d, a, b, x[i + 10], 17, -42063)
166
+      b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162)
167
+      a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682)
168
+      d = md5ff(d, a, b, c, x[i + 13], 12, -40341101)
169
+      c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290)
170
+      b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329)
171
+
172
+      a = md5gg(a, b, c, d, x[i + 1], 5, -165796510)
173
+      d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632)
174
+      c = md5gg(c, d, a, b, x[i + 11], 14, 643717713)
175
+      b = md5gg(b, c, d, a, x[i], 20, -373897302)
176
+      a = md5gg(a, b, c, d, x[i + 5], 5, -701558691)
177
+      d = md5gg(d, a, b, c, x[i + 10], 9, 38016083)
178
+      c = md5gg(c, d, a, b, x[i + 15], 14, -660478335)
179
+      b = md5gg(b, c, d, a, x[i + 4], 20, -405537848)
180
+      a = md5gg(a, b, c, d, x[i + 9], 5, 568446438)
181
+      d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690)
182
+      c = md5gg(c, d, a, b, x[i + 3], 14, -187363961)
183
+      b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501)
184
+      a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467)
185
+      d = md5gg(d, a, b, c, x[i + 2], 9, -51403784)
186
+      c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473)
187
+      b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734)
188
+
189
+      a = md5hh(a, b, c, d, x[i + 5], 4, -378558)
190
+      d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463)
191
+      c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562)
192
+      b = md5hh(b, c, d, a, x[i + 14], 23, -35309556)
193
+      a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060)
194
+      d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353)
195
+      c = md5hh(c, d, a, b, x[i + 7], 16, -155497632)
196
+      b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640)
197
+      a = md5hh(a, b, c, d, x[i + 13], 4, 681279174)
198
+      d = md5hh(d, a, b, c, x[i], 11, -358537222)
199
+      c = md5hh(c, d, a, b, x[i + 3], 16, -722521979)
200
+      b = md5hh(b, c, d, a, x[i + 6], 23, 76029189)
201
+      a = md5hh(a, b, c, d, x[i + 9], 4, -640364487)
202
+      d = md5hh(d, a, b, c, x[i + 12], 11, -421815835)
203
+      c = md5hh(c, d, a, b, x[i + 15], 16, 530742520)
204
+      b = md5hh(b, c, d, a, x[i + 2], 23, -995338651)
205
+
206
+      a = md5ii(a, b, c, d, x[i], 6, -198630844)
207
+      d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415)
208
+      c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905)
209
+      b = md5ii(b, c, d, a, x[i + 5], 21, -57434055)
210
+      a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571)
211
+      d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606)
212
+      c = md5ii(c, d, a, b, x[i + 10], 15, -1051523)
213
+      b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799)
214
+      a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359)
215
+      d = md5ii(d, a, b, c, x[i + 15], 10, -30611744)
216
+      c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380)
217
+      b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649)
218
+      a = md5ii(a, b, c, d, x[i + 4], 6, -145523070)
219
+      d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379)
220
+      c = md5ii(c, d, a, b, x[i + 2], 15, 718787259)
221
+      b = md5ii(b, c, d, a, x[i + 9], 21, -343485551)
222
+
223
+      a = safeAdd(a, olda)
224
+      b = safeAdd(b, oldb)
225
+      c = safeAdd(c, oldc)
226
+      d = safeAdd(d, oldd)
227
+    }
228
+    return [a, b, c, d]
229
+  }
230
+
231
+  /**
232
+   * Convert an array of little-endian words to a string
233
+   *
234
+   * @param {Array<number>} input MD5 Array
235
+   * @returns {string} MD5 string
236
+   */
237
+  function binl2rstr(input) {
238
+    var i
239
+    var output = ''
240
+    var length32 = input.length * 32
241
+    for (i = 0; i < length32; i += 8) {
242
+      output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff)
243
+    }
244
+    return output
245
+  }
246
+
247
+  /**
248
+   * Convert a raw string to an array of little-endian words
249
+   * Characters >255 have their high-byte silently ignored.
250
+   *
251
+   * @param {string} input Raw input string
252
+   * @returns {Array<number>} Array of little-endian words
253
+   */
254
+  function rstr2binl(input) {
255
+    var i
256
+    var output = []
257
+    output[(input.length >> 2) - 1] = undefined
258
+    for (i = 0; i < output.length; i += 1) {
259
+      output[i] = 0
260
+    }
261
+    var length8 = input.length * 8
262
+    for (i = 0; i < length8; i += 8) {
263
+      output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32
264
+    }
265
+    return output
266
+  }
267
+
268
+  /**
269
+   * Calculate the MD5 of a raw string
270
+   *
271
+   * @param {string} s Input string
272
+   * @returns {string} Raw MD5 string
273
+   */
274
+  function rstrMD5(s) {
275
+    return binl2rstr(binlMD5(rstr2binl(s), s.length * 8))
276
+  }
277
+
278
+  /**
279
+   * Calculates the HMAC-MD5 of a key and some data (raw strings)
280
+   *
281
+   * @param {string} key HMAC key
282
+   * @param {string} data Raw input string
283
+   * @returns {string} Raw MD5 string
284
+   */
285
+  function rstrHMACMD5(key, data) {
286
+    var i
287
+    var bkey = rstr2binl(key)
288
+    var ipad = []
289
+    var opad = []
290
+    var hash
291
+    ipad[15] = opad[15] = undefined
292
+    if (bkey.length > 16) {
293
+      bkey = binlMD5(bkey, key.length * 8)
294
+    }
295
+    for (i = 0; i < 16; i += 1) {
296
+      ipad[i] = bkey[i] ^ 0x36363636
297
+      opad[i] = bkey[i] ^ 0x5c5c5c5c
298
+    }
299
+    hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8)
300
+    return binl2rstr(binlMD5(opad.concat(hash), 512 + 128))
301
+  }
302
+
303
+  /**
304
+   * Convert a raw string to a hex string
305
+   *
306
+   * @param {string} input Raw input string
307
+   * @returns {string} Hex encoded string
308
+   */
309
+  function rstr2hex(input) {
310
+    var hexTab = '0123456789abcdef'
311
+    var output = ''
312
+    var x
313
+    var i
314
+    for (i = 0; i < input.length; i += 1) {
315
+      x = input.charCodeAt(i)
316
+      output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f)
317
+    }
318
+    return output
319
+  }
320
+
321
+  /**
322
+   * Encode a string as UTF-8
323
+   *
324
+   * @param {string} input Input string
325
+   * @returns {string} UTF8 string
326
+   */
327
+  function str2rstrUTF8(input) {
328
+    return unescape(encodeURIComponent(input))
329
+  }
330
+
331
+  /**
332
+   * Encodes input string as raw MD5 string
333
+   *
334
+   * @param {string} s Input string
335
+   * @returns {string} Raw MD5 string
336
+   */
337
+  function rawMD5(s) {
338
+    return rstrMD5(str2rstrUTF8(s))
339
+  }
340
+  /**
341
+   * Encodes input string as Hex encoded string
342
+   *
343
+   * @param {string} s Input string
344
+   * @returns {string} Hex encoded string
345
+   */
346
+  function hexMD5(s) {
347
+    return rstr2hex(rawMD5(s))
348
+  }
349
+  /**
350
+   * Calculates the raw HMAC-MD5 for the given key and data
351
+   *
352
+   * @param {string} k HMAC key
353
+   * @param {string} d Input string
354
+   * @returns {string} Raw MD5 string
355
+   */
356
+  function rawHMACMD5(k, d) {
357
+    return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d))
358
+  }
359
+  /**
360
+   * Calculates the Hex encoded HMAC-MD5 for the given key and data
361
+   *
362
+   * @param {string} k HMAC key
363
+   * @param {string} d Input string
364
+   * @returns {string} Raw MD5 string
365
+   */
366
+  function hexHMACMD5(k, d) {
367
+    return rstr2hex(rawHMACMD5(k, d))
368
+  }
369
+
370
+  /**
371
+   * Calculates MD5 value for a given string.
372
+   * If a key is provided, calculates the HMAC-MD5 value.
373
+   * Returns a Hex encoded string unless the raw argument is given.
374
+   *
375
+   * @param {string} string Input string
376
+   * @param {string} [key] HMAC key
377
+   * @param {boolean} [raw] Raw output switch
378
+   * @returns {string} MD5 output
379
+   */
380
+  function md5(string, key, raw) {
381
+    if (!key) {
382
+      if (!raw) {
383
+        return hexMD5(string)
384
+      }
385
+      return rawMD5(string)
386
+    }
387
+    if (!raw) {
388
+      return hexHMACMD5(key, string)
389
+    }
390
+    return rawHMACMD5(key, string)
391
+  }
392
+
393
+  if (typeof define === 'function' && define.amd) {
394
+    define(function () {
395
+      return md5
396
+    })
397
+  } else if (typeof module === 'object' && module.exports) {
398
+    module.exports = md5
399
+  } else {
400
+    $.md5 = md5
401
+  }
402
+})(this)
0 403
\ No newline at end of file
1 404
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+{
2
+  "name": "Auto Upload SpotRep - K9RCP",
3
+  "product_string": "Auto Upload SpotRep - K9RCP",
4
+  "window" : {
5
+    "id" : "mainWindow",
6
+    "toolbar" : false,
7
+    "show" : true,
8
+    "width" : 630,
9
+    "height" : 230,
10
+	"resizable": false
11
+    },
12
+ "webkit": {
13
+    "plugin": true
14
+  },
15
+  "main": "index.html"
16
+}
0 17
\ No newline at end of file
1 18
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+<html>
2
+<body>
3
+<h3>SpotRep2 Mapping System</h3>
4
+<h4>This allows Users to Map the SpotRep2 reports into a map that can be viewed in a web browser in real time. </h4>
5
+
6
+<p>
7
+<h4>Contents</h4>
8
+
9
+<p><b>www - PHP code for the mapping</b><br>
10
+<ul>
11
+<li>Make sure to update the map tiles with your mapping tiles and accesstokens</li>
12
+</ul>
13
+</p>
14
+
15
+<p>
16
+<b>NWJS-AUTO-UPLOADER - Auto Upload SpotRep2</b><br>
17
+This NWJS(node-webkit) app allows the auto uploading of the spotrep2.txt file from the winlink callsign directory into the mapping software
18
+<ul>
19
+<li>To make this work you need to add the this package.nw to the NWJS files.
20
+
21
+Goto https://nwjs.io/ and download the normal package to get started.
22
+</li>
23
+</ul>
24
+</p>
25
+<img src="https://i.imgur.com/xu5NfGp.png" width="550px"  /><br />
26
+
27
+</body>
28
+</html>
29
+
30
+