./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
"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"
)
+++ /dev/null
-/*
- * 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);
-
-}
+++ /dev/null
-#! /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
+++ /dev/null
-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";
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
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");
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)
{
}
ZDCloseDatabase(cd);
}
- g_free(path);
g_free(timezone_path);
- g_free(basename);
}
if (ret && text_date && text_time)
#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
gchar *rating_symbol;
gchar *path;
gchar *basename;
+ gchar *download_locn;
GNetworkMonitor *net_mon;
GSocketConnectable *geeqie_org;
gboolean internet_available;
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);
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"));
gchar *path;
GString *copyright;
gchar *timezone_path;
- gchar *basename;
ZoneDetect *cd;
FILE *fp = NULL;
#define LINE_LENGTH 1000
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);
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))
{
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);
}
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);
#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>
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;
#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)
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);
}
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;
}
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];
{
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]);
}
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
}
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;
}
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);
}
/* 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;
/* 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++;
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;
}
}
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]);
}
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")) {
}
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) {
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]);
+ }
}
}