Project

General

Profile

Download (27.2 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / helpers / RubikNetwork.java @ e6dbe81a

1 fdec60a3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 1c327853 Leszek Koltunski
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8 fdec60a3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10 7ff3cacb leszek
package org.distorted.helpers;
11 fdec60a3 Leszek Koltunski
12 1d643a0e Leszek Koltunski
import java.io.BufferedReader;
13 b88cdd91 Leszek Koltunski
import java.io.IOException;
14 3f7a4363 Leszek Koltunski
import java.io.InputStream;
15 1d643a0e Leszek Koltunski
import java.io.InputStreamReader;
16 3f7a4363 Leszek Koltunski
import java.net.HttpURLConnection;
17
import java.net.URL;
18
import java.net.UnknownHostException;
19
import java.security.MessageDigest;
20
import java.security.NoSuchAlgorithmException;
21 1c04d054 leszek
import java.util.ArrayList;
22 3f7a4363 Leszek Koltunski
23 e4854e54 Leszek Koltunski
import android.app.Activity;
24 7fe62d1f Leszek Koltunski
import android.content.Context;
25 1780dcb0 Leszek Koltunski
import android.content.pm.PackageInfo;
26
import android.content.pm.PackageManager;
27 b88cdd91 Leszek Koltunski
import android.graphics.Bitmap;
28
import android.graphics.BitmapFactory;
29 1780dcb0 Leszek Koltunski
30 fcf7320f Leszek Koltunski
import org.distorted.objectlib.json.JsonWriter;
31 a7d8c3cd Leszek Koltunski
import org.distorted.objects.RubikObjectList;
32 36e2cbdd Leszek Koltunski
33 7bb30586 leszek
import static org.distorted.objects.RubikObjectList.SHOW_DOWNLOADED_DEBUG;
34 7ff3cacb leszek
import static org.distorted.helpers.RubikScores.LEVELS_SHOWN;
35 211b48f2 Leszek Koltunski
36 fdec60a3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
37
38 ffe7e55d Leszek Koltunski
public class RubikNetwork
39 fdec60a3 Leszek Koltunski
  {
40 46be3ddf Leszek Koltunski
  public interface ScoresReceiver
41 b8b38548 Leszek Koltunski
    {
42 65bc1da3 Leszek Koltunski
    void receive(String[][][] country, String[][][] name, int[][][] time);
43 4895fff6 Leszek Koltunski
    void message(String mess);
44 4c0cd600 Leszek Koltunski
    void error(String error);
45 b8b38548 Leszek Koltunski
    }
46
47 46be3ddf Leszek Koltunski
  public interface IconReceiver
48 63dd19c4 Leszek Koltunski
    {
49 7fe62d1f Leszek Koltunski
    void iconDownloaded(int ordinal, Bitmap bitmap, boolean downloaded);
50 46be3ddf Leszek Koltunski
    }
51
52
  public interface Updatee
53
    {
54 1c04d054 leszek
    int getType();
55 63dd19c4 Leszek Koltunski
    void receiveUpdate(RubikUpdates update);
56 1c04d054 leszek
    void objectDownloaded(String shortName);
57 63dd19c4 Leszek Koltunski
    void errorUpdate();
58
    }
59
60 46be3ddf Leszek Koltunski
  public interface Downloadee
61
    {
62
    void jsonDownloaded();
63
    }
64
65 286d73ae Leszek Koltunski
  public static final int MAX_PLACES = 10;
66 d8aa4ba8 Leszek Koltunski
67 1c04d054 leszek
  private static final int UPDATES_RUNNING = 1;
68
  private static final int UPDATES_SUCCESS = 2;
69
  private static final int UPDATES_FAILURE = 3;
70 63dd19c4 Leszek Koltunski
71 36e2cbdd Leszek Koltunski
  private final String[] hex = {
72
    "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
73
    "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f",
74
    "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
75
    "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f",
76
    "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
77
    "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f",
78
    "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",
79
    "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f",
80
    "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",
81
    "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f",
82
    "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
83
    "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f",
84
    "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",
85
    "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f",
86
    "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",
87
    "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f",
88
    "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
89
    "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f",
90
    "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
91
    "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f",
92
    "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
93
    "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af",
94
    "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7",
95
    "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf",
96
    "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",
97
    "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf",
98
    "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
99
    "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df",
100
    "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7",
101
    "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef",
102
    "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
103
    "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff"
104
    };
105
106 a59f38d6 Leszek Koltunski
  private static final String SERVER="https://distorted.org/magic/cgi-bin/";
107
108 a36b9dca Leszek Koltunski
  private static String[][][] mCountry;
109
  private static String[][][] mName;
110 65bc1da3 Leszek Koltunski
  private static int[][][] mTime;
111 a36b9dca Leszek Koltunski
  private static int[][] mPlaces;
112 688f7712 Leszek Koltunski
113 6a083c6a Leszek Koltunski
  private static RubikNetwork mThis;
114 688f7712 Leszek Koltunski
  private static String mScores = "";
115 b6606976 leszek
  private static boolean mDowRunning = false;
116
  private static boolean mSubRunning = false;
117 1c04d054 leszek
  private static ArrayList<Updatee> mUpdateeList;
118 4895fff6 Leszek Koltunski
  private static String mVersion;
119 a7d8c3cd Leszek Koltunski
  private static int mNumObjects;
120 fcf7320f Leszek Koltunski
  private static RubikUpdates mUpdates;
121 1c04d054 leszek
  private static int mUpdatesState;
122 b8b38548 Leszek Koltunski
123 a36b9dca Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
124
125
  private static void initializeStatics()
126
    {
127 a7d8c3cd Leszek Koltunski
    int newNum = RubikObjectList.getNumObjects();
128
129 5bda8973 Leszek Koltunski
    if( mCountry==null || newNum!=mNumObjects ) mCountry = new String[newNum][LEVELS_SHOWN+1][MAX_PLACES];
130
    if( mName==null    || newNum!=mNumObjects ) mName    = new String[newNum][LEVELS_SHOWN+1][MAX_PLACES];
131 65bc1da3 Leszek Koltunski
    if( mTime==null    || newNum!=mNumObjects ) mTime    = new    int[newNum][LEVELS_SHOWN+1][MAX_PLACES];
132 5bda8973 Leszek Koltunski
    if( mPlaces==null  || newNum!=mNumObjects ) mPlaces  = new    int[newNum][LEVELS_SHOWN+1];
133 fcf7320f Leszek Koltunski
134
    if( mUpdates==null ) mUpdates = new RubikUpdates();
135 a7d8c3cd Leszek Koltunski
136
    mNumObjects = newNum;
137 a36b9dca Leszek Koltunski
    }
138
139 4895fff6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
140
141 86cbdab1 Leszek Koltunski
  private static String computeHash(String stringToHash, byte[] salt)
142 4895fff6 Leszek Koltunski
    {
143 86cbdab1 Leszek Koltunski
    String generatedPassword;
144
145
    try
146
      {
147
      MessageDigest md = MessageDigest.getInstance("MD5");
148
      md.update(salt);
149
      byte[] bytes = md.digest(stringToHash.getBytes());
150
      StringBuilder sb = new StringBuilder();
151
152
      for (byte aByte : bytes)
153
        {
154
        sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
155
        }
156
157
      generatedPassword = sb.toString();
158
      }
159
    catch (NoSuchAlgorithmException e)
160
      {
161
      return "NoSuchAlgorithm";
162
      }
163
164
    return generatedPassword;
165 4895fff6 Leszek Koltunski
    }
166
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168
169 46be3ddf Leszek Koltunski
  private boolean fillValuesNormal(ScoresReceiver receiver)
170 f3e12931 Leszek Koltunski
    {
171 d8aa4ba8 Leszek Koltunski
    int begin=-1 ,end, len = mScores.length();
172 17f9a695 Leszek Koltunski
    String row;
173 f3e12931 Leszek Koltunski
174 4c0cd600 Leszek Koltunski
    if( len==0 )
175
      {
176 46be3ddf Leszek Koltunski
      receiver.error("1");
177 4c0cd600 Leszek Koltunski
      return false;
178
      }
179 90fd47b0 Leszek Koltunski
    else if( len<=2 )
180 4c0cd600 Leszek Koltunski
      {
181 46be3ddf Leszek Koltunski
      receiver.error(mScores);
182 4c0cd600 Leszek Koltunski
      return false;
183
      }
184
185 a7d8c3cd Leszek Koltunski
    for(int i=0; i<mNumObjects; i++)
186 5bda8973 Leszek Koltunski
      for(int j=0; j<=LEVELS_SHOWN; j++)
187 329c0aeb Leszek Koltunski
        {
188
        mPlaces[i][j] = 0;
189
        }
190
191 d8aa4ba8 Leszek Koltunski
    while( begin<len )
192
      {
193
      end = mScores.indexOf('\n', begin+1);
194
      if( end<0 ) end = len;
195 286d73ae Leszek Koltunski
196
      try
197
        {
198 17f9a695 Leszek Koltunski
        row = mScores.substring(begin+1,end);
199 4c0cd600 Leszek Koltunski
        fillRow(row);
200 286d73ae Leszek Koltunski
        }
201
      catch(Exception ex)
202
        {
203
        // faulty row - ignore
204
        }
205
206 d8aa4ba8 Leszek Koltunski
      begin = end;
207
      }
208 17f9a695 Leszek Koltunski
209
    return true;
210 f3e12931 Leszek Koltunski
    }
211
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213
214 d8aa4ba8 Leszek Koltunski
  private void fillRow(String row)
215 f3e12931 Leszek Koltunski
    {
216 d8aa4ba8 Leszek Koltunski
    int s1 = row.indexOf(' ');
217
    int s2 = row.indexOf(' ',s1+1);
218
    int s3 = row.indexOf(' ',s2+1);
219
    int s4 = row.indexOf(' ',s3+1);
220 286d73ae Leszek Koltunski
    int s5 = row.length();
221 d8aa4ba8 Leszek Koltunski
222
    if( s5>s4 && s4>s3 && s3>s2 && s2>s1 && s1>0 )
223
      {
224 a7d8c3cd Leszek Koltunski
      int object = RubikObjectList.getOrdinal( row.substring(0,s1) );
225 b8b38548 Leszek Koltunski
226 a7d8c3cd Leszek Koltunski
      if( object>=0 && object<mNumObjects )
227 d8aa4ba8 Leszek Koltunski
        {
228 8e3898c8 Leszek Koltunski
        int level      = Integer.parseInt( row.substring(s1+1,s2) );
229 286d73ae Leszek Koltunski
        String name    = row.substring(s2+1, s3);
230
        int time       = Integer.parseInt( row.substring(s3+1,s4) );
231
        String country = row.substring(s4+1, s5);
232 d8aa4ba8 Leszek Koltunski
233 c8249cf6 Leszek Koltunski
        if( country.equals("do") ) country = "dm"; // see RubikScores.setCountry()
234
235 5bda8973 Leszek Koltunski
        if( level>LEVELS_SHOWN ) level = LEVELS_SHOWN;
236
237
        if(level>=0)
238 d8aa4ba8 Leszek Koltunski
          {
239 8e3898c8 Leszek Koltunski
          int p = mPlaces[object][level];
240
          mPlaces[object][level]++;
241 329c0aeb Leszek Koltunski
242 8e3898c8 Leszek Koltunski
          mCountry[object][level][p] = country;
243
          mName   [object][level][p] = name;
244 65bc1da3 Leszek Koltunski
          mTime   [object][level][p] = time;
245 d8aa4ba8 Leszek Koltunski
          }
246
        }
247
      }
248 874c37b1 Leszek Koltunski
    else
249
      {
250 5d50e7a7 Leszek Koltunski
      tryDoCommand(row);
251
      }
252
    }
253
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255
256
  private void tryDoCommand(String row)
257
    {
258
    if( row.startsWith("comm") )
259
      {
260
      int colon = row.indexOf(':');
261
262
      if( colon>0 )
263 874c37b1 Leszek Koltunski
        {
264 5d50e7a7 Leszek Koltunski
        String commandNumber = row.substring(4,colon);
265
        int number;
266
267
        try
268
          {
269
          number = Integer.parseInt(commandNumber);
270
          }
271
        catch(NumberFormatException ex)
272
          {
273
          number=0;
274
          }
275 874c37b1 Leszek Koltunski
276 5d50e7a7 Leszek Koltunski
        if(number==1)
277 874c37b1 Leszek Koltunski
          {
278
          String country = row.substring(colon+1);
279
          RubikScores scores = RubikScores.getInstance();
280
          scores.setCountry(country);
281
          }
282
        }
283
      }
284 f3e12931 Leszek Koltunski
    }
285
286 36e2cbdd Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
287
288
  private String URLencode(String s)
289
    {
290
    StringBuilder sbuf = new StringBuilder();
291
    int len = s.length();
292
293
    for (int i = 0; i < len; i++)
294
      {
295
      int ch = s.charAt(i);
296
297
           if ('A' <= ch && ch <= 'Z') sbuf.append((char)ch);
298
      else if ('a' <= ch && ch <= 'z') sbuf.append((char)ch);
299
      else if ('0' <= ch && ch <= '9') sbuf.append((char)ch);
300
      else if (ch == ' '             ) sbuf.append('+');
301
      else if (ch == '-' || ch == '_'
302
            || ch == '.' || ch == '!'
303
            || ch == '~' || ch == '*'
304
            || ch == '\'' || ch == '('
305
            || ch == ')'             ) sbuf.append((char)ch);
306
      else if (ch <= 0x007f)           sbuf.append(hex[ch]);
307
      else if (ch <= 0x07FF)
308
        {
309
        sbuf.append(hex[0xc0 | (ch >> 6)]);
310
        sbuf.append(hex[0x80 | (ch & 0x3F)]);
311
        }
312
      else
313
        {
314
        sbuf.append(hex[0xe0 | (ch >> 12)]);
315
        sbuf.append(hex[0x80 | ((ch >> 6) & 0x3F)]);
316
        sbuf.append(hex[0x80 | (ch & 0x3F)]);
317
        }
318
      }
319
320
    return sbuf.toString();
321
    }
322
323 f3e12931 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
324
325 46be3ddf Leszek Koltunski
  private boolean network(String url, ScoresReceiver receiver)
326 f3e12931 Leszek Koltunski
    {
327 36e2cbdd Leszek Koltunski
    try
328
      {
329 4895fff6 Leszek Koltunski
      java.net.URL connectURL = new URL(url);
330 36e2cbdd Leszek Koltunski
      HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
331
332
      conn.setDoInput(true);
333
      conn.setDoOutput(true);
334
      conn.setUseCaches(false);
335
      conn.setRequestMethod("GET");
336
      conn.connect();
337
      conn.getOutputStream().flush();
338
339 1d643a0e Leszek Koltunski
      InputStream is = conn.getInputStream();
340
      BufferedReader r = new BufferedReader(new InputStreamReader(is));
341
      StringBuilder total = new StringBuilder();
342
343
      for (String line; (line = r.readLine()) != null; )
344 36e2cbdd Leszek Koltunski
        {
345 1d643a0e Leszek Koltunski
        total.append(line).append('\n');
346 36e2cbdd Leszek Koltunski
        }
347 1d643a0e Leszek Koltunski
348
      mScores = total.toString();
349 46be3ddf Leszek Koltunski
      conn.disconnect();
350 36e2cbdd Leszek Koltunski
      }
351 cc5ec229 Leszek Koltunski
    catch( final UnknownHostException e )
352
      {
353 46be3ddf Leszek Koltunski
      receiver.message("No access to Internet");
354 cc5ec229 Leszek Koltunski
      return false;
355
      }
356
    catch( final SecurityException e )
357
      {
358 46be3ddf Leszek Koltunski
      receiver.message("Application not authorized to connect to the Internet");
359 cc5ec229 Leszek Koltunski
      return false;
360
      }
361
    catch( final Exception e )
362 36e2cbdd Leszek Koltunski
      {
363 46be3ddf Leszek Koltunski
      receiver.message(e.getMessage());
364 a675474f Leszek Koltunski
      return false;
365 36e2cbdd Leszek Koltunski
      }
366
367 3a768e35 leszek
    if( mScores.isEmpty() )
368 329c0aeb Leszek Koltunski
      {
369 46be3ddf Leszek Koltunski
      receiver.message("Failed to download scores");
370 329c0aeb Leszek Koltunski
      return false;
371
      }
372
373 a675474f Leszek Koltunski
    return true;
374 b8b38548 Leszek Koltunski
    }
375 d8aa4ba8 Leszek Koltunski
376 1fa125c2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
377
378 46be3ddf Leszek Koltunski
  private String constructSuspiciousURL(String suspURL)
379 1fa125c2 Leszek Koltunski
    {
380
    RubikScores scores = RubikScores.getInstance();
381 a59f38d6 Leszek Koltunski
    int deviceID       = scores.getDeviceID();
382
    String suspicious  = URLencode(suspURL);
383 1fa125c2 Leszek Koltunski
384 a59f38d6 Leszek Koltunski
    return SERVER+"suspicious.cgi?i="+deviceID+"&d="+suspicious;
385
    }
386 1fa125c2 Leszek Koltunski
387 a59f38d6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
388
389
  private String constructTokenURL(String token)
390
    {
391
    RubikScores scores = RubikScores.getInstance();
392
    String name = URLencode(scores.getName());
393
    int deviceID= scores.getDeviceID();
394
    String country = scores.getCountry();
395
    String version = mVersion==null ? "null" : mVersion;
396
    String tkn = URLencode(token);
397
398
    return SERVER+"token.cgi?n="+name+"&i="+deviceID+"&e="+version+"&c="+country+"&t="+tkn;
399 1fa125c2 Leszek Koltunski
    }
400
401 6a083c6a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
402
403 1c04d054 leszek
  private String constructUpdatesURL()
404 6a083c6a Leszek Koltunski
    {
405 1c04d054 leszek
    RubikScores sco = RubikScores.getInstance();
406
    String name     = URLencode(sco.getName());
407
    int numRuns     = sco.getNumRuns();
408
    int numPlay     = sco.getNumPlays();
409
    String country  = sco.getCountry();
410 0effd5a9 leszek
    int objectAPI   = JsonWriter.VERSION_OBJECT_APP;
411
    int tutorialAPI = JsonWriter.VERSION_EXTRAS_APP;
412 6a083c6a Leszek Koltunski
413 1c04d054 leszek
    String url=SERVER+"updates.cgi";
414
    url += "?n="+name+"&r="+numRuns+"&p="+numPlay+"&c="+country+"&e="+mVersion+"d"+"&a="+objectAPI+"&b="+tutorialAPI;
415 6a083c6a Leszek Koltunski
416
    return url;
417
    }
418
419 17f9a695 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
420
421
  private String constructDownloadURL()
422
    {
423
    RubikScores scores = RubikScores.getInstance();
424
    String name = URLencode(scores.getName());
425
    int numRuns = scores.getNumRuns();
426
    int numPlay = scores.getNumPlays();
427 874c37b1 Leszek Koltunski
    String country = scores.getCountry();
428 17f9a695 Leszek Koltunski
429 a59f38d6 Leszek Koltunski
    return SERVER+"download.cgi?n="+name+"&r="+numRuns+"&p="+numPlay+"&c="+country+"&e="+mVersion;
430 17f9a695 Leszek Koltunski
    }
431
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433
434
  private String constructSubmitURL()
435
    {
436
    RubikScores scores = RubikScores.getInstance();
437
    String name = URLencode(scores.getName());
438 11d68e9c Leszek Koltunski
    String veri = scores.isVerified() ? "1" : "";
439 17f9a695 Leszek Koltunski
    int numRuns = scores.getNumRuns();
440
    int numPlay = scores.getNumPlays();
441
    int deviceID= scores.getDeviceID();
442 6570171b Leszek Koltunski
    String reclist = scores.getRecordList("&o=","&l=","&t=");
443 17f9a695 Leszek Koltunski
    String country = scores.getCountry();
444 86cbdab1 Leszek Koltunski
    long epoch = System.currentTimeMillis();
445 9fe350fe Leszek Koltunski
    String salt = "cuboid";
446 17f9a695 Leszek Koltunski
447 1a7efafd leszek
    String url1 = SERVER+"submit.cgi";
448 11d68e9c Leszek Koltunski
    String url2 = "n="+name+"&v="+veri+"&r="+numRuns+"&p="+numPlay+"&i="+deviceID+"&e="+mVersion;
449 1c04d054 leszek
    url2 += reclist+"&c="+country+"&f="+epoch;
450 9fe350fe Leszek Koltunski
    String hash = computeHash( url2, salt.getBytes() );
451 17f9a695 Leszek Koltunski
452 b3ee0e78 Leszek Koltunski
    return url1 + "?" + url2 + "&h=" + hash;
453 17f9a695 Leszek Koltunski
    }
454
455 d8aa4ba8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
456
457 e4854e54 Leszek Koltunski
  private void figureOutVersion(Activity act)
458 d8aa4ba8 Leszek Koltunski
    {
459 e4854e54 Leszek Koltunski
    if( mVersion==null )
460 ffe7e55d Leszek Koltunski
      {
461 e4854e54 Leszek Koltunski
      try
462
        {
463
        PackageInfo pInfo = act.getPackageManager().getPackageInfo( act.getPackageName(), 0);
464
        mVersion = pInfo.versionName;
465
        }
466
      catch (PackageManager.NameNotFoundException e)
467
        {
468
        mVersion = "0.9.2";
469
        }
470 ffe7e55d Leszek Koltunski
      }
471
    }
472 a675474f Leszek Koltunski
473 ffe7e55d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
474 a36b9dca Leszek Koltunski
475 46be3ddf Leszek Koltunski
  private void downloadThread(ScoresReceiver receiver)
476 ffe7e55d Leszek Koltunski
    {
477 b6606976 leszek
    boolean receiveValues = true;
478 aa550481 Leszek Koltunski
479 17f9a695 Leszek Koltunski
    try
480 d8aa4ba8 Leszek Koltunski
      {
481 b6606976 leszek
      if( mScores.isEmpty() && !mDowRunning )
482 4895fff6 Leszek Koltunski
        {
483 b6606976 leszek
        mDowRunning = true;
484 aa550481 Leszek Koltunski
        receiveValues = network(constructDownloadURL(),receiver);
485 4895fff6 Leszek Koltunski
486 b6606976 leszek
        if( mDowRunning )
487 17f9a695 Leszek Koltunski
          {
488 46be3ddf Leszek Koltunski
          receiveValues = fillValuesNormal(receiver);
489 b6606976 leszek
          mDowRunning = false;
490 17f9a695 Leszek Koltunski
          }
491 1fa125c2 Leszek Koltunski
        }
492 aa550481 Leszek Koltunski
      if( receiveValues ) receiver.receive(mCountry, mName, mTime);
493 d8aa4ba8 Leszek Koltunski
      }
494 17f9a695 Leszek Koltunski
    catch( Exception e )
495 d8aa4ba8 Leszek Koltunski
      {
496 46be3ddf Leszek Koltunski
      receiver.message("Exception downloading records: "+e.getMessage() );
497 4895fff6 Leszek Koltunski
      }
498 ffe7e55d Leszek Koltunski
    }
499
500
///////////////////////////////////////////////////////////////////////////////////////////////////
501 286d73ae Leszek Koltunski
502 46be3ddf Leszek Koltunski
  private void submitThread(ScoresReceiver receiver)
503 ffe7e55d Leszek Koltunski
    {
504
    try
505
      {
506
      RubikScores scores = RubikScores.getInstance();
507
508 b6606976 leszek
      if( scores.thereAreUnsubmittedRecords() && !mSubRunning )
509 ffe7e55d Leszek Koltunski
        {
510 b6606976 leszek
        mSubRunning = true;
511 46be3ddf Leszek Koltunski
        boolean receiveValues = network(constructSubmitURL(),receiver);
512 ffe7e55d Leszek Koltunski
513 b6606976 leszek
        if( mSubRunning )
514 ffe7e55d Leszek Koltunski
          {
515 46be3ddf Leszek Koltunski
          receiveValues = fillValuesNormal(receiver);
516 b6606976 leszek
          mSubRunning = false;
517 ffe7e55d Leszek Koltunski
          }
518
519
        if( receiveValues )
520
          {
521
          RubikScores.getInstance().successfulSubmit();
522 46be3ddf Leszek Koltunski
          receiver.receive(mCountry, mName, mTime);
523 ffe7e55d Leszek Koltunski
          }
524
        }
525
      }
526
    catch( Exception e )
527 17f9a695 Leszek Koltunski
      {
528 46be3ddf Leszek Koltunski
      receiver.message("Exception submitting records: "+e.getMessage() );
529 17f9a695 Leszek Koltunski
      }
530 ffe7e55d Leszek Koltunski
    }
531 a675474f Leszek Koltunski
532 ffe7e55d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
533
534 1c04d054 leszek
  private void updatesThread()
535 ffe7e55d Leszek Koltunski
    {
536 1c04d054 leszek
    String url = constructUpdatesURL();
537 109a2b68 Leszek Koltunski
538 ffe7e55d Leszek Koltunski
    try
539 a675474f Leszek Koltunski
      {
540 ffe7e55d Leszek Koltunski
      java.net.URL connectURL = new URL(url);
541
      HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
542 17f9a695 Leszek Koltunski
543 ffe7e55d Leszek Koltunski
      conn.setDoInput(true);
544
      conn.setDoOutput(true);
545
      conn.setUseCaches(false);
546
      conn.setRequestMethod("GET");
547
      conn.connect();
548
      conn.getOutputStream().flush();
549
550
      InputStream is = conn.getInputStream();
551
      BufferedReader r = new BufferedReader(new InputStreamReader(is));
552
      StringBuilder answer = new StringBuilder();
553
554 1c04d054 leszek
      for( String line; (line = r.readLine()) != null; )
555 17f9a695 Leszek Koltunski
        {
556 ffe7e55d Leszek Koltunski
        answer.append(line).append('\n');
557 17f9a695 Leszek Koltunski
        }
558 ffe7e55d Leszek Koltunski
559
      String updates = answer.toString();
560 46be3ddf Leszek Koltunski
      conn.disconnect();
561 ffe7e55d Leszek Koltunski
      mUpdates.parse(updates);
562
563 1c04d054 leszek
      if( mUpdateeList!=null )
564
        {
565
        int numUpdatees = mUpdateeList.size();
566
567
        for(int u=0; u<numUpdatees; u++)
568
          {
569
          Updatee upd = mUpdateeList.get(u);
570
          upd.receiveUpdate(mUpdates);
571
          }
572
        }
573
574
      mUpdatesState = UPDATES_SUCCESS;
575 ffe7e55d Leszek Koltunski
      }
576
    catch( final Exception e )
577
      {
578 1c04d054 leszek
      if( mUpdateeList!=null )
579
        {
580
        int numUpdatees = mUpdateeList.size();
581
582
        for(int u=0; u<numUpdatees; u++)
583
          {
584
          Updatee upd = mUpdateeList.get(u);
585
          upd.errorUpdate();
586
          }
587
        }
588
589
      mUpdatesState = UPDATES_FAILURE;
590 ffe7e55d Leszek Koltunski
      }
591
    }
592
593
///////////////////////////////////////////////////////////////////////////////////////////////////
594
595 46be3ddf Leszek Koltunski
  private void suspiciousThread(String suspURL)
596 ffe7e55d Leszek Koltunski
    {
597 46be3ddf Leszek Koltunski
    String url = constructSuspiciousURL(suspURL);
598 ffe7e55d Leszek Koltunski
599
    try
600
      {
601
      java.net.URL connectURL = new URL(url);
602
      HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
603
604
      conn.setDoInput(true);
605
      conn.setDoOutput(true);
606
      conn.setUseCaches(false);
607
      conn.setRequestMethod("GET");
608
      conn.connect();
609
      conn.getOutputStream().flush();
610
      conn.getInputStream();
611 46be3ddf Leszek Koltunski
      conn.disconnect();
612 ffe7e55d Leszek Koltunski
      }
613
    catch( final Exception e )
614
      {
615
      // ignore
616 a675474f Leszek Koltunski
      }
617 d8aa4ba8 Leszek Koltunski
    }
618 4f9f99a2 Leszek Koltunski
619 a59f38d6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
620
621
  private void tokenThread(String token)
622
    {
623
    String url = constructTokenURL(token);
624
625
    try
626
      {
627
      java.net.URL connectURL = new URL(url);
628
      HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
629
630
      conn.setDoInput(true);
631
      conn.setDoOutput(true);
632
      conn.setUseCaches(false);
633
      conn.setRequestMethod("GET");
634
      conn.connect();
635
      conn.getOutputStream().flush();
636
      conn.getInputStream();
637
      conn.disconnect();
638
      }
639
    catch( final Exception e )
640
      {
641
      // ignore
642
      }
643
    }
644
645 b88cdd91 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
646
647
  private Bitmap downloadIcon(String url)
648
    {
649
    try
650
      {
651
      java.net.URL connectURL = new URL(url);
652
      HttpURLConnection conn = (HttpURLConnection) connectURL.openConnection();
653
      conn.setDoInput(true);
654
      conn.connect();
655
      InputStream input = conn.getInputStream();
656 46be3ddf Leszek Koltunski
      Bitmap icon = BitmapFactory.decodeStream(input);
657
      conn.disconnect();
658
      return icon;
659 b88cdd91 Leszek Koltunski
      }
660
    catch (IOException e)
661
      {
662
      android.util.Log.e("D", "Failed to download "+url);
663
      android.util.Log.e("D", e.getMessage() );
664
      return null;
665
      }
666
    }
667
668
///////////////////////////////////////////////////////////////////////////////////////////////////
669
670 7fe62d1f Leszek Koltunski
  private void iconThread(Context context, IconReceiver receiver)
671 b88cdd91 Leszek Koltunski
    {
672
    int numC = mUpdates.getCompletedNumber();
673
    int numS = mUpdates.getStartedNumber();
674
675
    for(int c=0; c<numC; c++)
676
      {
677 b92ad5cd Leszek Koltunski
      int iconPresent = mUpdates.getCompletedIconPresent(c);
678 b88cdd91 Leszek Koltunski
679 b92ad5cd Leszek Koltunski
      if( iconPresent!=0 )
680 b88cdd91 Leszek Koltunski
        {
681 7fe62d1f Leszek Koltunski
        boolean downloaded = false;
682
        Bitmap icon = mUpdates.getCompletedIcon(context,c);
683 b92ad5cd Leszek Koltunski
684
        if( icon==null )
685
          {
686
          String url = mUpdates.getCompletedURL(c);
687
          icon = downloadIcon(url);
688 7fe62d1f Leszek Koltunski
          downloaded = true;
689 84d746d7 Leszek Koltunski
690 e847c553 Leszek Koltunski
          if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Downloading icon "+url);
691 b92ad5cd Leszek Koltunski
          }
692
        if( icon!=null )
693
          {
694
          mUpdates.setCompletedIcon(c,icon);
695 7fe62d1f Leszek Koltunski
          receiver.iconDownloaded(c,icon,downloaded);
696 b92ad5cd Leszek Koltunski
          }
697 b88cdd91 Leszek Koltunski
        }
698
      }
699
700
    for(int s=0; s<numS; s++)
701
      {
702 b92ad5cd Leszek Koltunski
      int iconPresent = mUpdates.getStartedIconPresent(s);
703 b88cdd91 Leszek Koltunski
704 b92ad5cd Leszek Koltunski
      if( iconPresent!=0 )
705 b88cdd91 Leszek Koltunski
        {
706 7fe62d1f Leszek Koltunski
        boolean downloaded = false;
707
        Bitmap icon = mUpdates.getStartedIcon(context,s);
708 b92ad5cd Leszek Koltunski
709
        if( icon==null )
710
          {
711
          String url = mUpdates.getStartedURL(s);
712
          icon = downloadIcon(url);
713 7fe62d1f Leszek Koltunski
          downloaded = true;
714 84d746d7 Leszek Koltunski
715 e847c553 Leszek Koltunski
          if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Downloading icon "+url);
716 b92ad5cd Leszek Koltunski
          }
717
        if( icon!=null )
718
          {
719
          mUpdates.setStartedIcon(s,icon);
720 7fe62d1f Leszek Koltunski
          receiver.iconDownloaded(numC+s,icon,downloaded);
721 b92ad5cd Leszek Koltunski
          }
722 b88cdd91 Leszek Koltunski
        }
723
      }
724
    }
725
726 46be3ddf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
727
728
  private InputStream downloadJSON(String name)
729
    {
730
    String url = mUpdates.getURL() + name;
731
732
    try
733
      {
734 e847c553 Leszek Koltunski
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Downloading JSON "+url);
735 84d746d7 Leszek Koltunski
736 46be3ddf Leszek Koltunski
      java.net.URL connectURL = new URL(url);
737
      HttpURLConnection conn = (HttpURLConnection) connectURL.openConnection();
738
      conn.setDoInput(true);
739
      conn.connect();
740 806329e3 Leszek Koltunski
      return conn.getInputStream();
741 46be3ddf Leszek Koltunski
      }
742
    catch (IOException e)
743
      {
744
      android.util.Log.e("D", "Failed to download "+url);
745
      android.util.Log.e("D", e.getMessage() );
746
      return null;
747
      }
748
    }
749
750
///////////////////////////////////////////////////////////////////////////////////////////////////
751
752
  private void jsonThread(final RubikUpdates.UpdateInfo info, Downloadee downloadee)
753
    {
754
    if(info.mUpdateObject) info.mObjectStream = downloadJSON(info.mObjectShortName+"_object.json");
755
    if(info.mUpdateExtras) info.mExtrasStream = downloadJSON(info.mObjectShortName+"_extras.json");
756
757
    downloadee.jsonDownloaded();
758 806329e3 Leszek Koltunski
759
    try
760
      {
761
      if( info.mObjectStream!=null ) info.mObjectStream.close();
762
      }
763
    catch(IOException ioe)
764
      {
765
      android.util.Log.e("D", "failed to close object input stream");
766
      }
767
768
    try
769
      {
770
      if( info.mExtrasStream!=null ) info.mExtrasStream.close();
771
      }
772
    catch(IOException ioe)
773
      {
774
      android.util.Log.e("D", "failed to close extras input stream");
775
      }
776 46be3ddf Leszek Koltunski
    }
777
778 bc511ea5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
779
780 6a083c6a Leszek Koltunski
  private RubikNetwork()
781 bc511ea5 Leszek Koltunski
    {
782
783
    }
784
785 4f9f99a2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
786
// PUBLIC API
787
///////////////////////////////////////////////////////////////////////////////////////////////////
788
789
  public static void onPause()
790
    {
791 b6606976 leszek
    mDowRunning = false;
792
    mSubRunning = false;
793
794 1c04d054 leszek
    mUpdateeList.clear();
795 4f9f99a2 Leszek Koltunski
    }
796
797 bc511ea5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
798
799 6a083c6a Leszek Koltunski
  public static RubikNetwork getInstance()
800 bc511ea5 Leszek Koltunski
    {
801 35161021 Leszek Koltunski
    if( mThis==null ) mThis = new RubikNetwork();
802 bc511ea5 Leszek Koltunski
    return mThis;
803
    }
804
805 4f9f99a2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
806
807 e4854e54 Leszek Koltunski
  public void download(final ScoresReceiver receiver, final Activity act)
808 4f9f99a2 Leszek Koltunski
    {
809 ffe7e55d Leszek Koltunski
    initializeStatics();
810
    figureOutVersion(act);
811 1780dcb0 Leszek Koltunski
812 ffe7e55d Leszek Koltunski
    Thread thread = new Thread()
813 1780dcb0 Leszek Koltunski
      {
814 ffe7e55d Leszek Koltunski
      public void run()
815
        {
816 46be3ddf Leszek Koltunski
        downloadThread(receiver);
817 ffe7e55d Leszek Koltunski
        }
818
      };
819 6f8e5dfc Leszek Koltunski
820 ffe7e55d Leszek Koltunski
    thread.start();
821 4f9f99a2 Leszek Koltunski
    }
822 bc511ea5 Leszek Koltunski
823
///////////////////////////////////////////////////////////////////////////////////////////////////
824
825 e4854e54 Leszek Koltunski
  public void submit(ScoresReceiver receiver, final Activity act)
826 bc511ea5 Leszek Koltunski
    {
827 ffe7e55d Leszek Koltunski
    initializeStatics();
828
    figureOutVersion(act);
829 bc511ea5 Leszek Koltunski
830 ffe7e55d Leszek Koltunski
    Thread thread = new Thread()
831
      {
832
      public void run()
833
        {
834 46be3ddf Leszek Koltunski
        submitThread(receiver);
835 ffe7e55d Leszek Koltunski
        }
836
      };
837 1780dcb0 Leszek Koltunski
838 ffe7e55d Leszek Koltunski
    thread.start();
839 bc511ea5 Leszek Koltunski
    }
840 6a083c6a Leszek Koltunski
841
///////////////////////////////////////////////////////////////////////////////////////////////////
842
843 1c04d054 leszek
  public void downloadUpdates(final Activity act)
844 6a083c6a Leszek Koltunski
    {
845 ffe7e55d Leszek Koltunski
    initializeStatics();
846 e4854e54 Leszek Koltunski
    figureOutVersion(act);
847 1c04d054 leszek
    mUpdatesState = UPDATES_RUNNING;
848 ffe7e55d Leszek Koltunski
849
    Thread thread = new Thread()
850
      {
851
      public void run()
852
        {
853 1c04d054 leszek
        updatesThread();
854 ffe7e55d Leszek Koltunski
        }
855
      };
856
857
    thread.start();
858 6a083c6a Leszek Koltunski
    }
859 1fa125c2 Leszek Koltunski
860
///////////////////////////////////////////////////////////////////////////////////////////////////
861
862 e4854e54 Leszek Koltunski
  public void suspicious(final String suspicious, final Activity act)
863 1fa125c2 Leszek Koltunski
    {
864 ffe7e55d Leszek Koltunski
    initializeStatics();
865 e4854e54 Leszek Koltunski
    figureOutVersion(act);
866 ffe7e55d Leszek Koltunski
867
    Thread thread = new Thread()
868
      {
869
      public void run()
870
        {
871 46be3ddf Leszek Koltunski
        suspiciousThread(suspicious);
872 ffe7e55d Leszek Koltunski
        }
873
      };
874
875
    thread.start();
876 1fa125c2 Leszek Koltunski
    }
877 63dd19c4 Leszek Koltunski
878 a59f38d6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
879
880
  public void token(final String token)
881
    {
882
    initializeStatics();
883
884
    Thread thread = new Thread()
885
      {
886
      public void run()
887
        {
888
        tokenThread(token);
889
        }
890
      };
891
892
    thread.start();
893
    }
894
895 63dd19c4 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
896
897
  public void signUpForUpdates(Updatee updatee)
898
    {
899 1c04d054 leszek
    if( mUpdateeList==null ) mUpdateeList = new ArrayList<>();
900
901
    int numUpdatees = mUpdateeList.size();
902
    int type = updatee.getType();
903
904
    for(int u=0; u<numUpdatees; u++)
905
      {
906
      Updatee upd = mUpdateeList.get(u);
907
908
      if( upd.getType()==type )
909
        {
910
        mUpdateeList.remove(u);
911
        break;
912
        }
913
      }
914
915
    mUpdateeList.add(updatee);
916
917
    if( mUpdatesState==UPDATES_SUCCESS )
918
      {
919
      updatee.receiveUpdate(mUpdates);
920
      }
921
    else if( mUpdatesState==UPDATES_FAILURE )
922
      {
923
      updatee.errorUpdate();
924
      }
925 63dd19c4 Leszek Koltunski
    }
926 903c7bbc Leszek Koltunski
927 ffe7e55d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
928
929 7fe62d1f Leszek Koltunski
  public void downloadIcons(final Context context, final IconReceiver receiver)
930 46be3ddf Leszek Koltunski
    {
931
    initializeStatics();
932
933
    Thread thread = new Thread()
934
      {
935
      public void run()
936
        {
937 7fe62d1f Leszek Koltunski
        iconThread(context,receiver);
938 46be3ddf Leszek Koltunski
        }
939
      };
940
941
    thread.start();
942
    }
943
944
///////////////////////////////////////////////////////////////////////////////////////////////////
945
946
  public void downloadJSON(final RubikUpdates.UpdateInfo info, final Downloadee downloadee)
947 ffe7e55d Leszek Koltunski
    {
948 b88cdd91 Leszek Koltunski
    initializeStatics();
949
950
    Thread thread = new Thread()
951
      {
952
      public void run()
953
        {
954 46be3ddf Leszek Koltunski
        jsonThread(info,downloadee);
955 b88cdd91 Leszek Koltunski
        }
956
      };
957 ffe7e55d Leszek Koltunski
958 b88cdd91 Leszek Koltunski
    thread.start();
959 ffe7e55d Leszek Koltunski
    }
960
961 903c7bbc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
962
963
  public void updateDone(String shortName)
964
    {
965
    mUpdates.updateDone(shortName);
966 dcc8b2f9 Leszek Koltunski
    mScores = "";
967 1c04d054 leszek
968
    if( mUpdateeList!=null )
969
      {
970
      int numUpdatees = mUpdateeList.size();
971
972
      for(int u=0; u<numUpdatees; u++)
973
        {
974
        Updatee upd = mUpdateeList.get(u);
975
        upd.objectDownloaded(shortName);
976
        }
977
      }
978 903c7bbc Leszek Koltunski
    }
979 b8b38548 Leszek Koltunski
}