1 |
/**
|
2 |
* aagtl Advanced Geocaching Tool for Android
|
3 |
* loosely based on agtl by Daniel Fett <fett@danielfett.de>
|
4 |
* Copyright (C) 2010 - 2012 Zoff.cc <aagtl@work.zoff.cc>
|
5 |
*
|
6 |
* This program is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU General Public License
|
8 |
* version 2 as published by the Free Software Foundation.
|
9 |
*
|
10 |
* This program is distributed in the hope that it will be useful,
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
* GNU General Public License for more details.
|
14 |
*
|
15 |
* You should have received a copy of the GNU General Public License
|
16 |
* along with this program; if not, write to the
|
17 |
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
18 |
* Boston, MA 02110-1301, USA.
|
19 |
*/
|
20 |
|
21 |
package com.zoffcc.applications.aagtl;
|
22 |
|
23 |
import java.util.regex.Matcher;
|
24 |
import java.util.regex.Pattern;
|
25 |
|
26 |
import net.htmlparser.jericho.Source;
|
27 |
import android.os.Bundle;
|
28 |
import android.os.Message;
|
29 |
import android.widget.Toast;
|
30 |
|
31 |
public class CacheDownloader
|
32 |
{
|
33 |
aagtl main_aagtl;
|
34 |
GeocacheCoordinate current_cache = null;
|
35 |
HTMLDownloader downloader = null;
|
36 |
|
37 |
// to debug page parsing
|
38 |
// to debug page parsing
|
39 |
static final Boolean DEBUG_ = false;
|
40 |
static final Boolean DEBUG2_ = false;
|
41 |
|
42 |
// to debug page parsing
|
43 |
// to debug page parsing
|
44 |
|
45 |
public CacheDownloader(aagtl main_aagtl, HTMLDownloader dol)
|
46 |
{
|
47 |
this.main_aagtl = main_aagtl;
|
48 |
this.downloader = dol;
|
49 |
}
|
50 |
|
51 |
public GeocacheCoordinate update_coordinate(GeocacheCoordinate coordinate)
|
52 |
{
|
53 |
GeocacheCoordinate gc_ret = coordinate;
|
54 |
current_cache = gc_ret;
|
55 |
|
56 |
// download from internet
|
57 |
String data = this.__get_cache_page(coordinate.name);
|
58 |
|
59 |
if (data == null)
|
60 |
{
|
61 |
// we got "null" return value!!
|
62 |
return null;
|
63 |
}
|
64 |
|
65 |
// System.out.println(data);
|
66 |
|
67 |
// split output into lines
|
68 |
String[] response_lines = data.split("\n");
|
69 |
// parse the HTML lines
|
70 |
GeocacheCoordinate temp_gc = this.__parse_cache_page(response_lines, coordinate);
|
71 |
|
72 |
if (temp_gc != null)
|
73 |
{
|
74 |
// write full data to DB
|
75 |
this.main_aagtl.pv.begin_trans();
|
76 |
try
|
77 |
{
|
78 |
this.main_aagtl.pv.add_point_full(gc_ret);
|
79 |
this.main_aagtl.pv.commit();
|
80 |
}
|
81 |
finally
|
82 |
{
|
83 |
this.main_aagtl.pv.end_trans();
|
84 |
}
|
85 |
}
|
86 |
else
|
87 |
{
|
88 |
// we got "null" return value!!
|
89 |
return null;
|
90 |
}
|
91 |
|
92 |
return gc_ret;
|
93 |
}
|
94 |
|
95 |
public String __get_cache_page(String cacheid)
|
96 |
{
|
97 |
return this.downloader.getUrlData(String.format("http://www.geocaching.com/seek/cache_details.aspx?wp=%s", cacheid));
|
98 |
}
|
99 |
|
100 |
public static GeocacheCoordinate __parse_cache_page_print(String cache_page, GeocacheCoordinate coordinate)
|
101 |
{
|
102 |
try
|
103 |
{
|
104 |
Source source = new Source(cache_page);
|
105 |
String title = source.getFirstElement("id", "pageTitle", false).getTextExtractor().toString();
|
106 |
title = title.replace("(" + coordinate.name + ") ", "");
|
107 |
//System.out.println("title=" + title);
|
108 |
coordinate.title = title;
|
109 |
//
|
110 |
String lat_lon = source.getFirstElement("class", "LatLong Meta", false).getTextExtractor().toString();
|
111 |
//System.out.println("lat_lon=" + lat_lon);
|
112 |
Coordinate c_ = Coordinate.parse_coord_string(lat_lon);
|
113 |
if (c_ == null)
|
114 |
{
|
115 |
return null;
|
116 |
}
|
117 |
else
|
118 |
{
|
119 |
coordinate.lat = c_.lat;
|
120 |
coordinate.lon = c_.lon;
|
121 |
// System.out.println("lat=" + c_.lat + " lon=" + c_.lon);
|
122 |
}
|
123 |
|
124 |
String type = source.getFirstElement("id", "Content", false).getFirstElement("h2").getFirstElement("img").getAttributeValue("src").toString();
|
125 |
coordinate.type = GeocacheCoordinate.GC_TYPE_HASH.get(type.split("/")[3].split("\\.")[0]);
|
126 |
//System.out.println("type=" + coordinate.type);
|
127 |
|
128 |
}
|
129 |
catch (Exception e)
|
130 |
{
|
131 |
e.printStackTrace();
|
132 |
return null;
|
133 |
}
|
134 |
return coordinate;
|
135 |
}
|
136 |
|
137 |
public GeocacheCoordinate __parse_cache_page(String[] cache_page, GeocacheCoordinate coordinate)
|
138 |
{
|
139 |
String section = "";
|
140 |
String section2 = "";
|
141 |
String section_old = "XXXXXX";
|
142 |
String shortdesc = "";
|
143 |
String desc = "";
|
144 |
String hints = "";
|
145 |
String waypoints = "";
|
146 |
String images = "";
|
147 |
String logs = "";
|
148 |
String head = "";
|
149 |
Boolean found = false;
|
150 |
|
151 |
String line = "";
|
152 |
if (DEBUG_) System.out.println("lines=" + cache_page.length);
|
153 |
for (int i = 0; i < cache_page.length; i++)
|
154 |
{
|
155 |
line = cache_page[i];
|
156 |
// remove spaces at start and end of string
|
157 |
line = line.trim();
|
158 |
// line = line.replace("\r", "");
|
159 |
// line = line.replace("\n", "");
|
160 |
|
161 |
// if (DEBUG_) System.out.println("line=" + line);
|
162 |
|
163 |
if (section.compareTo(section_old) != 0)
|
164 |
{
|
165 |
if (DEBUG_) System.out.println("##sec##=" + section);
|
166 |
section_old = section;
|
167 |
}
|
168 |
|
169 |
if ((section.equals("")) && (line.startsWith("<div class=\"span-17 last")))
|
170 |
{
|
171 |
section = "head";
|
172 |
}
|
173 |
else if ((section.equals("head")) && (line.startsWith("<span id=\"ctl00_ContentBody_ShortDescription\">")))
|
174 |
{
|
175 |
section = "shortdesc";
|
176 |
}
|
177 |
else if (((section.equals("head")) || (section.equals("shortdesc"))) && (line.startsWith("<span id=\"ctl00_ContentBody_LongDescription\">")))
|
178 |
{
|
179 |
section = "desc";
|
180 |
|
181 |
}
|
182 |
else if (((section.equals("desc")) || (section.equals("shortdesc"))) && (line.startsWith("Additional Hints")))
|
183 |
{
|
184 |
section = "after-desc";
|
185 |
}
|
186 |
else if ((section.equals("after-desc")) && (line.contains("<div id=\"div_hint\"")))
|
187 |
{
|
188 |
section = "hints";
|
189 |
}
|
190 |
else if (line.startsWith("<div id=\"ctl00_ContentBody_uxStatusInformation\""))
|
191 |
{
|
192 |
section2 = "status-found-1";
|
193 |
}
|
194 |
else if ((section2.equals("status-found-1")) && (line.contains("id=\"ctl00_ContentBody_hlFoundItLog\"")))
|
195 |
{
|
196 |
section2 = "status-found-2";
|
197 |
// we have found this cache already
|
198 |
if (DEBUG_) System.out.println("-- found it --");
|
199 |
found = true;
|
200 |
section2 = "";
|
201 |
}
|
202 |
else if ((section.equals("hints")) && (line.startsWith("<div id='dk'")))
|
203 |
{
|
204 |
section = "after-hints";
|
205 |
}
|
206 |
else if (((section.equals("after-hints")) || (section.equals("after-desc"))) && (line.startsWith("<div class=\"CacheDetailNavigationWidget\">")))
|
207 |
{
|
208 |
section = "pre-waypoints";
|
209 |
|
210 |
}
|
211 |
else if (((section.equals("after-hints")) || (section.equals("pre-waypoints"))) && (line.startsWith("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">")))
|
212 |
{
|
213 |
section = "waypoints";
|
214 |
|
215 |
}
|
216 |
else if ((section.equals("waypoints")) && (line.contains("</tbody> </table>")))
|
217 |
{
|
218 |
section = "after-waypoints";
|
219 |
|
220 |
}
|
221 |
else if (((section.equals("pre-waypoints")) || (section.equals("after-waypoints"))) && (line.startsWith("<span id=\"ctl00_ContentBody_Images\">")))
|
222 |
{
|
223 |
section = "images";
|
224 |
|
225 |
}
|
226 |
else if (((section.equals("images")) || (section.equals("after-waypoints")) || (section.equals("pre-waypoints"))) && (line.contains("initalLogs = {")))
|
227 |
{
|
228 |
section = "logs";
|
229 |
logs = line;
|
230 |
if (DEBUG_) System.out.println("logline=" + logs);
|
231 |
}
|
232 |
|
233 |
if (section.equals("logs"))
|
234 |
{
|
235 |
// finish
|
236 |
// the
|
237 |
// for-loop
|
238 |
//
|
239 |
break;
|
240 |
}
|
241 |
|
242 |
if (section.equals("head"))
|
243 |
{
|
244 |
head = String.format("%s%s\n", head, line);
|
245 |
}
|
246 |
else if (section.equals("shortdesc"))
|
247 |
{
|
248 |
shortdesc = String.format("%s%s\n", shortdesc, line);
|
249 |
}
|
250 |
else if (section.equals("desc"))
|
251 |
{
|
252 |
desc = String.format("%s%s\n", desc, line);
|
253 |
}
|
254 |
else if (section.equals("hints"))
|
255 |
{
|
256 |
hints = String.format("%s%s\n", hints, line);
|
257 |
}
|
258 |
else if (section.equals("waypoints"))
|
259 |
{
|
260 |
waypoints = String.format("%s%s\n", waypoints, line);
|
261 |
}
|
262 |
else if (section.equals("images"))
|
263 |
{
|
264 |
images = String.format("%s%s\n", images, line);
|
265 |
}
|
266 |
//else if (section.equals("logs"))
|
267 |
//{
|
268 |
// logs = logs + line;
|
269 |
//}
|
270 |
}
|
271 |
|
272 |
String[] temp_str = new String[7];
|
273 |
temp_str = this.__parse_head(head);
|
274 |
coordinate.size = Integer.parseInt(temp_str[0]);
|
275 |
coordinate.difficulty = Integer.parseInt(temp_str[1]);
|
276 |
coordinate.terrain = Integer.parseInt(temp_str[2]);
|
277 |
coordinate.owner = temp_str[3];
|
278 |
coordinate.lat = Double.parseDouble(temp_str[4]);
|
279 |
coordinate.lon = Double.parseDouble(temp_str[5]);
|
280 |
coordinate.type = temp_str[6];
|
281 |
coordinate.shortdesc = shortdesc;
|
282 |
coordinate.desc = desc;
|
283 |
coordinate.hints = this.__treat_hints(hints);
|
284 |
coordinate.logs = this.__treat_logs(logs);
|
285 |
coordinate.guid = this.__get_guid(head);
|
286 |
coordinate.found = found;
|
287 |
coordinate.waypoints = this.__treat_waypoints(waypoints);
|
288 |
|
289 |
// seems we got bogus data!! -> return "null"
|
290 |
if ((coordinate.guid == null) && (coordinate.owner.compareTo("dummy") == 0) && (coordinate.lat == 0.0))
|
291 |
{
|
292 |
return null;
|
293 |
}
|
294 |
|
295 |
// coordinate.shortdesc = self.__treat_shortdesc(shortdesc)
|
296 |
// coordinate.desc = self.__treat_desc(desc)
|
297 |
// coordinate.hints = self.__treat_hints(hints)
|
298 |
// coordinate.set_waypoints(self.__treat_waypoints(waypoints))
|
299 |
// coordinate.set_logs(self.__treat_logs(logs))
|
300 |
// self.__treat_images(images)
|
301 |
// coordinate.set_images(self.images)
|
302 |
|
303 |
return coordinate;
|
304 |
}
|
305 |
|
306 |
public String _strip_html(String input)
|
307 |
{
|
308 |
// **old** return input.replaceAll("\\<[^>]*>", "");
|
309 |
return HtmlToText.htmlToPlainText(input);
|
310 |
}
|
311 |
|
312 |
public String __treat_waypoints(String input)
|
313 |
{
|
314 |
String ret = input;
|
315 |
if (DEBUG_) System.out.println("way1=" + ret);
|
316 |
ret = ret.replaceAll("<tr>", "<br><tr>");
|
317 |
ret = ret.replaceAll("<tr ", "<br><tr ");
|
318 |
ret = HtmlToText.htmlToPlainText(ret);
|
319 |
ret = ret.replaceAll("\n", "<br><br>");
|
320 |
if (DEBUG_) System.out.println("way2=" + ret);
|
321 |
|
322 |
// // OLD
|
323 |
// ret = ret.replaceAll("<td>", "\t");
|
324 |
// ret = ret.replaceAll("<tr>", "#~RETURN#~");
|
325 |
// // remove all other HTML tags
|
326 |
// ret = ret.replaceAll("<[^>]*>", "");
|
327 |
// // make lots of spaces to only 1 space
|
328 |
// ret = ret.replaceAll("[ \t]+", " ");
|
329 |
// ret = ret.replaceAll("#~RETURN#~", "<br>");
|
330 |
// // OLD
|
331 |
return ret;
|
332 |
}
|
333 |
|
334 |
public String __treat_hints(String input)
|
335 |
{
|
336 |
String ret = input;
|
337 |
ret = this._strip_html(ret);
|
338 |
ret = ret + "\n<br>\n<br>" + this.convert_rot13(ret);
|
339 |
return ret;
|
340 |
}
|
341 |
|
342 |
public String __treat_logs(String input)
|
343 |
{
|
344 |
String ret = input;
|
345 |
// <img src="http://www.geocaching.com/images/icons/icon_smile.gif"
|
346 |
// alt="Found it" title="Found it" />
|
347 |
// <img src="http://www.geocaching.com/images/icons/icon_sad.gif"
|
348 |
// alt="Didn't find it" title="Didn't find it" />
|
349 |
|
350 |
// replace found,not found images
|
351 |
ret = input.replaceAll("<img src=\"[^>]*icon_smile.gif[^>]*>", "\n<br><br>* FOUND *\n\n<br><br>");
|
352 |
ret = ret.replaceAll("<img src=\"[^>]*icon_sad.gif[^>]*>", "\n<br><br># NOT FOUND #\n\n<br><br>");
|
353 |
|
354 |
// if (DEBUG_) System.out.println("log1=" + ret);
|
355 |
ret = HtmlToText.htmlToPlainText(ret);
|
356 |
ret = ret.replaceAll("\n", "<br>");
|
357 |
// if (DEBUG_) System.out.println("log2=" + ret);
|
358 |
return ret;
|
359 |
}
|
360 |
|
361 |
public String convert_rot13(String in)
|
362 |
{
|
363 |
StringBuffer tempReturn = new StringBuffer();
|
364 |
int abyte = 0;
|
365 |
|
366 |
for (int i = 0; i < in.length(); i++)
|
367 |
{
|
368 |
abyte = in.charAt(i);
|
369 |
int cap = abyte & 32;
|
370 |
abyte &= ~cap;
|
371 |
abyte = ((abyte >= 'A') && (abyte <= 'Z') ? ((abyte - 'A' + 13) % 26 + 'A') : abyte) | cap;
|
372 |
tempReturn.append((char) abyte);
|
373 |
}
|
374 |
return tempReturn.toString();
|
375 |
}
|
376 |
|
377 |
public String __get_guid(String in)
|
378 |
{
|
379 |
String guid = "";
|
380 |
Pattern p = Pattern.compile(".*guid=([a-z0-9-]+)\"");
|
381 |
Matcher m = p.matcher(in);
|
382 |
Boolean has_found = m.find();
|
383 |
|
384 |
if (!has_found)
|
385 |
{
|
386 |
return null;
|
387 |
}
|
388 |
|
389 |
if (m.groupCount() > 0)
|
390 |
{
|
391 |
guid = m.group(1);
|
392 |
}
|
393 |
|
394 |
return guid;
|
395 |
}
|
396 |
|
397 |
public String[] __parse_head(String in)
|
398 |
{
|
399 |
String[] ret = new String[7];
|
400 |
|
401 |
// System.out.println(""+in);
|
402 |
|
403 |
String sizestring = "";
|
404 |
|
405 |
// <img src="/images/icons/container/micro.gif" alt="Size: Micro"
|
406 |
Pattern p = Pattern.compile("<img src=\"/images/icons/container/([^\\.]+)\\.gif\" alt=\"Size:");
|
407 |
Matcher m = p.matcher(in);
|
408 |
Boolean has_found = m.find();
|
409 |
|
410 |
String size = "5";
|
411 |
String lat = "0.0";
|
412 |
String lon = "0.0";
|
413 |
String diff = "1";
|
414 |
String terr = "1";
|
415 |
String type = GeocacheCoordinate.TYPE_REGULAR;
|
416 |
String owner = "dummy";
|
417 |
|
418 |
if (!has_found)
|
419 |
{
|
420 |
ret[0] = size;
|
421 |
ret[1] = diff;
|
422 |
ret[2] = terr;
|
423 |
ret[3] = owner;
|
424 |
ret[4] = lat;
|
425 |
ret[5] = lon;
|
426 |
|
427 |
System.out.println("__parse_head: problem -> no data!");
|
428 |
return ret;
|
429 |
}
|
430 |
|
431 |
if (m.groupCount() > 0)
|
432 |
{
|
433 |
sizestring = m.group(1);
|
434 |
|
435 |
if (sizestring.compareTo("micro") == 0)
|
436 |
{
|
437 |
size = "1";
|
438 |
}
|
439 |
else if (sizestring.compareTo("small") == 0)
|
440 |
{
|
441 |
size = "2";
|
442 |
}
|
443 |
else if (sizestring.compareTo("regular") == 0)
|
444 |
{
|
445 |
size = "3";
|
446 |
}
|
447 |
else if ((sizestring.compareTo("large") == 0) || (sizestring.compareTo("big") == 0))
|
448 |
{
|
449 |
size = "4";
|
450 |
}
|
451 |
else if ((sizestring.compareTo("not_chosen") == 0) || (sizestring.compareTo("other") == 0))
|
452 |
{
|
453 |
size = "5";
|
454 |
}
|
455 |
if (DEBUG_) System.out.println("size=" + size);
|
456 |
}
|
457 |
|
458 |
// <img src="/images/WptTypes/2.gif" alt="Traditional Cache"
|
459 |
p = Pattern.compile("<img src=\"/images/WptTypes/.*\\.gif\" alt=\"([^\"]*)\"");
|
460 |
m = p.matcher(in);
|
461 |
has_found = m.find();
|
462 |
if (has_found)
|
463 |
{
|
464 |
if (m.groupCount() > 0)
|
465 |
{
|
466 |
if (m.group(1).compareTo("Traditional Cache") == 0)
|
467 |
{
|
468 |
type = GeocacheCoordinate.TYPE_REGULAR;
|
469 |
}
|
470 |
else if (m.group(1).compareTo("Multi-cache") == 0)
|
471 |
{
|
472 |
type = GeocacheCoordinate.TYPE_MULTI;
|
473 |
}
|
474 |
else if (m.group(1).compareTo("Unknown Cache") == 0)
|
475 |
{
|
476 |
type = GeocacheCoordinate.TYPE_MYSTERY;
|
477 |
}
|
478 |
else
|
479 |
{
|
480 |
type = GeocacheCoordinate.TYPE_UNKNOWN;
|
481 |
}
|
482 |
if (DEBUG_) System.out.println("type=" + type);
|
483 |
}
|
484 |
}
|
485 |
|
486 |
p = Pattern.compile("(?s)uxLegendScale\"[^>]*?><img src=\"http://www.geocaching.com/images/stars/stars[0-9_]+\\.gif\" alt=\"([0-9.]+) out");
|
487 |
m = p.matcher(in);
|
488 |
has_found = m.find();
|
489 |
if (has_found)
|
490 |
{
|
491 |
if (m.groupCount() > 0)
|
492 |
{
|
493 |
diff = String.format("%.0f", Double.parseDouble(m.group(1)) * 10);
|
494 |
if (DEBUG_) System.out.println("diff=" + diff);
|
495 |
}
|
496 |
}
|
497 |
|
498 |
p = Pattern.compile("(?s)ContentBody_Localize6\"[^>]*?><img src=\"http://www.geocaching.com/images/stars/stars[0-9_]+\\.gif\" alt=\"([0-9.]+) out");
|
499 |
m = p.matcher(in);
|
500 |
has_found = m.find();
|
501 |
if (has_found)
|
502 |
{
|
503 |
if (m.groupCount() > 0)
|
504 |
{
|
505 |
terr = String.format("%.0f", Double.parseDouble(m.group(1)) * 10);
|
506 |
if (DEBUG_) System.out.println("terr=" + terr);
|
507 |
}
|
508 |
}
|
509 |
|
510 |
// owner =
|
511 |
// HTMLManipulations._decode_htmlentities(re.compile("\\sby <[^>]+>([^<]+)</a>",
|
512 |
// re.MULTILINE).search(head).group(1))
|
513 |
|
514 |
Pattern p2 = Pattern.compile("lat=([0-9.-]+)&lon=([0-9.-]+)&");
|
515 |
Matcher m2 = p2.matcher(in);
|
516 |
Boolean has_found2 = m2.find();
|
517 |
|
518 |
if (!has_found2)
|
519 |
{
|
520 |
lat = "0.0";
|
521 |
lon = "0.0";
|
522 |
|
523 |
ret[0] = size;
|
524 |
ret[1] = diff;
|
525 |
ret[2] = terr;
|
526 |
ret[3] = owner;
|
527 |
ret[4] = lat;
|
528 |
ret[5] = lon;
|
529 |
|
530 |
Message msg = this.main_aagtl.toast_handler.obtainMessage();
|
531 |
Bundle b = new Bundle();
|
532 |
b.putInt("command", 1);
|
533 |
b.putInt("duration", Toast.LENGTH_LONG);
|
534 |
// b.putString("text", "__parse_head: problem parsing lat,lon -> " +
|
535 |
// in);
|
536 |
b.putString("text", "problem downloading cache\n\nplease check username/password!!\n\nor maybe network error");
|
537 |
msg.setData(b);
|
538 |
this.main_aagtl.toast_handler.sendMessage(msg);
|
539 |
|
540 |
System.out.println("__parse_head: problem parsing lat,lon -> 0.0 0.0 !");
|
541 |
System.out.println("" + in);
|
542 |
return ret;
|
543 |
}
|
544 |
else
|
545 |
{
|
546 |
if (m2.groupCount() > 1)
|
547 |
{
|
548 |
lat = m2.group(1);
|
549 |
lon = m2.group(2);
|
550 |
}
|
551 |
}
|
552 |
|
553 |
ret[0] = size;
|
554 |
ret[1] = diff;
|
555 |
ret[2] = terr;
|
556 |
ret[3] = owner;
|
557 |
ret[4] = lat;
|
558 |
ret[5] = lon;
|
559 |
ret[6] = type;
|
560 |
|
561 |
if (DEBUG_) System.out.println("lat=" + lat);
|
562 |
if (DEBUG_) System.out.println("lon=" + lon);
|
563 |
// System.out.println("size=" + size);
|
564 |
// System.out.println("lat=" + lat);
|
565 |
// System.out.println("lon=" + lon);
|
566 |
|
567 |
return ret;
|
568 |
}
|
569 |
|
570 |
}
|