Revise timezone function
authorColin Clark <colin.clark@cclark.uk>
Tue, 11 Jan 2022 10:21:47 +0000 (10:21 +0000)
committerColin Clark <colin.clark@cclark.uk>
Tue, 11 Jan 2022 10:21:47 +0000 (10:21 +0000)
- Download database file from the web, instead of compiling locally
- Update zonedetect.c

CHECKLIST.md
geeqie-install-debian.sh
scripts/zonedetect/builder.cpp [deleted file]
scripts/zonedetect/create_timezone_database.sh [deleted file]
scripts/zonedetect/zoneToAlpha.h [deleted file]
src/exif-common.c
src/main.h
src/preferences.c
src/zonedetect.c

index ab7cb4c..cb76f47 100644 (file)
@@ -24,14 +24,6 @@ make update-po
 ./scripts/template-desktop.sh
 ```
 
-* Update the the timezone database if the underlying database has changed significantly
-
-```sh
-./scripts/zonedetect/create_timezone_database
-```
-
-* Upload the timezone database to TBD
-
 ## After compiling the sources, carry out the following actions when necessary
 
 * Update the man page and Command Line Options section in Help if the command line options have changed
index 900929c..0499c56 100755 (executable)
@@ -81,7 +81,7 @@ optional_array=(
 "libraw-dev"
 "libomp (required by libraw)"
 "libomp-dev"
-"libarchive (for compressed files e.g. zip)"
+"libarchive (for compressed files e.g. zip, including timezone)"
 "libarchive-dev"
 )
 
diff --git a/scripts/zonedetect/builder.cpp b/scripts/zonedetect/builder.cpp
deleted file mode 100644 (file)
index af6e65e..0000000
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * Copyright (c) 2018, Bertold Van den Bergh (vandenbergh@bertold.org)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the author nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <shapefil.h>
-#include <iostream>
-#include <limits>
-#include <fstream>
-#include <vector>
-#include <algorithm>
-#include <unordered_map>
-#include <functional>
-#include <math.h>
-#include <tuple>
-
-const double Inf = std::numeric_limits<float>::infinity();
-
-std::unordered_map<std::string, std::string> alpha2ToName;
-std::unordered_map<std::string, std::string> tzidToAlpha2;
-
-void errorFatal(std::string what)
-{
-    std::cerr<<what<<"\n";
-    exit(1);
-}
-
-int encodeVariableLength(std::vector<uint8_t>& output, int64_t valueIn, bool handleNeg = true)
-{
-    uint64_t value = valueIn * 2;
-    if(valueIn < 0) {
-        value = -valueIn * 2 + 1;
-    }
-
-    if(!handleNeg) {
-        value = valueIn;
-    }
-
-    int bytesUsed = 0;
-    do {
-        uint8_t byteOut = value & 0x7F;
-        if(value >= 128) {
-            byteOut |= 0x80;
-        }
-        output.push_back(byteOut);
-        bytesUsed ++;
-        value >>= 7;
-    } while(value);
-
-    return bytesUsed;
-}
-
-int64_t doubleToFixedPoint(double input, double scale, unsigned int precision = 32)
-{
-    double inputScaled = input / scale;
-    return inputScaled * pow(2, precision-1);
-
-}
-
-struct Point {
-    Point(double lat = 0, double lon = 0)
-    {
-        lat_ = lat;
-        lon_ = lon;
-    }
-
-    Point operator-(const Point& p)
-    {
-        Point result(lat_ - p.lat_, lon_ - p.lon_);
-        return result;
-    }
-
-    std::tuple<int64_t, int64_t> toFixedPoint(unsigned int precision = 32)
-    {
-        int64_t latFixedPoint = doubleToFixedPoint(lat_, 90, precision);
-        int64_t lonFixedPoint = doubleToFixedPoint(lon_, 180, precision);
-
-        return std::make_tuple(latFixedPoint, lonFixedPoint);
-    }
-
-    int encodePointBinary(std::vector<uint8_t>& output, unsigned int precision = 32)
-    {
-        int64_t latFixedPoint, lonFixedPoint;
-        std::tie(latFixedPoint, lonFixedPoint) = toFixedPoint(precision);
-
-        int bytesUsed = encodeVariableLength(output, latFixedPoint);
-        bytesUsed += encodeVariableLength(output, lonFixedPoint);
-
-        return bytesUsed;
-    }
-
-    double lat_;
-    double lon_;
-};
-
-struct PolygonData {
-    Point boundingMin;
-    Point boundingMax;
-    std::vector<Point> points_;
-    unsigned long fileIndex_ = 0;
-    unsigned long metadataId_;
-
-    void processPoint(const Point& p)
-    {
-        if(p.lat_ < boundingMin.lat_) {
-            boundingMin.lat_ = p.lat_;
-        }
-        if(p.lon_ < boundingMin.lon_) {
-            boundingMin.lon_ = p.lon_;
-        }
-        if(p.lat_ > boundingMax.lat_) {
-            boundingMax.lat_ = p.lat_;
-        }
-        if(p.lon_ > boundingMax.lon_) {
-            boundingMax.lon_ = p.lon_;
-        }
-
-        points_.push_back(p);
-    }
-
-    PolygonData(unsigned long id):
-        boundingMin(Inf, Inf),
-        boundingMax(-Inf, -Inf),
-        metadataId_(id)
-    {
-    }
-
-    long encodeBinaryData(std::vector<uint8_t>& output, unsigned int precision = 20)
-    {
-        long bytesEncoded = 0;
-        bool first = true;
-        int64_t latFixedPoint = 0, lonFixedPoint = 0;
-        int64_t latFixedPointPrev, lonFixedPointPrev;
-        uint64_t vertices = 0;
-
-        std::vector<uint8_t> tmp;
-
-        int64_t diffLatAcc = 0, diffLonAcc = 0, diffLatPrev = 0, diffLonPrev = 0;
-
-        for(Point& point: points_) {
-            /* The points should first be rounded, and then the integer value is differentiated */
-            latFixedPointPrev = latFixedPoint;
-            lonFixedPointPrev = lonFixedPoint;
-            std::tie(latFixedPoint, lonFixedPoint) = point.toFixedPoint(precision);
-
-            int64_t diffLat = latFixedPoint - latFixedPointPrev;
-            int64_t diffLon = lonFixedPoint - lonFixedPointPrev;
-
-            if(first) {
-                /* First point is always encoded */
-                vertices++;
-                encodeVariableLength(tmp, latFixedPoint);
-                encodeVariableLength(tmp, lonFixedPoint);
-                first = false;
-            } else {
-                /* Ignore points that are not different */
-                if(!diffLon && !diffLat) {
-                    continue;
-                }
-
-                if(diffLat != diffLatPrev || diffLon != diffLonPrev) {
-                    /* Encode accumulator */
-                    vertices++;
-                    encodeVariableLength(tmp, diffLatAcc);
-                    encodeVariableLength(tmp, diffLonAcc);
-
-                    diffLatAcc = 0;
-                    diffLonAcc = 0;
-                }
-
-                diffLatAcc += diffLat;
-                diffLonAcc += diffLon;
-            }
-
-            diffLatPrev = diffLat;
-            diffLonPrev = diffLon;
-        }
-
-        /* Encode final point */
-        vertices++;
-        encodeVariableLength(tmp, diffLatAcc);
-        encodeVariableLength(tmp, diffLonAcc);
-
-        encodeVariableLength(output, vertices, false);
-        std::copy(tmp.begin(), tmp.end(), std::back_inserter(output));
-
-        return bytesEncoded;
-    }
-};
-
-void encodeStringToBinary(std::vector<uint8_t>& output, std::string& input)
-{
-    encodeVariableLength(output, input.size(), false);
-    for(unsigned int i=0; i<input.size(); i++) {
-        output.push_back(input[i] ^ 0x80);
-    }
-}
-
-
-std::unordered_map<std::string, uint64_t> usedStrings_;
-
-struct MetaData {
-    void encodeBinaryData(std::vector<uint8_t>& output)
-    {
-        for(std::string& str: data_) {
-            if(str.length() >= 256) {
-                std::cout << "Metadata string is too long\n";
-                exit(1);
-            }
-
-            if(!usedStrings_.count(str)) {
-                usedStrings_[str] = output.size();
-                encodeStringToBinary(output, str);
-            } else {
-                encodeVariableLength(output, usedStrings_[str] + 256, false);
-            }
-        }
-    }
-
-    std::vector<std::string> data_;
-
-    unsigned long fileIndex_;
-};
-
-
-std::vector<PolygonData*> polygons_;
-std::vector<MetaData> metadata_;
-std::vector<std::string> fieldNames_;
-
-
-unsigned int decodeVariableLength(uint8_t* buffer, int64_t* result, bool handleNeg = true)
-{
-    int64_t value = 0;
-    unsigned int i=0, shift = 0;
-
-    do {
-        value |= (buffer[i] & 0x7F) << shift;
-        shift += 7;
-    } while(buffer[i++] & 0x80);
-
-    if(!handleNeg) {
-        *result = value;
-    } else {
-        *result = (value & 1)?-(value/2):(value/2);
-    }
-    return i;
-}
-
-void readMetaDataTimezone(DBFHandle dataHandle)
-{
-    /* Specify field names */
-    fieldNames_.push_back("TimezoneIdPrefix");
-    fieldNames_.push_back("TimezoneId");
-    fieldNames_.push_back("CountryAlpha2");
-    fieldNames_.push_back("CountryName");
-
-    /* Parse attribute names */
-    for(int i = 0; i < DBFGetRecordCount(dataHandle); i++) {
-        metadata_[i].data_.resize(4);
-        for(int j = 0; j < DBFGetFieldCount(dataHandle); j++) {
-            char fieldTitle[12];
-            int fieldWidth, fieldDecimals;
-            DBFFieldType eType = DBFGetFieldInfo(dataHandle, j, fieldTitle, &fieldWidth, &fieldDecimals);
-
-            fieldTitle[11] = 0;
-            std::string fieldTitleStr(fieldTitle);
-
-            if( eType == FTString ) {
-                if(fieldTitleStr == "tzid") {
-                    std::string data = DBFReadStringAttribute(dataHandle, i, j);
-                    size_t pos = data.find('/');
-                    if (pos == std::string::npos) {
-                        metadata_[i].data_.at(0) = data;
-                    } else {
-                        metadata_[i].data_.at(0) = data.substr(0, pos) + "/";
-                        metadata_[i].data_.at(1) = data.substr(pos + 1, std::string::npos);
-                    }
-                    if(tzidToAlpha2.count(data)) {
-                        metadata_[i].data_.at(2) = tzidToAlpha2[data];
-                        if(alpha2ToName.count(metadata_[i].data_.at(2))) {
-                            metadata_[i].data_.at(3) = alpha2ToName[metadata_[i].data_.at(2)];
-                        } else {
-                            std::cout<<metadata_[i].data_.at(2)<< " not found in alpha2ToName! ("<<data<<")\n";
-                        }
-                    } else {
-                        std::cout<<data<<" not found in zoneToAlpha2!\n";
-                    }
-                }
-            }
-        }
-    }
-}
-
-void readMetaDataNaturalEarthCountry(DBFHandle dataHandle)
-{
-    /* Specify field names */
-    fieldNames_.push_back("Alpha2");
-    fieldNames_.push_back("Alpha3");
-    fieldNames_.push_back("Name");
-
-    /* Parse attribute names */
-    for(int i = 0; i < DBFGetRecordCount(dataHandle); i++) {
-        metadata_[i].data_.resize(3);
-        for(int j = 0; j < DBFGetFieldCount(dataHandle); j++) {
-            char fieldTitle[12];
-            int fieldWidth, fieldDecimals;
-            DBFFieldType eType = DBFGetFieldInfo(dataHandle, j, fieldTitle, &fieldWidth, &fieldDecimals);
-
-            fieldTitle[11] = 0;
-            std::string fieldTitleStr(fieldTitle);
-
-            if( eType == FTString ) {
-                if(fieldTitleStr == "ISO_A2" || fieldTitleStr == "WB_A2") {
-                    std::string tmp = DBFReadStringAttribute(dataHandle, i, j);
-                    if(tmp != "-99") {
-                        metadata_[i].data_.at(0) = tmp;
-                    }
-                } else if(fieldTitleStr == "ISO_A3" || fieldTitleStr == "WB_A3" || fieldTitleStr == "BRK_A3") {
-                    std::string tmp = DBFReadStringAttribute(dataHandle, i, j);
-                    if(tmp != "-99") {
-                        metadata_[i].data_.at(1) = tmp;
-                    }
-                } else if(fieldTitleStr == "NAME_LONG") {
-                    metadata_[i].data_.at(2) = DBFReadStringAttribute(dataHandle, i, j);
-                }
-            }
-
-        }
-    }
-}
-
-std::unordered_map<std::string, std::string> parseAlpha2ToName(DBFHandle dataHandle)
-{
-    std::unordered_map<std::string, std::string> result;
-
-    for(int i = 0; i < DBFGetRecordCount(dataHandle); i++) {
-        std::string alpha2, name;
-        for(int j = 0; j < DBFGetFieldCount(dataHandle); j++) {
-            char fieldTitle[12];
-            int fieldWidth, fieldDecimals;
-            DBFFieldType eType = DBFGetFieldInfo(dataHandle, j, fieldTitle, &fieldWidth, &fieldDecimals);
-
-            fieldTitle[11] = 0;
-            std::string fieldTitleStr(fieldTitle);
-
-            if( eType == FTString ) {
-                if(fieldTitleStr == "ISO_A2" || fieldTitleStr == "WB_A2") {
-                    std::string tmp = DBFReadStringAttribute(dataHandle, i, j);
-                    if(tmp != "-99" && alpha2 == "") {
-                        alpha2 = tmp;
-                    }
-                } else if(fieldTitleStr == "NAME_LONG") {
-                    name = DBFReadStringAttribute(dataHandle, i, j);
-                }
-            }
-        }
-        if(alpha2 != "") {
-            result[alpha2]=name;
-        }
-    }
-
-    result["GF"]="French Guiana";
-    result["GP"]="Guadeloupe";
-    result["BQ"]="Bonaire";
-    result["MQ"]="Martinique";
-    result["SJ"]="Svalbard and Jan Mayen Islands";
-    result["NO"]="Norway";
-    result["CX"]="Christmas Island";
-    result["CC"]="Cocos Islands";
-    result["YT"]="Mayotte";
-    result["RE"]="RĂ©union";
-    result["TK"]="Tokelau";
-
-    return result;
-}
-
-std::unordered_map<std::string, std::string> parseTimezoneToAlpha2(std::string path)
-{
-    std::unordered_map<std::string, std::string> result;
-    //TODO: Clean solution...
-#include "zoneToAlpha.h"
-
-    return result;
-}
-
-int main(int argc, char ** argv )
-{
-    if(argc != 6) {
-        std::cout << "Wrong number of parameters\n";
-        return 1;
-    }
-
-    tzidToAlpha2 = parseTimezoneToAlpha2("TODO");
-
-    char tableType = argv[1][0];
-    std::string path = argv[2];
-    std::string outPath = argv[3];
-    unsigned int precision = strtol(argv[4], NULL, 10);
-    std::string notice = argv[5];
-
-    DBFHandle dataHandle = DBFOpen("naturalearth/ne_10m_admin_0_countries_lakes", "rb" );
-    alpha2ToName = parseAlpha2ToName(dataHandle);
-    DBFClose(dataHandle);
-
-    dataHandle = DBFOpen(path.c_str(), "rb" );
-    if( dataHandle == NULL ) {
-        errorFatal("Could not open attribute file\n");
-    }
-
-    metadata_.resize(DBFGetRecordCount(dataHandle));
-    std::cout << "Reading "<<metadata_.size()<<" metadata records.\n";
-
-    if(tableType == 'C') {
-        readMetaDataNaturalEarthCountry(dataHandle);
-    } else if(tableType == 'T') {
-        readMetaDataTimezone(dataHandle);
-    } else {
-        std::cout << "Unknown table type\n";
-        return 1;
-    }
-
-    DBFClose(dataHandle);
-
-    SHPHandle shapeHandle = SHPOpen(path.c_str(), "rb");
-    if( shapeHandle == NULL ) {
-        errorFatal("Could not open shapefile\n");
-    }
-
-    int numEntities, shapeType, totalPolygons = 0;
-    SHPGetInfo(shapeHandle, &numEntities, &shapeType, NULL, NULL);
-
-    std::cout<<"Opened "<<SHPTypeName( shapeType )<< " file with "<<numEntities<<" entries.\n";
-
-    for(int i = 0; i < numEntities; i++ ) {
-        SHPObject *shapeObject;
-
-        shapeObject = SHPReadObject( shapeHandle, i );
-        if(shapeObject) {
-            if(shapeObject->nSHPType != 3 && shapeObject->nSHPType != 5 &&
-                    shapeObject->nSHPType != 13 && shapeObject->nSHPType != 15) {
-                std::cout<<"Unsupported shape object ("<< SHPTypeName(shapeObject->nSHPType) <<")\n";
-                continue;
-            }
-
-            int partIndex = 0;
-
-            PolygonData* polygonData = nullptr;
-
-            for(int j = 0; j < shapeObject->nVertices; j++ ) {
-                if(j == 0 || j == shapeObject->panPartStart[partIndex]) {
-                    totalPolygons++;
-
-                    if(polygonData) {
-                        /* Commit it */
-                        polygons_.push_back(polygonData);
-                    }
-                    polygonData =  new PolygonData(i);
-
-                    if(partIndex + 1 < shapeObject->nParts) {
-                        partIndex++;
-                    }
-                }
-
-                Point p(shapeObject->padfY[j], shapeObject->padfX[j]);
-                polygonData->processPoint(p);
-
-            }
-
-            if(polygonData) {
-                /* Commit it */
-                polygons_.push_back(polygonData);
-            }
-
-            SHPDestroyObject(shapeObject);
-        }
-    }
-
-    SHPClose(shapeHandle);
-
-    std::cout<<"Parsed "<<totalPolygons<<" polygons.\n";
-
-    /* Sort according to bounding box */
-    std::sort(polygons_.begin(), polygons_.end(), [](PolygonData* a, PolygonData* b) {
-        return a->boundingMin.lat_ < b->boundingMin.lat_;
-    });
-
-    /* Encode data section and store pointers */
-    std::vector<uint8_t> outputData;
-    for(PolygonData* polygon: polygons_) {
-        polygon->fileIndex_ = outputData.size();
-        polygon->encodeBinaryData(outputData, precision);
-    }
-    std::cout << "Encoded data section into "<<outputData.size()<<" bytes.\n";
-
-    /* Encode metadata */
-    std::vector<uint8_t> outputMeta;
-    for(MetaData& metadata: metadata_) {
-        metadata.fileIndex_ = outputMeta.size();
-        metadata.encodeBinaryData(outputMeta);
-    }
-    std::cout << "Encoded metadata into "<<outputMeta.size()<<" bytes.\n";
-
-    /* Encode bounding boxes */
-    std::vector<uint8_t> outputBBox;
-    int64_t prevFileIndex = 0;
-    int64_t prevMetaIndex = 0;
-    for(PolygonData* polygon: polygons_) {
-        polygon->boundingMin.encodePointBinary(outputBBox, precision);
-        polygon->boundingMax.encodePointBinary(outputBBox, precision);
-
-        encodeVariableLength(outputBBox, metadata_.at(polygon->metadataId_).fileIndex_ - prevMetaIndex);
-        prevMetaIndex = metadata_[polygon->metadataId_].fileIndex_;
-
-        encodeVariableLength(outputBBox, polygon->fileIndex_ - prevFileIndex, false);
-        prevFileIndex = polygon->fileIndex_;
-    }
-    std::cout << "Encoded bounding box section into "<<outputBBox.size()<<" bytes.\n";
-
-    /* Encode header */
-    std::vector<uint8_t> outputHeader;
-    outputHeader.push_back('P');
-    outputHeader.push_back('L');
-    outputHeader.push_back('B');
-    outputHeader.push_back(tableType);
-    outputHeader.push_back(0);
-    outputHeader.push_back(precision);
-    outputHeader.push_back(fieldNames_.size());
-    for(unsigned int i=0; i<fieldNames_.size(); i++) {
-        encodeStringToBinary(outputHeader, fieldNames_[i]);
-    }
-    encodeStringToBinary(outputHeader, notice);
-    encodeVariableLength(outputHeader, outputBBox.size(), false);
-    encodeVariableLength(outputHeader, outputMeta.size(), false);
-    encodeVariableLength(outputHeader, outputData.size(), false);
-    std::cout << "Encoded header into "<<outputHeader.size()<<" bytes.\n";
-
-    FILE* outputFile = fopen(outPath.c_str(), "wb");
-    fwrite(outputHeader.data(), 1, outputHeader.size(), outputFile);
-    fwrite(outputBBox.data(), 1, outputBBox.size(), outputFile);
-    fwrite(outputMeta.data(), 1, outputMeta.size(), outputFile);
-    fwrite(outputData.data(), 1, outputData.size(), outputFile);
-    fclose(outputFile);
-
-}
diff --git a/scripts/zonedetect/create_timezone_database.sh b/scripts/zonedetect/create_timezone_database.sh
deleted file mode 100755 (executable)
index 9d67bfc..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#! /bin/sh
-
-## @file
-## @brief  This script will generate the timezone database file used to
-## correct exif time and date for UTC offset and Daylight Saving Time.
-##
-## The Preferences/General tab of Geeqie gives the user the option to
-## download the database from a defined location on geeqie.org.
-##
-## If the generated file differs from that on geeqie.org you should
-## upload the new version. You will need write privileges to do this.
-##
-## Refer to https://github.com/BertoldVdb/ZoneDetect for the
-## origin of files builder.cpp and zoneToAlpha.h
-##
-
-timezone_boundary_builder_default_release="2019a"
-
-cd "$(dirname "$0")"
-current_dir=$PWD
-
-xdg-open https://github.com/evansiroky/timezone-boundary-builder/releases/
-
-if [ -f timezone_boundary_builder_release.txt ]
-then
-       timezone_boundary_builder_release=$(cat timezone_boundary_builder_release.txt)
-else
-       timezone_boundary_builder_release=$timezone_boundary_builder_default_release
-fi
-
-timezone_boundary_builder_release=$(zenity --entry --entry-text="$timezone_boundary_builder_release" --title "Geeqie generate timezone database" --text="Which timezone boundary builder\nrelease should be used?\n" --width=350 --window-icon="$current_dir/../../geeqie.png")
-
-if [ -n "$timezone_boundary_builder_release" ]
-then
-       echo "$timezone_boundary_builder_release" > "timezone_boundary_builder_release.txt"
-else
-       exit
-fi
-
-rm -rf naturalearth
-rm -rf timezone
-rm -rf geeqie_org
-rm -f timezone21.bin
-
-g++ builder.cpp -o builder -lshp
-
-mkdir naturalearth
-cd naturalearth
-wget https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_0_countries_lakes.zip
-if [ "$?" -ne 0 ]
-then
-       zenity --error --text="Download of naturalearthdata failed" --title="Generate Geeqie timezone database" --width=300 --window-icon="$current_dir/../../geeqie.png"
-       exit
-fi
-
-unzip ne_10m_admin_0_countries_lakes.zip
-cd ..
-
-mkdir timezone
-cd timezone
-wget "https://github.com/evansiroky/timezone-boundary-builder/releases/download/$timezone_boundary_builder_release/timezones.shapefile.zip"
-if [ "$?" -ne 0 ]
-then
-       zenity --error --text="Download of timezone-boundary-builder failed" --title="Generate Geeqie timezone database" --width=300 --window-icon="$current_dir/../../geeqie.png"
-       exit
-fi
-
-unzip timezones.shapefile.zip
-cd ..
-
-
-./builder T timezone/dist/combined-shapefile timezone21.bin 21 "Contains data from Natural Earth, placed in the Public Domain. Contains information from https://github.com/evansiroky/timezone-boundary-builder, which is made available here under the Open Database License (ODbL)."
-
-mkdir geeqie_org
-cd geeqie_org
-wget http://www.geeqie.org/downloads/timezone21.bin
-if [ "$?" -ne 0 ]
-then
-       zenity --error --text="Download of timezone database from geeqie.org failed" --title="Generate Geeqie timezone database" --width=300 --window-icon="$current_dir/../../geeqie.png"
-       exit
-fi
-cd ..
-
-diff ./geeqie_org/timezone21.bin timezone21.bin
-
-if [ "$?" -ne 0 ]
-then
-       zenity --info --title="Generate Geeqie timezone database" --text="Generated file differs from that on geeqie.org\n\nUpload timezone21.bin to:\ngeeqie.org/downloads/" --width=300 --window-icon="$current_dir/../../geeqie.png"
-else
-       zenity --info --title="Generate Geeqie timezone database" --text="Generated file is the same as on geeqie.org" --width=300 --window-icon="$current_dir/../../geeqie.png"
-       rm timezone21.bin
-fi
-
-rm -f builder
-rm -rf naturalearth
-rm -rf timezone
-rm -rf geeqie_org
diff --git a/scripts/zonedetect/zoneToAlpha.h b/scripts/zonedetect/zoneToAlpha.h
deleted file mode 100644 (file)
index aba55aa..0000000
+++ /dev/null
@@ -1,425 +0,0 @@
-result["Europe/Andorra"] = "AD";
-result["Asia/Dubai"] = "AE";
-result["Asia/Kabul"] = "AF";
-result["America/Antigua"] = "AG";
-result["America/Anguilla"] = "AI";
-result["Europe/Tirane"] = "AL";
-result["Asia/Yerevan"] = "AM";
-result["Africa/Luanda"] = "AO";
-result["Antarctica/McMurdo"] = "AQ";
-result["Antarctica/Casey"] = "AQ";
-result["Antarctica/Davis"] = "AQ";
-result["Antarctica/DumontDUrville"] = "AQ";
-result["Antarctica/Mawson"] = "AQ";
-result["Antarctica/Palmer"] = "AQ";
-result["Antarctica/Rothera"] = "AQ";
-result["Antarctica/Syowa"] = "AQ";
-result["Antarctica/Troll"] = "AQ";
-result["Antarctica/Vostok"] = "AQ";
-result["America/Argentina/Buenos_Aires"] = "AR";
-result["America/Argentina/Cordoba"] = "AR";
-result["America/Argentina/Salta"] = "AR";
-result["America/Argentina/Jujuy"] = "AR";
-result["America/Argentina/Tucuman"] = "AR";
-result["America/Argentina/Catamarca"] = "AR";
-result["America/Argentina/La_Rioja"] = "AR";
-result["America/Argentina/San_Juan"] = "AR";
-result["America/Argentina/Mendoza"] = "AR";
-result["America/Argentina/San_Luis"] = "AR";
-result["America/Argentina/Rio_Gallegos"] = "AR";
-result["America/Argentina/Ushuaia"] = "AR";
-result["Pacific/Pago_Pago"] = "AS";
-result["Europe/Vienna"] = "AT";
-result["Australia/Lord_Howe"] = "AU";
-result["Antarctica/Macquarie"] = "AU";
-result["Australia/Hobart"] = "AU";
-result["Australia/Currie"] = "AU";
-result["Australia/Melbourne"] = "AU";
-result["Australia/Sydney"] = "AU";
-result["Australia/Broken_Hill"] = "AU";
-result["Australia/Brisbane"] = "AU";
-result["Australia/Lindeman"] = "AU";
-result["Australia/Adelaide"] = "AU";
-result["Australia/Darwin"] = "AU";
-result["Australia/Perth"] = "AU";
-result["Australia/Eucla"] = "AU";
-result["America/Aruba"] = "AW";
-result["Europe/Mariehamn"] = "AX";
-result["Asia/Baku"] = "AZ";
-result["Europe/Sarajevo"] = "BA";
-result["America/Barbados"] = "BB";
-result["Asia/Dhaka"] = "BD";
-result["Europe/Brussels"] = "BE";
-result["Africa/Ouagadougou"] = "BF";
-result["Europe/Sofia"] = "BG";
-result["Asia/Bahrain"] = "BH";
-result["Africa/Bujumbura"] = "BI";
-result["Africa/Porto-Novo"] = "BJ";
-result["America/St_Barthelemy"] = "BL";
-result["Atlantic/Bermuda"] = "BM";
-result["Asia/Brunei"] = "BN";
-result["America/La_Paz"] = "BO";
-result["America/Kralendijk"] = "BQ";
-result["America/Noronha"] = "BR";
-result["America/Belem"] = "BR";
-result["America/Fortaleza"] = "BR";
-result["America/Recife"] = "BR";
-result["America/Araguaina"] = "BR";
-result["America/Maceio"] = "BR";
-result["America/Bahia"] = "BR";
-result["America/Sao_Paulo"] = "BR";
-result["America/Campo_Grande"] = "BR";
-result["America/Cuiaba"] = "BR";
-result["America/Santarem"] = "BR";
-result["America/Porto_Velho"] = "BR";
-result["America/Boa_Vista"] = "BR";
-result["America/Manaus"] = "BR";
-result["America/Eirunepe"] = "BR";
-result["America/Rio_Branco"] = "BR";
-result["America/Nassau"] = "BS";
-result["Asia/Thimphu"] = "BT";
-result["Africa/Gaborone"] = "BW";
-result["Europe/Minsk"] = "BY";
-result["America/Belize"] = "BZ";
-result["America/St_Johns"] = "CA";
-result["America/Halifax"] = "CA";
-result["America/Glace_Bay"] = "CA";
-result["America/Moncton"] = "CA";
-result["America/Goose_Bay"] = "CA";
-result["America/Blanc-Sablon"] = "CA";
-result["America/Toronto"] = "CA";
-result["America/Nipigon"] = "CA";
-result["America/Thunder_Bay"] = "CA";
-result["America/Iqaluit"] = "CA";
-result["America/Pangnirtung"] = "CA";
-result["America/Atikokan"] = "CA";
-result["America/Winnipeg"] = "CA";
-result["America/Rainy_River"] = "CA";
-result["America/Resolute"] = "CA";
-result["America/Rankin_Inlet"] = "CA";
-result["America/Regina"] = "CA";
-result["America/Swift_Current"] = "CA";
-result["America/Edmonton"] = "CA";
-result["America/Cambridge_Bay"] = "CA";
-result["America/Yellowknife"] = "CA";
-result["America/Inuvik"] = "CA";
-result["America/Creston"] = "CA";
-result["America/Dawson_Creek"] = "CA";
-result["America/Fort_Nelson"] = "CA";
-result["America/Vancouver"] = "CA";
-result["America/Whitehorse"] = "CA";
-result["America/Dawson"] = "CA";
-result["Indian/Cocos"] = "CC";
-result["Africa/Kinshasa"] = "CD";
-result["Africa/Lubumbashi"] = "CD";
-result["Africa/Bangui"] = "CF";
-result["Africa/Brazzaville"] = "CG";
-result["Europe/Zurich"] = "CH";
-result["Africa/Abidjan"] = "CI";
-result["Pacific/Rarotonga"] = "CK";
-result["America/Santiago"] = "CL";
-result["America/Punta_Arenas"] = "CL";
-result["Pacific/Easter"] = "CL";
-result["Africa/Douala"] = "CM";
-result["Asia/Shanghai"] = "CN";
-result["Asia/Urumqi"] = "CN";
-result["America/Bogota"] = "CO";
-result["America/Costa_Rica"] = "CR";
-result["America/Havana"] = "CU";
-result["Atlantic/Cape_Verde"] = "CV";
-result["America/Curacao"] = "CW";
-result["Indian/Christmas"] = "CX";
-result["Asia/Nicosia"] = "CY";
-result["Asia/Famagusta"] = "CY";
-result["Europe/Prague"] = "CZ";
-result["Europe/Berlin"] = "DE";
-result["Europe/Busingen"] = "DE";
-result["Africa/Djibouti"] = "DJ";
-result["Europe/Copenhagen"] = "DK";
-result["America/Dominica"] = "DM";
-result["America/Santo_Domingo"] = "DO";
-result["Africa/Algiers"] = "DZ";
-result["America/Guayaquil"] = "EC";
-result["Pacific/Galapagos"] = "EC";
-result["Europe/Tallinn"] = "EE";
-result["Africa/Cairo"] = "EG";
-result["Africa/El_Aaiun"] = "EH";
-result["Africa/Asmara"] = "ER";
-result["Europe/Madrid"] = "ES";
-result["Africa/Ceuta"] = "ES";
-result["Atlantic/Canary"] = "ES";
-result["Africa/Addis_Ababa"] = "ET";
-result["Europe/Helsinki"] = "FI";
-result["Pacific/Fiji"] = "FJ";
-result["Atlantic/Stanley"] = "FK";
-result["Pacific/Chuuk"] = "FM";
-result["Pacific/Pohnpei"] = "FM";
-result["Pacific/Kosrae"] = "FM";
-result["Atlantic/Faroe"] = "FO";
-result["Europe/Paris"] = "FR";
-result["Africa/Libreville"] = "GA";
-result["Europe/London"] = "GB";
-result["America/Grenada"] = "GD";
-result["Asia/Tbilisi"] = "GE";
-result["America/Cayenne"] = "GF";
-result["Europe/Guernsey"] = "GG";
-result["Africa/Accra"] = "GH";
-result["Europe/Gibraltar"] = "GI";
-result["America/Godthab"] = "GL";
-result["America/Danmarkshavn"] = "GL";
-result["America/Scoresbysund"] = "GL";
-result["America/Thule"] = "GL";
-result["Africa/Banjul"] = "GM";
-result["Africa/Conakry"] = "GN";
-result["America/Guadeloupe"] = "GP";
-result["Africa/Malabo"] = "GQ";
-result["Europe/Athens"] = "GR";
-result["Atlantic/South_Georgia"] = "GS";
-result["America/Guatemala"] = "GT";
-result["Pacific/Guam"] = "GU";
-result["Africa/Bissau"] = "GW";
-result["America/Guyana"] = "GY";
-result["Asia/Hong_Kong"] = "HK";
-result["America/Tegucigalpa"] = "HN";
-result["Europe/Zagreb"] = "HR";
-result["America/Port-au-Prince"] = "HT";
-result["Europe/Budapest"] = "HU";
-result["Asia/Jakarta"] = "ID";
-result["Asia/Pontianak"] = "ID";
-result["Asia/Makassar"] = "ID";
-result["Asia/Jayapura"] = "ID";
-result["Europe/Dublin"] = "IE";
-result["Asia/Jerusalem"] = "IL";
-result["Europe/Isle_of_Man"] = "IM";
-result["Asia/Kolkata"] = "IN";
-result["Indian/Chagos"] = "IO";
-result["Asia/Baghdad"] = "IQ";
-result["Asia/Tehran"] = "IR";
-result["Atlantic/Reykjavik"] = "IS";
-result["Europe/Rome"] = "IT";
-result["Europe/Jersey"] = "JE";
-result["America/Jamaica"] = "JM";
-result["Asia/Amman"] = "JO";
-result["Asia/Tokyo"] = "JP";
-result["Africa/Nairobi"] = "KE";
-result["Asia/Bishkek"] = "KG";
-result["Asia/Phnom_Penh"] = "KH";
-result["Pacific/Tarawa"] = "KI";
-result["Pacific/Enderbury"] = "KI";
-result["Pacific/Kiritimati"] = "KI";
-result["Indian/Comoro"] = "KM";
-result["America/St_Kitts"] = "KN";
-result["Asia/Pyongyang"] = "KP";
-result["Asia/Seoul"] = "KR";
-result["Asia/Kuwait"] = "KW";
-result["America/Cayman"] = "KY";
-result["Asia/Almaty"] = "KZ";
-result["Asia/Qyzylorda"] = "KZ";
-result["Asia/Aqtobe"] = "KZ";
-result["Asia/Aqtau"] = "KZ";
-result["Asia/Atyrau"] = "KZ";
-result["Asia/Oral"] = "KZ";
-result["Asia/Vientiane"] = "LA";
-result["Asia/Beirut"] = "LB";
-result["America/St_Lucia"] = "LC";
-result["Europe/Vaduz"] = "LI";
-result["Asia/Colombo"] = "LK";
-result["Africa/Monrovia"] = "LR";
-result["Africa/Maseru"] = "LS";
-result["Europe/Vilnius"] = "LT";
-result["Europe/Luxembourg"] = "LU";
-result["Europe/Riga"] = "LV";
-result["Africa/Tripoli"] = "LY";
-result["Africa/Casablanca"] = "MA";
-result["Europe/Monaco"] = "MC";
-result["Europe/Chisinau"] = "MD";
-result["Europe/Podgorica"] = "ME";
-result["America/Marigot"] = "MF";
-result["Indian/Antananarivo"] = "MG";
-result["Pacific/Majuro"] = "MH";
-result["Pacific/Kwajalein"] = "MH";
-result["Europe/Skopje"] = "MK";
-result["Africa/Bamako"] = "ML";
-result["Asia/Yangon"] = "MM";
-result["Asia/Ulaanbaatar"] = "MN";
-result["Asia/Hovd"] = "MN";
-result["Asia/Choibalsan"] = "MN";
-result["Asia/Macau"] = "MO";
-result["Pacific/Saipan"] = "MP";
-result["America/Martinique"] = "MQ";
-result["Africa/Nouakchott"] = "MR";
-result["America/Montserrat"] = "MS";
-result["Europe/Malta"] = "MT";
-result["Indian/Mauritius"] = "MU";
-result["Indian/Maldives"] = "MV";
-result["Africa/Blantyre"] = "MW";
-result["America/Mexico_City"] = "MX";
-result["America/Cancun"] = "MX";
-result["America/Merida"] = "MX";
-result["America/Monterrey"] = "MX";
-result["America/Matamoros"] = "MX";
-result["America/Mazatlan"] = "MX";
-result["America/Chihuahua"] = "MX";
-result["America/Ojinaga"] = "MX";
-result["America/Hermosillo"] = "MX";
-result["America/Tijuana"] = "MX";
-result["America/Bahia_Banderas"] = "MX";
-result["Asia/Kuala_Lumpur"] = "MY";
-result["Asia/Qostanay"] = "KZ";
-result["Asia/Kuching"] = "MY";
-result["Africa/Maputo"] = "MZ";
-result["Africa/Windhoek"] = "NA";
-result["Pacific/Noumea"] = "NC";
-result["Africa/Niamey"] = "NE";
-result["Pacific/Norfolk"] = "NF";
-result["Africa/Lagos"] = "NG";
-result["America/Managua"] = "NI";
-result["Europe/Amsterdam"] = "NL";
-result["Europe/Oslo"] = "NO";
-result["Asia/Kathmandu"] = "NP";
-result["Pacific/Nauru"] = "NR";
-result["Pacific/Niue"] = "NU";
-result["Pacific/Auckland"] = "NZ";
-result["Pacific/Chatham"] = "NZ";
-result["Asia/Muscat"] = "OM";
-result["America/Panama"] = "PA";
-result["America/Lima"] = "PE";
-result["Pacific/Tahiti"] = "PF";
-result["Pacific/Marquesas"] = "PF";
-result["Pacific/Gambier"] = "PF";
-result["Pacific/Port_Moresby"] = "PG";
-result["Pacific/Bougainville"] = "PG";
-result["Asia/Manila"] = "PH";
-result["Asia/Karachi"] = "PK";
-result["Europe/Warsaw"] = "PL";
-result["America/Miquelon"] = "PM";
-result["Pacific/Pitcairn"] = "PN";
-result["America/Puerto_Rico"] = "PR";
-result["Asia/Gaza"] = "PS";
-result["Asia/Hebron"] = "PS";
-result["Europe/Lisbon"] = "PT";
-result["Atlantic/Madeira"] = "PT";
-result["Atlantic/Azores"] = "PT";
-result["Pacific/Palau"] = "PW";
-result["America/Asuncion"] = "PY";
-result["Asia/Qatar"] = "QA";
-result["Indian/Reunion"] = "RE";
-result["Europe/Bucharest"] = "RO";
-result["Europe/Belgrade"] = "RS";
-result["Europe/Kaliningrad"] = "RU";
-result["Europe/Moscow"] = "RU";
-result["Europe/Simferopol"] = "RU";
-result["Europe/Volgograd"] = "RU";
-result["Europe/Kirov"] = "RU";
-result["Europe/Astrakhan"] = "RU";
-result["Europe/Saratov"] = "RU";
-result["Europe/Ulyanovsk"] = "RU";
-result["Europe/Samara"] = "RU";
-result["Asia/Yekaterinburg"] = "RU";
-result["Asia/Omsk"] = "RU";
-result["Asia/Novosibirsk"] = "RU";
-result["Asia/Barnaul"] = "RU";
-result["Asia/Tomsk"] = "RU";
-result["Asia/Novokuznetsk"] = "RU";
-result["Asia/Krasnoyarsk"] = "RU";
-result["Asia/Irkutsk"] = "RU";
-result["Asia/Chita"] = "RU";
-result["Asia/Yakutsk"] = "RU";
-result["Asia/Khandyga"] = "RU";
-result["Asia/Vladivostok"] = "RU";
-result["Asia/Ust-Nera"] = "RU";
-result["Asia/Magadan"] = "RU";
-result["Asia/Sakhalin"] = "RU";
-result["Asia/Srednekolymsk"] = "RU";
-result["Asia/Kamchatka"] = "RU";
-result["Asia/Anadyr"] = "RU";
-result["Africa/Kigali"] = "RW";
-result["Asia/Riyadh"] = "SA";
-result["Pacific/Guadalcanal"] = "SB";
-result["Indian/Mahe"] = "SC";
-result["Africa/Khartoum"] = "SD";
-result["Europe/Stockholm"] = "SE";
-result["Asia/Singapore"] = "SG";
-result["Atlantic/St_Helena"] = "SH";
-result["Europe/Ljubljana"] = "SI";
-result["Arctic/Longyearbyen"] = "SJ";
-result["Europe/Bratislava"] = "SK";
-result["Africa/Freetown"] = "SL";
-result["Europe/San_Marino"] = "SM";
-result["Africa/Dakar"] = "SN";
-result["Africa/Mogadishu"] = "SO";
-result["America/Paramaribo"] = "SR";
-result["Africa/Juba"] = "SS";
-result["Africa/Sao_Tome"] = "ST";
-result["America/El_Salvador"] = "SV";
-result["America/Lower_Princes"] = "SX";
-result["Asia/Damascus"] = "SY";
-result["Africa/Mbabane"] = "SZ";
-result["America/Grand_Turk"] = "TC";
-result["Africa/Ndjamena"] = "TD";
-result["Indian/Kerguelen"] = "TF";
-result["Africa/Lome"] = "TG";
-result["Asia/Bangkok"] = "TH";
-result["Asia/Dushanbe"] = "TJ";
-result["Pacific/Fakaofo"] = "TK";
-result["Asia/Dili"] = "TL";
-result["Asia/Ashgabat"] = "TM";
-result["Africa/Tunis"] = "TN";
-result["Pacific/Tongatapu"] = "TO";
-result["Europe/Istanbul"] = "TR";
-result["America/Port_of_Spain"] = "TT";
-result["Pacific/Funafuti"] = "TV";
-result["Asia/Taipei"] = "TW";
-result["Africa/Dar_es_Salaam"] = "TZ";
-result["Europe/Kiev"] = "UA";
-result["Europe/Uzhgorod"] = "UA";
-result["Europe/Zaporozhye"] = "UA";
-result["Africa/Kampala"] = "UG";
-result["Pacific/Midway"] = "UM";
-result["Pacific/Wake"] = "UM";
-result["America/New_York"] = "US";
-result["America/Detroit"] = "US";
-result["America/Kentucky/Louisville"] = "US";
-result["America/Kentucky/Monticello"] = "US";
-result["America/Indiana/Indianapolis"] = "US";
-result["America/Indiana/Vincennes"] = "US";
-result["America/Indiana/Winamac"] = "US";
-result["America/Indiana/Marengo"] = "US";
-result["America/Indiana/Petersburg"] = "US";
-result["America/Indiana/Vevay"] = "US";
-result["America/Chicago"] = "US";
-result["America/Indiana/Tell_City"] = "US";
-result["America/Indiana/Knox"] = "US";
-result["America/Menominee"] = "US";
-result["America/North_Dakota/Center"] = "US";
-result["America/North_Dakota/New_Salem"] = "US";
-result["America/North_Dakota/Beulah"] = "US";
-result["America/Denver"] = "US";
-result["America/Boise"] = "US";
-result["America/Phoenix"] = "US";
-result["America/Los_Angeles"] = "US";
-result["America/Anchorage"] = "US";
-result["America/Juneau"] = "US";
-result["America/Sitka"] = "US";
-result["America/Metlakatla"] = "US";
-result["America/Yakutat"] = "US";
-result["America/Nome"] = "US";
-result["America/Adak"] = "US";
-result["Pacific/Honolulu"] = "US";
-result["America/Montevideo"] = "UY";
-result["Asia/Samarkand"] = "UZ";
-result["Asia/Tashkent"] = "UZ";
-result["Europe/Vatican"] = "VA";
-result["America/St_Vincent"] = "VC";
-result["America/Caracas"] = "VE";
-result["America/Tortola"] = "VG";
-result["America/St_Thomas"] = "VI";
-result["Asia/Ho_Chi_Minh"] = "VN";
-result["Pacific/Efate"] = "VU";
-result["Pacific/Wallis"] = "WF";
-result["Pacific/Apia"] = "WS";
-result["Asia/Aden"] = "YE";
-result["Indian/Mayotte"] = "YT";
-result["Africa/Johannesburg"] = "ZA";
-result["Africa/Lusaka"] = "ZM";
-result["Africa/Harare"] = "ZW";
index 833a86c..ecd64f6 100644 (file)
@@ -660,6 +660,11 @@ static void zd_tz(ZoneDetectResult *results, gchar **timezone, gchar **countryna
        g_free(timezone_id);
 }
 
+void ZoneDetect_onError(int errZD, int errNative)
+{
+       log_printf("Error: ZoneDetect %s (0x%08X)\n", ZDGetErrorString(errZD), (unsigned)errNative);
+}
+
 /**
  * @brief Gets timezone data from an exif structure
  * @param[in] exif
@@ -689,8 +694,6 @@ static gboolean exif_build_tz_data(ExifData *exif, gchar **exif_date_time, gchar
        ZoneDetect *cd;
        ZoneDetectResult *results;
        gboolean ret = FALSE;
-       gchar *basename;
-       gchar *path;
 
        text_latitude = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLatitude");
        text_longitude = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLongitude");
@@ -724,11 +727,10 @@ static gboolean exif_build_tz_data(ExifData *exif, gchar **exif_date_time, gchar
                        longitude = -longitude;
                        }
 
-               path = path_from_utf8(TIMEZONE_DATABASE);
-               basename = g_path_get_basename(path);
-               timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
+               timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
                if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
                        {
+                       ZDSetErrorHandler(ZoneDetect_onError);
                        cd = ZDOpenDatabase(timezone_path);
                        if (cd)
                                {
@@ -745,9 +747,7 @@ static gboolean exif_build_tz_data(ExifData *exif, gchar **exif_date_time, gchar
                                }
                        ZDCloseDatabase(cd);
                        }
-               g_free(path);
                g_free(timezone_path);
-               g_free(basename);
                }
 
        if (ret && text_date && text_time)
index 426017c..25729c6 100644 (file)
 #include "debug.h"
 #include "options.h"
 
-#define TIMEZONE_DATABASE GQ_WEBSITE"downloads/timezone21.bin"
-
+#define TIMEZONE_DATABASE_WEB "https://cdn.bertold.org/zonedetect/db/db.zip"
+#define TIMEZONE_DATABASE_FILE "timezone21.bin"
+#define TIMEZONE_DATABASE_VERSION "out_v1"
 #define HELP_SEARCH_ENGINE "https://duckduckgo.com/?q=site:geeqie.org/help "
 
 #define STAR_RATING_NOT_READ -12345
index dc26b82..7b135fe 100644 (file)
@@ -1992,6 +1992,7 @@ static void config_tab_general(GtkWidget *notebook)
        gchar *rating_symbol;
        gchar *path;
        gchar *basename;
+       gchar *download_locn;
        GNetworkMonitor *net_mon;
        GSocketConnectable *geeqie_org;
        gboolean internet_available;
@@ -2198,9 +2199,9 @@ static void config_tab_general(GtkWidget *notebook)
 
        tz = g_new0(TZData, 1);
 
-       path = path_from_utf8(TIMEZONE_DATABASE);
+       path = path_from_utf8(TIMEZONE_DATABASE_WEB);
        basename = g_path_get_basename(path);
-       tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
+       tz->timezone_database_user = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
        g_free(path);
        g_free(basename);
 
@@ -2213,6 +2214,10 @@ static void config_tab_general(GtkWidget *notebook)
                button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
                }
 
+       download_locn = g_strconcat(_("Download database from: "), TIMEZONE_DATABASE_WEB, NULL);
+       pref_label_new(GTK_WIDGET(hbox), download_locn);
+       g_free(download_locn);
+
        if (!internet_available)
                {
                gtk_widget_set_tooltip_text(button, _("No Internet connection!\nThe timezone database is used to display exif time and date\ncorrected for UTC offset and Daylight Saving Time"));
@@ -4068,7 +4073,6 @@ void show_about_window(LayoutWindow *lw)
        gchar *path;
        GString *copyright;
        gchar *timezone_path;
-       gchar *basename;
        ZoneDetect *cd;
        FILE *fp = NULL;
 #define LINE_LENGTH 1000
@@ -4077,21 +4081,21 @@ void show_about_window(LayoutWindow *lw)
        copyright = g_string_new(NULL);
        copyright = g_string_append(copyright, "This program comes with absolutely no warranty.\nGNU General Public License, version 2 or later.\nSee https://www.gnu.org/licenses/old-licenses/gpl-2.0.html\n\n");
 
-       path = path_from_utf8(TIMEZONE_DATABASE);
-       basename = g_path_get_basename(path);
-       timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
+       timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
        if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
                {
                cd = ZDOpenDatabase(timezone_path);
                if (cd)
                        {
                        copyright = g_string_append(copyright, ZDGetNotice(cd));
-                       ZDCloseDatabase(cd);
                        }
+               else
+                       {
+                       log_printf("Error: Init of timezone database %s failed\n", timezone_path);
+                       }
+               ZDCloseDatabase(cd);
                }
-       g_free(path);
        g_free(timezone_path);
-       g_free(basename);
 
        authors[0] = NULL;
        path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
@@ -4167,6 +4171,9 @@ static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, g
        GError *error = NULL;
        TZData *tz = data;
        gchar *tmp_filename;
+       gchar *timezone_bin;
+       gchar *tmp_dir = NULL;
+       FileData *fd;
 
        if (!g_cancellable_is_cancelled(tz->cancellable))
                {
@@ -4176,13 +4183,35 @@ static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, g
 
        if (g_file_copy_finish(G_FILE(source_object), res, &error))
                {
-               tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
-               move_file(tmp_filename, tz->timezone_database_user);
+               tmp_filename = g_file_get_path(tz->tmp_g_file);
+               fd = file_data_new_simple(tmp_filename);
+               tmp_dir = open_archive(fd);
+
+               if (tmp_dir)
+                       {
+                       timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
+                       if (isfile(timezone_bin))
+                               {
+                               move_file(timezone_bin, tz->timezone_database_user);
+                               }
+                       else
+                               {
+                               warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
+                               }
+
+                       g_free(timezone_bin);
+                       g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
+                       }
+               else
+                       {
+                       warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
+                       }
                g_free(tmp_filename);
+               file_data_unref(fd);
                }
        else
                {
-               file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
+               file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
                }
 
        g_file_delete(tz->tmp_g_file, NULL, &error);
@@ -4231,7 +4260,7 @@ static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
                }
        else
                {
-               tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
+               tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
 
                tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
 
index 47fe37b..9265c62 100644 (file)
@@ -34,7 +34,7 @@
 #include <math.h>
 #if defined(_MSC_VER) || defined(__MINGW32__)
 #include <windows.h>
-#else
+#elif defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION)
 #include <errno.h>
 #include <sys/mman.h>
 #include <fcntl.h>
@@ -64,9 +64,11 @@ struct ZoneDetectOpaque {
     HANDLE fdMap;
     int32_t length;
     int32_t padding;
-#else
+#elif defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION)
     int fd;
     off_t length;
+#else
+    int length;
 #endif
 
     uint8_t closeType;
@@ -232,7 +234,8 @@ static char *ZDParseString(const ZoneDetect *library, uint32_t *index)
 #if defined(_MSC_VER)
         __try {
 #endif
-            for(size_t i = 0; i < strLength; i++) {
+            size_t i;
+            for(i = 0; i < strLength; i++) {
                 str[i] = (char)(library->mapping[strOffset + i] ^ UINT8_C(0x80));
             }
 #if defined(_MSC_VER)
@@ -286,7 +289,12 @@ static int ZDParseHeader(ZoneDetect *library)
     uint32_t index = UINT32_C(7);
 
     library->fieldNames = malloc(library->numFields * sizeof *library->fieldNames);
-    for(size_t i = 0; i < library->numFields; i++) {
+    if (!library->fieldNames) {
+        return -1;
+    }
+
+    size_t i;
+    for(i = 0; i < library->numFields; i++) {
         library->fieldNames[i] = ZDParseString(library, &index);
     }
 
@@ -333,12 +341,12 @@ static int ZDPointInBox(int32_t xl, int32_t x, int32_t xr, int32_t yl, int32_t y
 
 static uint32_t ZDUnshuffle(uint64_t w)
 {
-    w &=                  0x5555555555555555;
-    w = (w | (w >> 1))  & 0x3333333333333333;
-    w = (w | (w >> 2))  & 0x0F0F0F0F0F0F0F0F;
-    w = (w | (w >> 4))  & 0x00FF00FF00FF00FF;
-    w = (w | (w >> 8))  & 0x0000FFFF0000FFFF;
-    w = (w | (w >> 16)) & 0x00000000FFFFFFFF;
+    w &=                  0x5555555555555555llu;
+    w = (w | (w >> 1))  & 0x3333333333333333llu;
+    w = (w | (w >> 2))  & 0x0F0F0F0F0F0F0F0Fllu;
+    w = (w | (w >> 4))  & 0x00FF00FF00FF00FFllu;
+    w = (w | (w >> 8))  & 0x0000FFFF0000FFFFllu;
+    w = (w | (w >> 16)) & 0x00000000FFFFFFFFllu;
     return (uint32_t)w;
 }
 
@@ -602,7 +610,8 @@ float* ZDPolygonToList(const ZoneDetect *library, uint32_t polygonId, size_t* le
         goto fail;
     }
 
-    for(size_t i = 0; i<length; i+= 2) {
+    size_t i;
+    for(i = 0; i<length; i+= 2) {
         int32_t lat = data[i];
         int32_t lon = data[i+1];
 
@@ -777,7 +786,8 @@ void ZDCloseDatabase(ZoneDetect *library)
 {
     if(library) {
         if(library->fieldNames) {
-            for(size_t i = 0; i < (size_t)library->numFields; i++) {
+            size_t i;
+            for(i = 0; i < (size_t)library->numFields; i++) {
                 if(library->fieldNames[i]) {
                     free(library->fieldNames[i]);
                 }
@@ -793,9 +803,9 @@ void ZDCloseDatabase(ZoneDetect *library)
             if(library->mapping && !UnmapViewOfFile(library->mapping)) zdError(ZD_E_DB_MUNMAP_MSVIEW, (int)GetLastError());
             if(library->fdMap && !CloseHandle(library->fdMap))         zdError(ZD_E_DB_MUNMAP, (int)GetLastError());
             if(library->fd && !CloseHandle(library->fd))               zdError(ZD_E_DB_CLOSE, (int)GetLastError());
-#else
-            if(library->mapping && munmap(library->mapping, (size_t)(library->length))) zdError(ZD_E_DB_MUNMAP, errno);
-            if(library->fd >= 0 && close(library->fd))                                  zdError(ZD_E_DB_CLOSE, errno);
+#elif defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION)
+            if(library->mapping && munmap(library->mapping, (size_t)(library->length))) zdError(ZD_E_DB_MUNMAP, 0);
+            if(library->fd >= 0 && close(library->fd))                                  zdError(ZD_E_DB_CLOSE, 0);
 #endif
         }
 
@@ -813,7 +823,11 @@ ZoneDetect *ZDOpenDatabaseFromMemory(void* buffer, size_t length)
         library->length = (long int)length;
 
         if(library->length <= 0) {
+#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION)
             zdError(ZD_E_DB_SEEK, errno);
+#else
+            zdError(ZD_E_DB_SEEK, 0);
+#endif
             goto fail;
         }
 
@@ -865,7 +879,7 @@ ZoneDetect *ZDOpenDatabase(const char *path)
             zdError(ZD_E_DB_MMAP_MSVIEW, (int)GetLastError());
             goto fail;
         }
-#else
+#elif defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION)
         library->fd = open(path, O_RDONLY | O_CLOEXEC);
         if(library->fd < 0) {
             zdError(ZD_E_DB_OPEN, errno);
@@ -966,10 +980,12 @@ ZoneDetectResult *ZDLookup(const ZoneDetect *library, float lat, float lon, floa
     }
 
     /* Clean up results */
-    for(size_t i = 0; i < numResults; i++) {
+    size_t i;
+    for(i = 0; i < numResults; i++) {
         int insideSum = 0;
         ZDLookupResult overrideResult = ZD_LOOKUP_IGNORE;
-        for(size_t j = i; j < numResults; j++) {
+        size_t j;
+        for(j = i; j < numResults; j++) {
             if(results[i].metaId == results[j].metaId) {
                 ZDLookupResult tmpResult = results[j].lookupResult;
                 results[j].lookupResult = ZD_LOOKUP_IGNORE;
@@ -998,7 +1014,7 @@ ZoneDetectResult *ZDLookup(const ZoneDetect *library, float lat, float lon, floa
 
     /* Remove zones to ignore */
     size_t newNumResults = 0;
-    for(size_t i = 0; i < numResults; i++) {
+    for(i = 0; i < numResults; i++) {
         if(results[i].lookupResult != ZD_LOOKUP_IGNORE) {
             results[newNumResults] = results[i];
             newNumResults++;
@@ -1007,13 +1023,54 @@ ZoneDetectResult *ZDLookup(const ZoneDetect *library, float lat, float lon, floa
     numResults = newNumResults;
 
     /* Lookup metadata */
-    for(size_t i = 0; i < numResults; i++) {
+    for(i = 0; i < numResults; i++) {
         uint32_t tmpIndex = library->metadataOffset + results[i].metaId;
         results[i].data = malloc(library->numFields * sizeof *results[i].data);
         if(results[i].data) {
-            for(size_t j = 0; j < library->numFields; j++) {
+            size_t j;
+            for(j = 0; j < library->numFields; j++) {
                 results[i].data[j] = ZDParseString(library, &tmpIndex);
+                if (!results[i].data[j]) {
+                    /* free all allocated memory */
+                    size_t m;
+                    for(m = 0; m < j; m++) {
+                        if(results[i].data[m]) {
+                            free(results[i].data[m]);
+                        }
+                    }
+                    size_t k;
+                    for(k = 0; k < i; k++) {
+                        size_t l;
+                        for(l = 0; l < (size_t)results[k].numFields; l++) {
+                            if(results[k].data[l]) {
+                                free(results[k].data[l]);
+                            }
+                        }
+                        if (results[k].data) {
+                            free(results[k].data);
+                        }
+                    }
+                    free(results);
+                    return NULL;
+                }
+            }
+        }
+        else {
+            /* free all allocated memory */
+            size_t k;
+            for(k = 0; k < i; k++) {
+                size_t l;
+                for(l = 0; l < (size_t)results[k].numFields; l++) {
+                    if(results[k].data[l]) {
+                        free(results[k].data[l]);
+                    }
+                }
+                if (results[k].data) {
+                    free(results[k].data);
+                }
             }
+            free(results);
+            return NULL;
         }
     }
 
@@ -1040,7 +1097,8 @@ void ZDFreeResults(ZoneDetectResult *results)
 
     while(results[index].lookupResult != ZD_LOOKUP_END) {
         if(results[index].data) {
-            for(size_t i = 0; i < (size_t)results[index].numFields; i++) {
+            size_t i;
+            for(i = 0; i < (size_t)results[index].numFields; i++) {
                 if(results[index].data[i]) {
                     free(results[index].data[i]);
                 }
@@ -1141,7 +1199,8 @@ char* ZDHelperSimpleLookupString(const ZoneDetect* library, float lat, float lon
 
     char* strings[2] = {NULL};
 
-    for(unsigned int i = 0; i < result[0].numFields; i++) {
+    unsigned int i;
+    for(i = 0; i < result[0].numFields; i++) {
         if(result[0].fieldNames[i] && result[0].data[i]) {
             if(library->tableType == 'T') {
                 if(!strcmp(result[0].fieldNames[i], "TimezoneIdPrefix")) {
@@ -1160,7 +1219,7 @@ char* ZDHelperSimpleLookupString(const ZoneDetect* library, float lat, float lon
     }
 
     size_t length = 0;
-    for(unsigned int i=0; i<sizeof(strings)/sizeof(char*); i++) {
+    for(i=0; i<sizeof(strings)/sizeof(char*); i++) {
         if(strings[i]) {
             size_t partLength = strlen(strings[i]);
             if(partLength > 512) {
@@ -1177,10 +1236,12 @@ char* ZDHelperSimpleLookupString(const ZoneDetect* library, float lat, float lon
     length += 1;
 
     output = (char*)malloc(length);
-    output[0] = 0;
-    for(unsigned int i=0; i<sizeof(strings)/sizeof(char*); i++) {
-        if(strings[i]) {
-            strcat(output + strlen(output), strings[i]);
+    if(output) {
+        output[0] = 0;
+        for(i=0; i<sizeof(strings)/sizeof(char*); i++) {
+            if(strings[i]) {
+                strcat(output + strlen(output), strings[i]);
+            }
         }
     }