/* GNU General Public License CacheWolf is a software for PocketPC, Win and Linux that enables paperless caching. It supports the sites geocaching.com and opencaching.de Copyright (C) 2006 CacheWolf development team See http://www.cachewolf.de/ for more information. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package CacheWolf.imp; import com.stevesoft.ewe_pat.Regex; import CacheWolf.MainForm; import CacheWolf.OC; import CacheWolf.Preferences; import CacheWolf.Profile; import CacheWolf.controls.InfoBox; import CacheWolf.database.CWPoint; import CacheWolf.database.CacheDB; import CacheWolf.database.CacheHolder; import CacheWolf.database.CacheImage; import CacheWolf.database.CacheSize; import CacheWolf.database.CacheTerrDiff; import CacheWolf.database.CacheType; import CacheWolf.database.CoordinatePoint; import CacheWolf.database.Log; import CacheWolf.navi.TransformCoordinates; import CacheWolf.utils.BetterUTF8Codec; import CacheWolf.utils.Common; import CacheWolf.utils.MyLocale; import CacheWolf.utils.STRreplace; import CacheWolf.utils.SafeXML; import CacheWolf.utils.UrlFetcher; import ewe.io.BufferedReader; import ewe.io.File; import ewe.io.IOException; import ewe.io.TextReader; import ewe.net.MalformedURLException; import ewe.net.URL; import ewe.sys.Convert; import ewe.sys.Double; import ewe.sys.Time; import ewe.sys.Vm; import ewe.ui.FormBase; import ewe.util.Enumeration; import ewe.util.Hashtable; import ewe.util.zip.ZipEntry; import ewe.util.zip.ZipException; import ewe.util.zip.ZipFile; import ewesoft.xml.MinML; import ewesoft.xml.sax.AttributeList; /** * Class to import Data from opencaching. It uses the lastmodified parameter to identify new or changed caches. See here: http://www.opencaching.com/phpBB2/viewtopic.php?t=281 (out-dated) See here: http://www.opencaching.de/doc/xml/xml11.htm and * http://develforum.opencaching.de/viewtopic.php?t=135&postdays=0&postorder=asc&start=0 for more information. */ public class OCXMLImporter extends MinML { static protected final int STAT_INIT = 0; static protected final int STAT_CACHE = 1; static protected final int STAT_CACHE_DESC = 2; static protected final int STAT_CACHE_LOG = 3; static protected final int STAT_PICTURE = 4; String hostname; int state = STAT_INIT; int numCacheImported, numDescImported, numLogImported = 0; int numCacheUpdated, numDescUpdated, numLogUpdated = 0; boolean debugGPX = false; CacheDB cacheDB; InfoBox inf; // CacheHolder ch; CacheHolder holder; Time dateOfthisSync; String strData = ""; int picCnt; boolean incUpdate = true; // complete or incremental Update boolean incFinds = true; Hashtable DBindexID = new Hashtable(); String picUrl = ""; String picTitle = ""; String picID; String cacheID; String logData, logIcon, logDate, logFinder, logId, finderID; boolean loggerRecommended; int logtype; String user; /** Temporarly save the values from XML */ double longitude; /** Temporarly save the values from XML: set to the language of the description which is currently parsed */ String processingDescLang; boolean isHTML; boolean isSyncSingle; // to load archieved boolean downloadPics = true; public OCXMLImporter() { cacheDB = MainForm.profile.cacheDB; incUpdate = true; if (MainForm.profile.getLast_sync_opencaching() == null || MainForm.profile.getLast_sync_opencaching().length() < 12) { MainForm.profile.setLast_sync_opencaching("20050801000000"); incUpdate = false; } user = Preferences.itself().myAlias.toLowerCase(); CacheHolder ch; for (int i = 0; i < cacheDB.size(); i++) { ch = cacheDB.get(i); if (!ch.getIdOC().equals("")) DBindexID.put(ch.getIdOC(), ch.getCode()); } } /** * * @param number * @param infB * @return true, if some change was made to the cacheDB */ public boolean syncSingle(int number, InfoBox infB) { CacheHolder ch; ch = cacheDB.get(number); hostname = OC.getOCHostName(ch.getCode()); holder = null; if (infB.isClosed()) { // there could have been an update before return true; } inf = new InfoBox("Opencaching download", MyLocale.getMsg(1608, "downloading data\n from " + hostname), InfoBox.PROGRESS_WITH_WARNINGS, false); inf.setPreferredSize(220, 300); inf.relayout(false); inf.exec(); String lastS; /** * Preferences.itself().downloadmissingOC = true, if not the last syncdate shall be used, but the caches shall be reloaded only used in syncSingle */ incUpdate = false; if (Preferences.itself().downloadAllOC) lastS = "20050801000000"; else { if (ch.getLastSync().length() < 14) lastS = "20050801000000"; else { lastS = ch.getLastSync(); incUpdate = true; } } dateOfthisSync = new Time(); dateOfthisSync.parse(lastS, "yyyyMMddHHmmss"); picCnt = 0; // Build url String url = "http://" + hostname + "/xml/ocxml11.php?" + "modifiedsince=" + lastS + "&cache=1" + "&cachedesc=1"; if (downloadPics) url += "&picture=1"; else url += "&picture=0"; url += "&cachelog=1" + "&removedobject=0" + "&wp=" + ch.getCode() + "&charset=utf-8" + "&cdata=0" + "&session=0"; ch.setUpdated(false); isSyncSingle = true; syncOC(url); inf.close(0); return true; } public void doIt() { boolean success = true; String finalMessage; String lastS = MainForm.profile.getLast_sync_opencaching(); final CWPoint centre = Preferences.itself().curCentrePt; // No need to clone curCentrePt as centre is only read if (!centre.isValid()) { new InfoBox(MyLocale.getMsg(5500, "Error"), "Coordinates for centre must be set").wait(FormBase.OKB); return; } final ImportGui importGui = new ImportGui(MyLocale.getMsg(130, "Download from opencaching"), ImportGui.ALL | ImportGui.DIST | ImportGui.INCLUDEFOUND | ImportGui.HOST, ImportGui.DESCRIPTIONIMAGE | ImportGui.SPOILERIMAGE | ImportGui.LOGIMAGE); if (importGui.execute() == FormBase.IDCANCEL) { return; } downloadPics = importGui.downloadDescriptionImages; Vm.showWait(true); String dist = importGui.maxDistanceInput.getText(); incFinds = !importGui.foundCheckBox.getState(); if (importGui.domains.getSelectedItem() != null) { hostname = (String) importGui.domains.getSelectedItem(); Preferences.itself().lastOCSite = hostname; } if (dist.length() == 0) return; final Double distDouble = new Double(); distDouble.value = Common.parseDouble(dist); dist = distDouble.toString(0, 1, 0).replace(',', '.'); // check, if distance is greater than before incUpdate = true; if (Convert.toInt(dist) > Convert.toInt(MainForm.profile.getDistOC()) || Preferences.itself().downloadAllOC) { // resysnc lastS = "20050801000000"; incUpdate = false; } MainForm.profile.setDistOC(dist); // Clear status of caches in db CacheHolder ch; for (int i = cacheDB.size() - 1; i >= 0; i--) { ch = cacheDB.get(i); ch.setUpdated(false); ch.setNew(false); ch.setLogUpdated(false); } picCnt = 0; // Build url String url = "http://" + hostname + "/xml/ocxml11.php?" + "modifiedsince=" + lastS + "&cache=1" + "&cachedesc=1"; if (downloadPics) url += "&picture=1"; else url += "&picture=0"; url += "&cachelog=1" + "&removedobject=0" + "&lat=" + centre.getLatDeg(TransformCoordinates.DD) + "&lon=" + centre.getLonDeg(TransformCoordinates.DD) + "&distance=" + dist + "&charset=utf-8" + "&cdata=0" + "&session=0"; inf = new InfoBox("Opencaching download", MyLocale.getMsg(1608, "downloading data\n from opencaching"), InfoBox.PROGRESS_WITH_WARNINGS, false); inf.setPreferredSize(220, 300); inf.relayout(false); inf.exec(); isSyncSingle = false; success = syncOC(url); MainForm.profile.saveIndex(Profile.SHOW_PROGRESS_BAR); Vm.showWait(false); if (success) { MainForm.profile.setLast_sync_opencaching(dateOfthisSync.format("yyyyMMddHHmmss")); // Preferences.itself().savePreferences(); finalMessage = MyLocale.getMsg(1607, "Update from opencaching successful"); inf.addWarning("Number of" + "\n...caches new/updated: " + numCacheImported + " / " + numCacheUpdated + "\n...cache descriptions new/updated: " + numDescImported + "\n...logs new/updated: " + numLogImported); inf.setInfo(finalMessage); } inf.showButton(FormBase.YESB); } private boolean syncOC(String address) { boolean success = true; File tmpFile = null; BufferedReader r; // inf = new InfoBox("Opencaching download", MyLocale.getMsg(1608,"downloading data\n from opencaching"), InfoBox.PROGRESS_WITH_WARNINGS, false); picCnt = 0; String finalMessage = ""; try { holder = null; final String target = MainForm.profile.dataDir + "dummy.zip"; UrlFetcher.fetchDataFile(address, target); // parse tmpFile = new File(target); if (tmpFile.getLength() == 0) { throw new IOException("no updates available"); } final ZipFile zif = new ZipFile(target); ZipEntry zipEnt; final Enumeration zipEnum = zif.entries(); inf.setInfo("...unzipping update file"); while (zipEnum.hasMoreElements()) { zipEnt = (ZipEntry) zipEnum.nextElement(); // skip over PRC-files and empty files if (zipEnt.getSize() > 0 && zipEnt.getName().endsWith("xml")) { TextReader tr = new TextReader(zif.getInputStream(zipEnt)); tr.codec = new BetterUTF8Codec(); String lineRead = tr.readLine().toLowerCase(); if (lineRead.startsWith("")) { // erste Zeile �berlesen // <?xml version="1.0" encoding="utf-8"?> // weil der parser das erste Zeichen nicht mag und dann aussteigt tr.read(); } //r = new BufferedReader(new InputStreamReader(zif.getInputStream(zipEnt), IO.JAVA_UTF8_CODEC)); parse(tr); tr.close(); } } zif.close(); } catch (final ZipException e) { finalMessage = MyLocale.getMsg(1614, "Error while unzipping udpate file"); success = false; } catch (final IOException e) { if (e.getMessage().equalsIgnoreCase("no updates available")) { finalMessage = "No updates available"; success = false; } else { if (e.getMessage().equalsIgnoreCase("could not connect") || e.getMessage().equalsIgnoreCase("unkown host")) { // is there a better way to find out what happened? finalMessage = MyLocale.getMsg(1616, "Error: could not download update file from " + hostname); } else { finalMessage = "IOException: " + e.getMessage(); } success = false; } } catch (final IllegalArgumentException e) { finalMessage = MyLocale.getMsg(1621, "Error parsing update file\n this is likely a bug in " + hostname + "\nplease try again later\n, state:") + " " + state + ", waypoint: " + holder.getCode(); success = false; Preferences.itself().log("Parse error: " + state + " " + holder.getCode(), e, true); } catch (final Exception e) { // here should be used the correct exception if (holder != null) finalMessage = MyLocale.getMsg(1615, "Error parsing update file, state:") + " " + state + ", waypoint: " + holder.getCode(); else finalMessage = MyLocale.getMsg(1615, "Error parsing update file, state:") + " " + state + ", waypoint: <unkown>"; success = false; Preferences.itself().log("", e, true); } finally { if (tmpFile != null) tmpFile.delete(); } /* * for (int i=cacheDB.size()-1; i >=0; i--) { ch = (CacheHolder)cacheDB.get(i); if (ch.wayPoint.toUpperCase().startsWith("OC")) { //TODO only handle changed caches ch.calcRecommendationScore(); } } */ inf.setInfo(finalMessage); return success; } public void startElement(String name, AttributeList atts) { if (debugGPX) { for (int i = 0; i < atts.getLength(); i++) { Preferences.itself().log(" Name: " + atts.getName(i) + " Value: " + atts.getValue(i)); } } strData = ""; if (name.equals("oc11xml")) { final Time lastSync = new Time(); try { lastSync.parse(atts.getValue("date"), "yyyy-MM-dd HH:mm:ss"); } catch (final IllegalArgumentException e) { Preferences.itself().log("", e, true); } // reduce time at 1 second to avoid sync problems lastSync.setTime(lastSync.getTime() - 1000); dateOfthisSync = lastSync; state = STAT_INIT; } // look for changes in the state if (name.equals("cache")) { state = STAT_CACHE; } if (name.equals("cachedesc")) { state = STAT_CACHE_DESC; } if (name.equals("cachelog")) { state = STAT_CACHE_LOG; logtype = 0; } if (name.equals("picture")) { state = STAT_PICTURE; } // examine data switch (state) { case STAT_CACHE: startCache(name, atts); break; case STAT_CACHE_DESC: startCacheDesc(name, atts); break; case STAT_CACHE_LOG: startCacheLog(name, atts); break; case STAT_PICTURE: startPicture(name, atts); break; } } public void endElement(String name) { // examine data switch (state) { case STAT_CACHE: endCache(name); break; case STAT_CACHE_DESC: endCacheDesc(name); break; case STAT_CACHE_LOG: endCacheLog(name); break; case STAT_PICTURE: endPicture(name); break; } // look for changes in the state if (name.equals("cache")) state = STAT_INIT; if (name.equals("cachedesc")) state = STAT_INIT; if (name.equals("cachelog")) state = STAT_INIT; if (name.equals("picture")) state = STAT_INIT; } public void characters(char[] ch2, int start, int length) { final String chars = new String(ch2, start, length); strData += chars; if (debugGPX) Preferences.itself().log(strData, null); } private void startCache(String name, AttributeList atts) { if (name.equals("id")) { cacheID = atts.getValue("id"); return; } if (holder == null) return; inf.setInfo(MyLocale.getMsg(1609, "Importing Cache:") + " " + numCacheImported + " / " + numCacheUpdated + "\n"); if (name.equals("type")) { holder.setType(CacheType.ocType2CwType(atts.getValue("id"))); holder.getDetails().attributes.clear(); return; } if (name.equals("status")) { // meaning of OC status : // 1=Kann gesucht werden ; // 2=Momentan nicht verf�gbar ; // 3=Archiviert ; // 4= ; // 5= ; // 6=Gesperrt ; // are there more ? ; if (atts.getValue("id").equals("1")) { holder.setAvailable(true); holder.setArchived(false); } else { holder.setAvailable(false); if ((atts.getValue("id").equals("3")) || (atts.getValue("id").equals("6")) || (atts.getValue("id").equals("7"))) { if (!isSyncSingle) { holder = null; numCacheImported--; } else { // Umsetzung wie in gpx f�r Status 6 if (atts.getValue("id").equals("6")) { holder.setArchived(false); } else { holder.setArchived(true); } } } } return; } if (name.equals("size")) { holder.setSize(CacheSize.ocXmlString2Cw(atts.getValue("id"))); return; } if (name.equals("waypoints")) { holder.setCode(atts.getValue("oc")); final String CName = atts.getValue("nccom") + " " + atts.getValue("gccom"); if (!CName.equals(" ")) { holder.setOwner(holder.getOwner() + " / " + CName.trim()); holder.getDetails().attributes.add(7); // wwwlink holder.setAttribsAsBits(holder.getDetails().attributes.getAttribsAsBits()); } else { holder.getDetails().attributes.add(6); // oconly holder.setAttribsAsBits(holder.getDetails().attributes.getAttribsAsBits()); } if (holder.getCode().length() == 0) throw new IllegalArgumentException("empty waypointname"); // this should not happen - it is likey a bug in opencaching / it happens on 27-12-2006 on cache OC143E return; } if (name.equals("attribute")) { final int id = Integer.parseInt(atts.getValue("id")); holder.getDetails().attributes.add(id); holder.setAttribsAsBits(holder.getDetails().attributes.getAttribsAsBits()); return; } } private void startCacheDesc(String name, AttributeList atts) { inf.setInfo(MyLocale.getMsg(1611, "Importing cache description:") + " " + numDescImported); if (name.equals("cacheid")) { cacheID = atts.getValue("id"); holder = getHolder(cacheID, false); return; } if (name.equals("desc")) { isHTML = atts.getValue("html").equals("1") ? true : false; return; } if (name.equals("language")) { processingDescLang = atts.getValue("id"); return; } } private void startCacheLog(String name, AttributeList atts) { if (name.equals("id")) { logId = atts.getValue("id"); return; } if (name.equals("cacheid")) { holder = getHolder(atts.getValue("id"), false); return; } if (holder == null) return; inf.setInfo(MyLocale.getMsg(1612, "Importing Cachlog:") + " " + numLogImported); if (name.equals("logtype")) { logtype = Convert.toInt(atts.getValue("id")); switch (logtype) { case 1: logIcon = Log.typeText2Image("Found"); break; case 2: logIcon = Log.typeText2Image("Not Found"); holder.setNoFindLogs((byte) (holder.getNoFindLogs() + 1)); break; case 3: logIcon = Log.typeText2Image("Note"); } loggerRecommended = atts.getValue("recommended").equals("1"); return; } } private void startPicture(String name, AttributeList atts) { if (name.equals("object")) { cacheID = atts.getValue("id"); // are there picture without cacheID? holder = getHolder(cacheID, false); return; } } private void endCache(String name) { if (name.equals("id")) { // </id> // the guid (=strData) is not part of gpx , so we use id of cacheID holder = getHolder(cacheID, true); // Allocate a new CacheHolder object holder.setIdOC(cacheID); holder.getDetails().URL = "http://" + hostname + "/viewcache.php?cacheid=" + cacheID; return; } if (holder == null) return; // id should always be the first for a <cache> if (name.equals("cache")) { holder.setLastSync(dateOfthisSync.format("yyyyMMddHHmmss")); int index; index = cacheDB.getIndex(holder.getCode()); if (index == -1) { numCacheImported++; holder.setNew(true); cacheDB.add(holder); DBindexID.put(holder.getIdOC(), holder.getCode()); } // update (overwrite) data else { numCacheUpdated++; holder.setNew(false); holder.setIncomplete(false); cacheDB.get(index).update(holder); DBindexID.put(holder.getIdOC(), holder.getCode()); } // clear data (picture, logs) if we do a complete Update if (!incUpdate) { holder.getDetails().CacheLogs.clear(); holder.getDetails().images.clear(); } // save all holder.getDetails().hasUnsavedChanges = true; // this makes CachHolder save the details in case that they are unloaded from memory // chD.saveCacheDetails(MainForm.profile.dataDir); // MainForm.profile.saveIndex(pref,Profile.NO_SHOW_PROGRESS_BAR); // this is done after .xml is completly processed holder = null; return; } if (name.equals("name")) { holder.setName(strData); return; } if (name.equals("userid")) { holder.setOwner(strData); return; } if (name.equals("longitude")) { longitude = Common.parseDouble(strData); return; } if (name.equals("latitude")) { holder.setWpt(new CoordinatePoint(Common.parseDouble(strData), longitude)); holder.setUpdated(false); // todo : correct definition of usage for this return; } if (name.equals("difficulty")) { holder.setDifficulty(CacheTerrDiff.v1Converter(strData)); return; } if (name.equals("terrain")) { holder.setTerrain(CacheTerrDiff.v1Converter(strData)); return; } if (name.equals("datehidden")) { holder.setHidden(strData.substring(0, 10)); // Date; return; } if (name.equals("country")) { holder.getDetails().setCountry(strData); return; } } private void endCacheDesc(String name) { if (holder == null) return; if (name.equals("cachedesc")) { numDescImported++; holder.isHTML(isHTML); if (downloadPics && isHTML) { getImageNamesFromDescription(); } holder.getDetails().hasUnsavedChanges = true; return; } if (name.equals("shortdesc")) { String linebraek; if (isHTML) linebraek = "<br>\n"; else linebraek = "\n"; // if a long description has been entered in this run (==holder.cache_updated is true), // then this one is added (for another language) // otherwise all previous descriptions will be overwritten ( or there are none yet) if (holder.isUpdated()) holder.getDetails().LongDescription += linebraek + processingDescLang + ":" + linebraek + strData + linebraek; else holder.getDetails().LongDescription = processingDescLang + ":" + linebraek + strData + linebraek; return; } if (name.equals("desc")) { // </desc> if (isHTML) holder.getDetails().LongDescription += SafeXML.html2iso8859s1(strData); else holder.getDetails().LongDescription += strData; return; } if (name.equals("hint")) { String linebreak; if (isHTML) linebreak = "<br>\n"; else linebreak = "\n"; if (holder.isUpdated()) holder.getDetails().Hints += linebreak + "[" + processingDescLang + ":]" + linebreak + Common.rot13(strData) + linebreak; else holder.getDetails().Hints = "[" + processingDescLang + ":]" + linebreak + Common.rot13(strData) + linebreak; // remark: // holder.cache_updated will be set to true // after the subtag-infos of tag <cachedesc> have been entered // (ending with the subtag </hint>) // to possibly add the <cachedesc> for an additional language holder.setUpdated(true); return; } } private void endCacheLog(String name) { if (holder == null) return; if (name.equals("cachelog")) { // </cachelog> if (holder.getDetails().CacheLogs.merge(new Log(logId, finderID, logIcon, logDate, logFinder, logData, loggerRecommended)) > -1) { numLogImported++; holder.getDetails().hasUnsavedChanges = true; // chD.saveCacheDetails(MainForm.profile.dataDir); } // if ((logFinder.equalsIgnoreCase(user) || logFinder.equalsIgnoreCase(Preferences.itself().myAlias2)) && logtype == 1) { if (incFinds || !holder.isNew()) { if (holder.getStatus().indexOf(":") < 0) { holder.setStatus(logDate); } else { if (!Preferences.itself().keepTimeOnUpdate) { holder.setStatus(logDate); } } holder.setFound(true); holder.getDetails().setOwnLog(new Log(logId, finderID, logIcon, logDate, logFinder, logData, loggerRecommended)); } else { // if (holder.is_new()) cacheDB.removeElementAt(cacheDB.getIndex(holder)); DBindexID.remove(holder.getCacheID()); // und Dateien l�schen? final File tmpFile = new File(MainForm.profile.dataDir + holder.getCode() + ".xml"); tmpFile.delete(); // todo: was ist mit den schon heruntergeladenen Bildern? } } return; } if (name.equals("date")) { logDate = strData; return; } if (name.equals("userid")) { logFinder = strData; return; } if (name.equals("text")) { logData = STRreplace.replace(strData, "\n", "<br />"); return; } } private void endPicture(String name) { if (holder == null) return; if (name.equals("id")) { picID = strData; return; } if (name.equals("url")) { picUrl = strData; return; } if (name.equals("title")) { picTitle = strData; return; } if (name.equals("picture")) { inf.setInfo(MyLocale.getMsg(1613, "Pictures:") + " " + ++picCnt); final CacheImage ii = new CacheImage(CacheImage.FROMUNKNOWN); ii.setTitle(picTitle); ii.setURL(picUrl); getPic(ii); holder.getDetails().hasUnsavedChanges = true; // saveCacheDetails(MainForm.profile.dataDir); return; } } private CacheHolder getHolder(String guid, boolean create) {// See also LOCXMLImporter CacheHolder ch = null; // Integer INTR = (Integer)DBindexID.get(guid); final String wp = (String) DBindexID.get(guid); // if(INTR != null){ if (wp != null) { // ch = cacheDB.get(INTR.intValue()); ch = cacheDB.get(wp); } else { if (create) ch = new CacheHolder(); } return ch; } private void getImageNamesFromDescription() { String fetchUrl; String imgTag; String imgAltText; final Regex imgRegexUrl = new Regex("(<img[^>]*src=[\"\']([^>^\"^\']*)[^>]*>|<img[^>]*src=([^>^\"^\'^ ]*)[^>]*>)"); // Ergebnis enthlt keine Anfhrungszeichen final Regex imgRegexAlt = new Regex("(?:alt=[\"\']([^>^\"^\']*)|alt=([^>^\"^\'^ ]*))"); // get alternative text for Pic imgRegexAlt.setIgnoreCase(true); imgRegexUrl.setIgnoreCase(true); int descIndex = 0; int numDownloaded = 1; while (imgRegexUrl.searchFrom(holder.getDetails().LongDescription, descIndex)) { // "img" found imgTag = imgRegexUrl.stringMatched(1); // (1) enthlt das gesamte <img ...>-tag fetchUrl = imgRegexUrl.stringMatched(2); // URL in Anfhrungszeichen in (2) falls ohne in (3) Ergebnis ist auf jeden Fall ohne Anfhrungszeichen if (fetchUrl == null) { fetchUrl = imgRegexUrl.stringMatched(3); } if (fetchUrl == null) { // TODO Fehler ausgeben: nicht abgedeckt ist der Fall, dass in einem Cache Links auf Bilder mit unterschiedlichen URL, aber gleichem Dateinamen sind. inf.addWarning(MyLocale.getMsg(1617, "Ignoriere Fehler in html-Cache-Description: \"<img\" without \"src=\" in cache " + holder.getCode())); continue; } inf.setInfo(MyLocale.getMsg(1611, "Importing cache description:") + " " + numDescImported + "\n" + MyLocale.getMsg(1620, "downloading embedded images: ") + numDownloaded++); if (imgRegexAlt.search(imgTag)) { imgAltText = imgRegexAlt.stringMatched(1); if (imgAltText == null) imgAltText = imgRegexAlt.stringMatched(2); // no alternative text as image title -> use filename } else { if (fetchUrl.toLowerCase().indexOf("opencaching.") > 0 || fetchUrl.toLowerCase().indexOf("geocaching.com") > 0) // wenn von Opencaching oder geocaching ist Dateiname doch nicht so toll, weil nur aus Nummer bestehend imgAltText = "No image title"; else imgAltText = fetchUrl.substring(fetchUrl.lastIndexOf('/') + 1); } descIndex = imgRegexUrl.matchedTo(); try { // TODO this is not quite correct: actually the "base" URL must be known... // but anyway a different baseURL should not happen very often - it doesn't in my area if (!fetchUrl.startsWith("http://")) { fetchUrl = new URL(new URL("http://" + hostname + "/"), fetchUrl).toString(); } } catch (final MalformedURLException e) { final String ErrMessage = MyLocale.getMsg(1618, "Ignoring error in cache: ") + holder.getCode() + ": ignoring MalformedUrlException: " + e.getMessage() + " while downloading from URL:" + fetchUrl; inf.addWarning("\n" + ErrMessage); Preferences.itself().log(ErrMessage, e); } final CacheImage imageInfo = new CacheImage(CacheImage.FROMDESCRIPTION); imageInfo.setURL(fetchUrl); imageInfo.setTitle(imgAltText); getPic(imageInfo); } } private void getPic(CacheImage imageInfo) { // TODO handling of relativ URLs String fileName = holder.getCode() + "_" + imageInfo.getURL().substring(imageInfo.getURL().lastIndexOf('/') + 1); fileName = Common.ClearForFileName(fileName).toLowerCase(); final String target = MainForm.profile.dataDir + fileName; imageInfo.setFilename(fileName); try { File ftest = new File(target); if (ftest.exists()) { if (ftest.length() == 0) { ftest.delete(); } else { holder.getDetails().images.add(imageInfo); } } else { if (downloadPics) { UrlFetcher.fetchDataFile(imageInfo.getURL(), target); ftest = new File(target); if (ftest.exists()) { if (ftest.length() > 0) { holder.getDetails().images.add(imageInfo); } else { ftest.delete(); } } } } } catch (final IOException e) { String ErrMessage; String wp, n; if (holder != null && holder.getCode() != null) wp = holder.getCode(); else wp = "WP???"; if (holder != null && holder.getName() != null) n = holder.getName(); else n = "name???"; String m; try { m = e.getMessage(); if (m == null) m = ""; } catch (Exception e2) { m = ""; } if (m.length() == 0) ErrMessage = "Ignoring error: OCXMLImporter.getPic: IOExeption == null, while downloading picture: " + fileName + " from URL:" + imageInfo.getURL(); else { if (m.equalsIgnoreCase("could not connect") || m.equalsIgnoreCase("unkown host")) { // is there a better way to find out what happened? ErrMessage = MyLocale.getMsg(1618, "Ignoring error in cache: ") + n + " (" + wp + ")" + MyLocale.getMsg(1619, ": could not download image from URL: ") + imageInfo.getURL(); } else ErrMessage = MyLocale.getMsg(1618, "Ignoring error in cache: ") + n + " (" + wp + "): ignoring IOException: " + m + " while downloading picture:" + fileName + " from URL:" + imageInfo.getURL(); } inf.addWarning(ErrMessage); Preferences.itself().log(ErrMessage, e, true); } } }