From 2272ba8f6a77903203632111a44b44e544fe332b Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 20 Feb 2019 15:03:55 +0100 Subject: projinfo: advertize the use of '--spatial-test intersects' when it can bring more results --- src/apps/projinfo.cpp | 106 +++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 40 deletions(-) (limited to 'src/apps') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 9f908c8a..9472d99e 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -136,11 +136,11 @@ static std::string c_ify_string(const std::string &str) { // --------------------------------------------------------------------------- -static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext, - const std::string &user_string, - bool kindIsCRS, const std::string &context, - bool buildBoundCRSToWGS84, CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, - bool quiet) { +static BaseObjectNNPtr buildObject( + DatabaseContextPtr dbContext, const std::string &user_string, + bool kindIsCRS, const std::string &context, bool buildBoundCRSToWGS84, + CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, + bool quiet) { BaseObjectPtr obj; std::string l_user_string(user_string); @@ -213,7 +213,8 @@ static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext, if (buildBoundCRSToWGS84) { auto crs = std::dynamic_pointer_cast(obj); if (crs) { - obj = crs->createBoundCRSToWGS84IfPossible(dbContext, allowUseIntermediateCRS) + obj = crs->createBoundCRSToWGS84IfPossible(dbContext, + allowUseIntermediateCRS) .as_nullable(); } } @@ -223,8 +224,10 @@ static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext, // --------------------------------------------------------------------------- -static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj, - CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, const OutputOptions &outputOpt) { +static void outputObject( + DatabaseContextPtr dbContext, BaseObjectNNPtr obj, + CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, + const OutputOptions &outputOpt) { auto identified = dynamic_cast(obj.get()); if (!outputOpt.quiet && identified && identified->isDeprecated()) { @@ -260,7 +263,7 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj, } auto crs = nn_dynamic_pointer_cast(obj); if (!outputOpt.quiet) { - if( crs ) { + if (crs) { std::cout << "PROJ.4 string:" << std::endl; } else { std::cout << "PROJ string:" << std::endl; @@ -271,8 +274,8 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj, if (crs) { objToExport = nn_dynamic_pointer_cast( - crs->createBoundCRSToWGS84IfPossible(dbContext, - allowUseIntermediateCRS)); + crs->createBoundCRSToWGS84IfPossible( + dbContext, allowUseIntermediateCRS)); } if (!objToExport) { objToExport = projStringExportable; @@ -411,8 +414,8 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj, std::shared_ptr objToExport; if (crs) { objToExport = nn_dynamic_pointer_cast( - crs->createBoundCRSToWGS84IfPossible(dbContext, - allowUseIntermediateCRS)); + crs->createBoundCRSToWGS84IfPossible( + dbContext, allowUseIntermediateCRS)); } if (!objToExport) { objToExport = wktExportable; @@ -514,26 +517,25 @@ static void outputOperations( DatabaseContextPtr dbContext, const std::string &sourceCRSStr, const std::string &targetCRSStr, const ExtentPtr &bboxFilter, CoordinateOperationContext::SpatialCriterion spatialCriterion, + bool spatialCriterionExplictlySpecified, CoordinateOperationContext::SourceTargetCRSExtentUse crsExtentUse, CoordinateOperationContext::GridAvailabilityUse gridAvailabilityUse, CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, const std::vector> &pivots, const std::string &authority, bool usePROJGridAlternatives, bool showSuperseded, const OutputOptions &outputOpt, bool summary) { - auto sourceObj = buildObject(dbContext, sourceCRSStr, true, "source CRS", - false, - CoordinateOperationContext::IntermediateCRSUse::NEVER, - outputOpt.quiet); + auto sourceObj = buildObject( + dbContext, sourceCRSStr, true, "source CRS", false, + CoordinateOperationContext::IntermediateCRSUse::NEVER, outputOpt.quiet); auto sourceCRS = nn_dynamic_pointer_cast(sourceObj); if (!sourceCRS) { std::cerr << "source CRS string is not a CRS" << std::endl; std::exit(1); } - auto targetObj = buildObject(dbContext, targetCRSStr, true, "target CRS", - false, - CoordinateOperationContext::IntermediateCRSUse::NEVER, - outputOpt.quiet); + auto targetObj = buildObject( + dbContext, targetCRSStr, true, "target CRS", false, + CoordinateOperationContext::IntermediateCRSUse::NEVER, outputOpt.quiet); auto targetCRS = nn_dynamic_pointer_cast(targetObj); if (!targetCRS) { std::cerr << "target CRS string is not a CRS" << std::endl; @@ -541,6 +543,7 @@ static void outputOperations( } std::vector list; + size_t spatialCriterionPartialIntersectionResultCount = 0; try { auto authFactory = dbContext @@ -558,6 +561,21 @@ static void outputOperations( ctxt->setDiscardSuperseded(!showSuperseded); list = CoordinateOperationFactory::create()->createOperations( NN_NO_CHECK(sourceCRS), NN_NO_CHECK(targetCRS), ctxt); + if (!spatialCriterionExplictlySpecified && + spatialCriterion == CoordinateOperationContext::SpatialCriterion:: + STRICT_CONTAINMENT) { + try { + ctxt->setSpatialCriterion( + CoordinateOperationContext::SpatialCriterion:: + PARTIAL_INTERSECTION); + spatialCriterionPartialIntersectionResultCount = + CoordinateOperationFactory::create() + ->createOperations(NN_NO_CHECK(sourceCRS), + NN_NO_CHECK(targetCRS), ctxt) + .size(); + } catch (const std::exception &) { + } + } } catch (const std::exception &e) { std::cerr << "createOperations() failed with: " << e.what() << std::endl; @@ -567,8 +585,14 @@ static void outputOperations( outputObject(dbContext, list[0], allowUseIntermediateCRS, outputOpt); return; } + std::cout << "Candidate operations found: " << list.size() << std::endl; + if (spatialCriterionPartialIntersectionResultCount > list.size()) { + std::cout << "Note: using '--spatial-test intersects' would bring " + "more results (" + << spatialCriterionPartialIntersectionResultCount << ")" + << std::endl; + } if (summary) { - std::cout << "Candidate operations found: " << list.size() << std::endl; for (const auto &op : list) { outputOperationSummary(op); } @@ -576,18 +600,15 @@ static void outputOperations( bool first = true; for (size_t i = 0; i < list.size(); ++i) { const auto &op = list[i]; - if (list.size() > 1) { - if (!first) { - std::cout << std::endl; - } - first = false; - std::cout << "-------------------------------------" - << std::endl; - std::cout << "Operation n" - "\xC2\xB0" - << (i + 1) << ":" << std::endl - << std::endl; + if (!first) { + std::cout << std::endl; } + first = false; + std::cout << "-------------------------------------" << std::endl; + std::cout << "Operation n" + "\xC2\xB0" + << (i + 1) << ":" << std::endl + << std::endl; outputOperationSummary(op); std::cout << std::endl; outputObject(dbContext, op, allowUseIntermediateCRS, outputOpt); @@ -614,6 +635,7 @@ int main(int argc, char **argv) { bool summary = false; ExtentPtr bboxFilter = nullptr; std::string area; + bool spatialCriterionExplictlySpecified = false; CoordinateOperationContext::SpatialCriterion spatialCriterion = CoordinateOperationContext::SpatialCriterion::STRICT_CONTAINMENT; CoordinateOperationContext::SourceTargetCRSExtentUse crsExtentUse = @@ -622,7 +644,8 @@ int main(int argc, char **argv) { CoordinateOperationContext::GridAvailabilityUse gridAvailabilityUse = CoordinateOperationContext::GridAvailabilityUse::USE_FOR_SORTING; CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS = - CoordinateOperationContext::IntermediateCRSUse::IF_NO_DIRECT_TRANSFORMATION; + CoordinateOperationContext::IntermediateCRSUse:: + IF_NO_DIRECT_TRANSFORMATION; std::vector> pivots; bool usePROJGridAlternatives = true; std::string mainDBPath; @@ -768,6 +791,7 @@ int main(int argc, char **argv) { } else if (arg == "--spatial-test" && i + 1 < argc) { i++; std::string value(argv[i]); + spatialCriterionExplictlySpecified = true; if (ci_equal(value, "contains")) { spatialCriterion = CoordinateOperationContext:: SpatialCriterion::STRICT_CONTAINMENT; @@ -822,9 +846,10 @@ int main(int argc, char **argv) { if (ci_equal(std::string(value), "always")) { allowUseIntermediateCRS = CoordinateOperationContext::IntermediateCRSUse::ALWAYS; - } else if (ci_equal(std::string(value), "if_no_direct_transformation")) { - allowUseIntermediateCRS = - CoordinateOperationContext::IntermediateCRSUse::IF_NO_DIRECT_TRANSFORMATION; + } else if (ci_equal(std::string(value), + "if_no_direct_transformation")) { + allowUseIntermediateCRS = CoordinateOperationContext:: + IntermediateCRSUse::IF_NO_DIRECT_TRANSFORMATION; } else if (ci_equal(std::string(value), "never")) { allowUseIntermediateCRS = CoordinateOperationContext::IntermediateCRSUse::NEVER; @@ -918,8 +943,8 @@ int main(int argc, char **argv) { } if (outputOpt.quiet && - (outputOpt.PROJ5 + outputOpt.WKT2_2018 + - outputOpt.WKT2_2015 + outputOpt.WKT1_GDAL) != 1) { + (outputOpt.PROJ5 + outputOpt.WKT2_2018 + outputOpt.WKT2_2015 + + outputOpt.WKT1_GDAL) != 1) { std::cerr << "-q can only be used with a single output format" << std::endl; usage(); @@ -1055,7 +1080,8 @@ int main(int argc, char **argv) { outputOperations( dbContext, sourceCRSStr, targetCRSStr, bboxFilter, spatialCriterion, - crsExtentUse, gridAvailabilityUse, allowUseIntermediateCRS, pivots, authority, + spatialCriterionExplictlySpecified, crsExtentUse, + gridAvailabilityUse, allowUseIntermediateCRS, pivots, authority, usePROJGridAlternatives, showSuperseded, outputOpt, summary); } -- cgit v1.2.3 From 94578ea8ff38f4bc6b1f6f52b80ecf7359f5dfc2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 20 Feb 2019 18:04:35 +0100 Subject: CoordinateOperation: add a hasBallparkTransformation() method that can be used to know if it includes a very approximative transformation term --- src/apps/projinfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/apps') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 9472d99e..55a8d622 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -508,6 +508,10 @@ static void outputOperationSummary(const CoordinateOperationNNPtr &op) { std::cout << "unknown domain of validity"; } + if (op->hasBallparkTransformation()) { + std::cout << ", has ballpark transformation"; + } + std::cout << std::endl; } -- cgit v1.2.3 From 69ef7449f5f26453a8b6cab1ba02cb870055615f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 20 Feb 2019 20:42:26 +0100 Subject: typo fixes: s/Explictly/Explicitly/ and s/instanciat/instantiat/ --- src/apps/cs2cs.cpp | 8 ++++---- src/apps/projinfo.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/apps') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 150548c5..dafd06f8 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -206,10 +206,10 @@ static void process(FILE *fid) } /************************************************************************/ -/* instanciate_crs() */ +/* instantiate_crs() */ /************************************************************************/ -static PJ *instanciate_crs(const std::string &definition, +static PJ *instantiate_crs(const std::string &definition, bool &isGeog, double &toRadians, bool &isLatFirst) { PJ *crs = proj_create(nullptr, @@ -541,7 +541,7 @@ int main(int argc, char **argv) { PJ *src = nullptr; if (!fromStr.empty()) { bool ignored; - src = instanciate_crs(fromStr, srcIsGeog, + src = instantiate_crs(fromStr, srcIsGeog, srcToRadians, ignored); if (!src) { emess(3, "cannot instantiate source coordinate system"); @@ -550,7 +550,7 @@ int main(int argc, char **argv) { PJ *dst = nullptr; if (!toStr.empty()) { - dst = instanciate_crs(toStr, destIsGeog, + dst = instantiate_crs(toStr, destIsGeog, destToRadians, destIsLatLong); if (!dst) { emess(3, "cannot instantiate target coordinate system"); diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 55a8d622..094587e2 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -521,7 +521,7 @@ static void outputOperations( DatabaseContextPtr dbContext, const std::string &sourceCRSStr, const std::string &targetCRSStr, const ExtentPtr &bboxFilter, CoordinateOperationContext::SpatialCriterion spatialCriterion, - bool spatialCriterionExplictlySpecified, + bool spatialCriterionExplicitlySpecified, CoordinateOperationContext::SourceTargetCRSExtentUse crsExtentUse, CoordinateOperationContext::GridAvailabilityUse gridAvailabilityUse, CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, @@ -565,7 +565,7 @@ static void outputOperations( ctxt->setDiscardSuperseded(!showSuperseded); list = CoordinateOperationFactory::create()->createOperations( NN_NO_CHECK(sourceCRS), NN_NO_CHECK(targetCRS), ctxt); - if (!spatialCriterionExplictlySpecified && + if (!spatialCriterionExplicitlySpecified && spatialCriterion == CoordinateOperationContext::SpatialCriterion:: STRICT_CONTAINMENT) { try { @@ -639,7 +639,7 @@ int main(int argc, char **argv) { bool summary = false; ExtentPtr bboxFilter = nullptr; std::string area; - bool spatialCriterionExplictlySpecified = false; + bool spatialCriterionExplicitlySpecified = false; CoordinateOperationContext::SpatialCriterion spatialCriterion = CoordinateOperationContext::SpatialCriterion::STRICT_CONTAINMENT; CoordinateOperationContext::SourceTargetCRSExtentUse crsExtentUse = @@ -795,7 +795,7 @@ int main(int argc, char **argv) { } else if (arg == "--spatial-test" && i + 1 < argc) { i++; std::string value(argv[i]); - spatialCriterionExplictlySpecified = true; + spatialCriterionExplicitlySpecified = true; if (ci_equal(value, "contains")) { spatialCriterion = CoordinateOperationContext:: SpatialCriterion::STRICT_CONTAINMENT; @@ -1084,7 +1084,7 @@ int main(int argc, char **argv) { outputOperations( dbContext, sourceCRSStr, targetCRSStr, bboxFilter, spatialCriterion, - spatialCriterionExplictlySpecified, crsExtentUse, + spatialCriterionExplicitlySpecified, crsExtentUse, gridAvailabilityUse, allowUseIntermediateCRS, pivots, authority, usePROJGridAlternatives, showSuperseded, outputOpt, summary); } -- cgit v1.2.3 From 5c691e7fec7c244b1a1a6b5ef97df2cf69e403df Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 21 Feb 2019 01:04:55 +0100 Subject: projinfo: add information about missing grids --- src/apps/projinfo.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) (limited to 'src/apps') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 094587e2..7e401887 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -464,11 +464,42 @@ static void outputObject( } } } + + auto op = dynamic_cast(obj.get()); + if (op && dbContext && getenv("PROJINFO_NO_GRID_CHECK") == nullptr) { + try { + auto setGrids = op->gridsNeeded(dbContext); + bool firstWarning = true; + for (const auto &grid : setGrids) { + if (!grid.available) { + if (firstWarning) { + std::cout << std::endl; + firstWarning = false; + } + std::cout << "Grid " << grid.shortName + << " needed but not found on the system."; + if (!grid.packageName.empty()) { + std::cout << " Can be obtained from the " + << grid.packageName << " package"; + if (!grid.url.empty()) { + std::cout << " at " << grid.url; + } + } else if (!grid.url.empty()) { + std::cout << " Can be obtained at " << grid.url; + } + std::cout << std::endl; + } + } + } catch (const std::exception &e) { + std::cerr << "Error in gridsNeeded(): " << e.what() << std::endl; + } + } } // --------------------------------------------------------------------------- -static void outputOperationSummary(const CoordinateOperationNNPtr &op) { +static void outputOperationSummary(const CoordinateOperationNNPtr &op, + const DatabaseContextPtr &dbContext) { auto ids = op->identifiers(); if (!ids.empty()) { std::cout << *(ids[0]->codeSpace()) << ":" << ids[0]->code(); @@ -512,6 +543,18 @@ static void outputOperationSummary(const CoordinateOperationNNPtr &op) { std::cout << ", has ballpark transformation"; } + if (dbContext && getenv("PROJINFO_NO_GRID_CHECK") == nullptr) { + try { + auto setGrids = op->gridsNeeded(dbContext); + for (const auto &grid : setGrids) { + if (!grid.available) { + std::cout << ", at least one grid missing"; + break; + } + } + } catch (const std::exception &) { + } + } std::cout << std::endl; } @@ -598,7 +641,7 @@ static void outputOperations( } if (summary) { for (const auto &op : list) { - outputOperationSummary(op); + outputOperationSummary(op, dbContext); } } else { bool first = true; @@ -613,7 +656,7 @@ static void outputOperations( "\xC2\xB0" << (i + 1) << ":" << std::endl << std::endl; - outputOperationSummary(op); + outputOperationSummary(op, dbContext); std::cout << std::endl; outputObject(dbContext, op, allowUseIntermediateCRS, outputOpt); } -- cgit v1.2.3 From c9b27a248d3ed9964b6ac0847a83eba383b62537 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 26 Feb 2019 21:17:33 +0100 Subject: Fix build issues on Solaris --- src/apps/proj_strtod.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/apps') diff --git a/src/apps/proj_strtod.cpp b/src/apps/proj_strtod.cpp index b8edc6a3..d4674705 100644 --- a/src/apps/proj_strtod.cpp +++ b/src/apps/proj_strtod.cpp @@ -309,7 +309,7 @@ double proj_strtod(const char *str, char **endptr) { number = exponent < 0? number / ex: number * ex; } else - number *= pow (10, exponent); + number *= pow (10.0, static_cast(exponent)); return number; } -- cgit v1.2.3 From 0ec59ca29500fad156c8f2dd6a96e13bb6595f88 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 6 Mar 2019 14:31:22 +0100 Subject: Make gie return non-zero exit code when file can't be opened --- src/apps/gie.cpp | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'src/apps') diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index abed11c0..e6b63d51 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -300,6 +300,20 @@ int main (int argc, char **argv) { return 1; } + for (i = 0; i < o->fargc; i++ ) { + FILE* f = fopen (o->fargv[i], "rt"); + if (f == nullptr) { + fprintf ( + T.fout, + "%sCannot open specified input file '%s' - bye!\n", + delim, + o->fargv[i] + ); + return 1; + } + fclose(f); + } + for (i = 0; i < o->fargc; i++) process_file (o->fargv[i]); @@ -370,8 +384,6 @@ static int another_failing_roundtrip (void) { } static int process_file (const char *fname) { - FILE *f; - F->lineno = F->next_lineno = F->level = 0; T.op_ok = T.total_ok = 0; T.op_ko = T.total_ko = 0; @@ -383,15 +395,8 @@ static int process_file (const char *fname) { return 0; } - f = fopen (fname, "rt"); - if (nullptr==f) { - if (T.verbosity > 0) { - fprintf (T.fout, "%sCannot open spec'd input file '%s' - bye!\n", delim, fname); - return 2; - } - errmsg (2, "Cannot open spec'd input file '%s' - bye!\n", fname); - } - F->f = f; + /* We have already tested in main that the file exists */ + F->f = fopen (fname, "rt"); if (T.verbosity > 0) fprintf (T.fout, "%sReading file '%s'\n", delim, fname); @@ -405,7 +410,7 @@ static int process_file (const char *fname) { } } - fclose (f); + fclose (F->f); F->lineno = F->next_lineno = 0; T.grand_ok += T.total_ok; -- cgit v1.2.3 From 0cd621da5791a99528f6a5fe892c659cab3bda23 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sat, 9 Mar 2019 10:30:11 +0100 Subject: Allow gie to use proj_create_crs_to_crs (#1314) The commands crs_src and crs_dst are introduced to allow operation initialization with proj_create_crs_to_crs. This has the benefit of using proj.db to select the proper operation. Additionally axis order is respected for the coordinate systems that are tested. This is beneficial when running the GIGS test suite for instance. --- src/apps/gie.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'src/apps') diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index e6b63d51..5407c0ba 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -148,7 +148,7 @@ static ffio *ffio_destroy (ffio *G); static ffio *ffio_create (const char **tags, size_t n_tags, size_t max_record_size); static const char *gie_tags[] = { - "", "operation", "use_proj4_init_rules", + "", "operation", "crs_src", "crs_dst", "use_proj4_init_rules", "accept", "expect", "roundtrip", "banner", "verbose", "direction", "tolerance", "ignore", "require_grid", "echo", "skip", "" }; @@ -175,6 +175,8 @@ static const char *err_const_from_errno (int err); typedef struct { char operation[MAX_OPERATION+1]; + char crs_dst[MAX_OPERATION+1]; + char crs_src[MAX_OPERATION+1]; PJ *P; PJ_COORD a, b, c, e; PJ_DIRECTION dir; @@ -607,6 +609,65 @@ either a conversion or a transformation) return 0; } +static int crs_to_crs_operation() { + T.op_id++; + T.operation_lineno = F->lineno; + + if (T.verbosity > 1) { + char buffer[80]; + finish_previous_operation (F->args); + snprintf(buffer, 80, "%-36.36s -> %-36.36s", T.crs_src, T.crs_dst); + banner (buffer); + } + + T.op_ok = 0; + T.op_ko = 0; + T.op_skip = 0; + T.skip_test = 0; + + direction ("forward"); + tolerance ("0.5 mm"); + ignore ("pjd_err_dont_skip"); + + proj_errno_reset (T.P); + + if (T.P) + proj_destroy (T.P); + proj_errno_reset (nullptr); + proj_context_use_proj4_init_rules(nullptr, T.use_proj4_init_rules); + + + T.P = proj_create_crs_to_crs(nullptr, T.crs_src, T.crs_dst, nullptr); + + strcpy(T.crs_src, ""); + strcpy(T.crs_dst, ""); + return 0; +} + +static int crs_src(const char *args) { + strncpy (&(T.crs_src[0]), F->args, MAX_OPERATION); + T.crs_src[MAX_OPERATION] = '\0'; + (void) args; + + if (strcmp(T.crs_src, "") != 0 && strcmp(T.crs_dst, "") != 0) { + crs_to_crs_operation(); + } + + return 0; +} + +static int crs_dst(const char *args) { + strncpy (&(T.crs_dst[0]), F->args, MAX_OPERATION); + T.crs_dst[MAX_OPERATION] = '\0'; + (void) args; + + if (strcmp(T.crs_src, "") != 0 && strcmp(T.crs_dst, "") != 0) { + crs_to_crs_operation(); + } + + return 0; +} + static PJ_COORD torad_coord (PJ *P, PJ_DIRECTION dir, PJ_COORD a) { size_t i, n; const char *axis = "enut"; @@ -1000,6 +1061,8 @@ static int dispatch (const char *cmnd, const char *args) { if (T.skip) return SKIP; if (0==strcmp (cmnd, "operation")) return operation ((char *) args); + if (0==strcmp (cmnd, "crs_src")) return crs_src (args); + if (0==strcmp (cmnd, "crs_dst")) return crs_dst (args); if (T.skip_test) { if (0==strcmp (cmnd, "expect")) return another_skip(); -- cgit v1.2.3 From e1350cac43d5a9854207af3fb318a74be7fcd12f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 17 Mar 2019 19:16:04 +0100 Subject: Fix some issues raised by latest cppcheck - coordinateoperation_internal.hpp: missing 'explicit' keyword - proj.cpp: unused 'generic' member in enumeration - init.cpp: useless assignment to a_orig and es_orig, because done again a few lines below. - crs.cpp: unused variable - datum.cpp: inefficient use of find() function - io.cpp: * missing 'static' qualifier for method * useles ternary test (left and right have same value) - aeqd.cpp: useless assignment of inv and fwd, snice done again a few lines below - isea.cpp: useless assignment of resolution and aperture since done again a few lines below, and with default values when params are absent - mod_ster.cpp: useless assignment of lp.lam, overriden in below code paths. - stere.cpp: false positive, but better not modify another variable than the iterator in a for() loop. --- src/apps/proj.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/apps') diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index 298a44e8..40fc5695 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -22,7 +22,6 @@ static PJ *Proj; static union { - PJ_UV (*generic)(PJ_UV, PJ *); PJ_XY (*fwd)(PJ_LP, PJ *); PJ_LP (*inv)(PJ_XY, PJ *); } proj; -- cgit v1.2.3 From 5d74522573291a8af698acf3102a662eb3a675eb Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 21 Mar 2019 17:30:06 +1000 Subject: Add -k ellipsoid option to projinfo (#1338) Allows querying of ellipsoid definitions by auth:code lookup --- src/apps/projinfo.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'src/apps') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 7e401887..ae97b9c1 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -77,7 +77,7 @@ struct OutputOptions { static void usage() { std::cerr - << "usage: projinfo [-o formats] [-k crs|operation] [--summary] [-q]" + << "usage: projinfo [-o formats] [-k crs|operation|ellipsoid] [--summary] [-q]" << std::endl << " ([--area name_or_code] | " "[--bbox west_long,south_lat,east_long,north_lat]) " @@ -138,7 +138,7 @@ static std::string c_ify_string(const std::string &str) { static BaseObjectNNPtr buildObject( DatabaseContextPtr dbContext, const std::string &user_string, - bool kindIsCRS, const std::string &context, bool buildBoundCRSToWGS84, + const std::string &kind, const std::string &context, bool buildBoundCRSToWGS84, CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, bool quiet) { BaseObjectPtr obj; @@ -174,10 +174,14 @@ static BaseObjectNNPtr buildObject( try { auto tokens = split(l_user_string, ':'); - if (!kindIsCRS && tokens.size() == 2) { + if (kind == "operation" && tokens.size() == 2) { auto urn = "urn:ogc:def:coordinateOperation:" + tokens[0] + "::" + tokens[1]; obj = createFromUserInput(urn, dbContext).as_nullable(); + } else if (kind == "ellipsoid" && tokens.size() == 2) { + auto urn = "urn:ogc:def:ellipsoid:" + tokens[0] + "::" + + tokens[1]; + obj = createFromUserInput(urn, dbContext).as_nullable(); } else { // Convenience to be able to use C escaped strings... if (l_user_string.size() > 2 && l_user_string[0] == '"' && @@ -572,7 +576,7 @@ static void outputOperations( const std::string &authority, bool usePROJGridAlternatives, bool showSuperseded, const OutputOptions &outputOpt, bool summary) { auto sourceObj = buildObject( - dbContext, sourceCRSStr, true, "source CRS", false, + dbContext, sourceCRSStr, "crs", "source CRS", false, CoordinateOperationContext::IntermediateCRSUse::NEVER, outputOpt.quiet); auto sourceCRS = nn_dynamic_pointer_cast(sourceObj); if (!sourceCRS) { @@ -581,7 +585,7 @@ static void outputOperations( } auto targetObj = buildObject( - dbContext, targetCRSStr, true, "target CRS", false, + dbContext, targetCRSStr, "crs", "target CRS", false, CoordinateOperationContext::IntermediateCRSUse::NEVER, outputOpt.quiet); auto targetCRS = nn_dynamic_pointer_cast(targetObj); if (!targetCRS) { @@ -678,7 +682,7 @@ int main(int argc, char **argv) { std::string targetCRSStr; bool outputSwithSpecified = false; OutputOptions outputOpt; - bool kindIsCRS = true; + std::string objectKind; bool summary = false; ExtentPtr bboxFilter = nullptr; std::string area; @@ -806,9 +810,11 @@ int main(int argc, char **argv) { i++; std::string kind(argv[i]); if (ci_equal(kind, "crs") || ci_equal(kind, "srs")) { - kindIsCRS = true; + objectKind = "crs"; } else if (ci_equal(kind, "operation")) { - kindIsCRS = false; + objectKind = "operation"; + } else if (ci_equal(kind, "ellipsoid")) { + objectKind = "ellipsoid"; } else { std::cerr << "Unrecognized value for option -k: " << kind << std::endl; @@ -998,7 +1004,7 @@ int main(int argc, char **argv) { } if (!user_string.empty()) { - auto obj(buildObject(dbContext, user_string, kindIsCRS, "input string", + auto obj(buildObject(dbContext, user_string, objectKind, "input string", buildBoundCRSToWGS84, allowUseIntermediateCRS, outputOpt.quiet)); if (guessDialect) { -- cgit v1.2.3 From ddd333e6bd6f5e033a2b829067910165e64eb0b9 Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Thu, 21 Mar 2019 19:53:37 +0000 Subject: Build: automatically enable system error messages Define HAVE_STRERROR during configuration. Before: $ cs2cs +proj=latlong +to +proj=latlong dummy : Sys errno: 2: dummy After: $ cs2cs +proj=latlong +to +proj=latlong dummy : Sys errno: 2: No such file or directory dummy --- src/apps/emess.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/apps') diff --git a/src/apps/emess.cpp b/src/apps/emess.cpp index 144e9e23..52f88aa3 100644 --- a/src/apps/emess.cpp +++ b/src/apps/emess.cpp @@ -20,6 +20,7 @@ #include #include "proj_api.h" +#include "proj_config.h" #define EMESS_ROUTINE #include "emess.h" -- cgit v1.2.3 From 10e1b7b75f70c704cf78a7eb7197beebb4b82d4a Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 24 Mar 2019 11:35:16 +0100 Subject: Make cs2cs support 4D coordinates. This is a bit of a hack, 4D coordinates *will* be written to STDOUT but the output format speficied with -f is not respected for the t component, rather it is forward verbatim from the input. Fixes #1354 --- src/apps/cs2cs.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/apps') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index dafd06f8..c68572fa 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -113,6 +113,17 @@ static void process(FILE *fid) z = strtod(s, &s); + /* To avoid breaking existing tests, we read what is a possible t */ + /* component of the input and rewind the s-pointer so that the final */ + /* output has consistant behaviour, with or without t values. */ + /* This is a bit of a hack, in most cases 4D coordinates will be */ + /* written to STDOUT (except when using -E) but the output format */ + /* speficied with -f is not respected for the t component, rather it */ + /* is forward verbatim from the input. */ + char *before_time = s; + double t = strtod(s, &s); + s = before_time; + if (data.v == HUGE_VAL) data.u = HUGE_VAL; @@ -120,11 +131,11 @@ static void process(FILE *fid) --s; /* assumed we gobbled \n */ if (echoin) { - char t; - t = *s; + char temp; + temp = *s; *s = '\0'; (void)fputs(line, stdout); - *s = t; + *s = temp; putchar('\t'); } @@ -141,7 +152,7 @@ static void process(FILE *fid) coord.xyzt.x = data.u; coord.xyzt.y = data.v; coord.xyzt.z = z; - coord.xyzt.t = HUGE_VAL; + coord.xyzt.t = t; coord = proj_trans(transformation, PJ_FWD, coord); data.u = coord.xyz.x; data.v = coord.xyz.y; -- cgit v1.2.3 From 1eadd02ac0b28486e98aed9407f27c4956619bae Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Sun, 24 Mar 2019 11:56:35 +0000 Subject: Doc: consistently use +opt and brackets +opt represents one parameter. An ellipsis indicates additional instances of the previous parameter may be given. Spaces are used between parameters and before an ellipsis, not purely to format brackets. See man(1) SYNOPSIS conventions. --- src/apps/cs2cs.cpp | 4 ++-- src/apps/geod.cpp | 2 +- src/apps/proj.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/apps') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index dafd06f8..b6a0f2ac 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -68,8 +68,8 @@ static const char *oform = static char oform_buffer[16]; /* buffer for oform when using -d */ static const char *oterr = "*\t*"; /* output line for unprojectable input */ static const char *usage = - "%s\nusage: %s [ -dDeEfIlrstvwW [args] ] [ +opts[=arg] ]\n" - " [+to [+opts[=arg] [ files ]\n"; + "%s\nusage: %s [-dDeEfIlrstvwW [args]] [+opt[=arg] ...]\n" + " [+to +opt[=arg] ...] [file ...]\n"; static double (*informat)(const char *, char **); /* input data deformatter function */ diff --git a/src/apps/geod.cpp b/src/apps/geod.cpp index 7225856e..b46188d3 100644 --- a/src/apps/geod.cpp +++ b/src/apps/geod.cpp @@ -22,7 +22,7 @@ static const char *osform = "%.3f"; /* output format for S */ static char pline[50]; /* work string */ static const char *usage = -"%s\nusage: %s [ -afFIlptwW [args] ] [ +opts[=arg] ] [ files ]\n"; +"%s\nusage: %s [-afFIlptwW [args]] [+opt[=arg] ...] [file ...]\n"; static void printLL(double p, double l) { diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index 40fc5695..5f0ee71f 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -45,7 +45,7 @@ static char oform_buffer[16]; /* Buffer for oform when using -d */ static const char *oterr = "*\t*", /* output line for unprojectable input */ - *usage = "%s\nusage: %s [ -bdeEfiIlmorsStTvVwW [args] ] [ +opts[=arg] ] [ files ]\n"; + *usage = "%s\nusage: %s [-bdeEfiIlmorsStTvVwW [args]] [+opt[=arg] ...] [file ...]\n"; static PJ_FACTORS facs; -- cgit v1.2.3 From 66774791d16d1b197911e595aaaceb9690c8ca14 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 25 Mar 2019 12:22:33 +0100 Subject: projinfo.cpp: formatting fix --- src/apps/projinfo.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/apps') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index ae97b9c1..4c99d7ce 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -77,7 +77,8 @@ struct OutputOptions { static void usage() { std::cerr - << "usage: projinfo [-o formats] [-k crs|operation|ellipsoid] [--summary] [-q]" + << "usage: projinfo [-o formats] [-k crs|operation|ellipsoid] " + "[--summary] [-q]" << std::endl << " ([--area name_or_code] | " "[--bbox west_long,south_lat,east_long,north_lat]) " @@ -138,7 +139,8 @@ static std::string c_ify_string(const std::string &str) { static BaseObjectNNPtr buildObject( DatabaseContextPtr dbContext, const std::string &user_string, - const std::string &kind, const std::string &context, bool buildBoundCRSToWGS84, + const std::string &kind, const std::string &context, + bool buildBoundCRSToWGS84, CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, bool quiet) { BaseObjectPtr obj; @@ -179,8 +181,7 @@ static BaseObjectNNPtr buildObject( tokens[1]; obj = createFromUserInput(urn, dbContext).as_nullable(); } else if (kind == "ellipsoid" && tokens.size() == 2) { - auto urn = "urn:ogc:def:ellipsoid:" + tokens[0] + "::" + - tokens[1]; + auto urn = "urn:ogc:def:ellipsoid:" + tokens[0] + "::" + tokens[1]; obj = createFromUserInput(urn, dbContext).as_nullable(); } else { // Convenience to be able to use C escaped strings... -- cgit v1.2.3 From 01f6d08f0a0d3b05c28d6772d63b506171c59371 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 26 Mar 2019 14:09:11 +0100 Subject: projinfo: catch potentially uncaugh exception. Coverity CID 193527 --- src/apps/projinfo.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/apps') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 4c99d7ce..7d4a8399 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -1132,11 +1132,18 @@ int main(int argc, char **argv) { } } - outputOperations( - dbContext, sourceCRSStr, targetCRSStr, bboxFilter, spatialCriterion, - spatialCriterionExplicitlySpecified, crsExtentUse, - gridAvailabilityUse, allowUseIntermediateCRS, pivots, authority, - usePROJGridAlternatives, showSuperseded, outputOpt, summary); + try { + outputOperations(dbContext, sourceCRSStr, targetCRSStr, bboxFilter, + spatialCriterion, + spatialCriterionExplicitlySpecified, crsExtentUse, + gridAvailabilityUse, allowUseIntermediateCRS, + pivots, authority, usePROJGridAlternatives, + showSuperseded, outputOpt, summary); + } catch (const std::exception &e) { + std::cerr << "outputOperations() failed with: " << e.what() + << std::endl; + std::exit(1); + } } return 0; -- cgit v1.2.3 From 703805a646f827971135af1b4e60087d88fed974 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 26 Mar 2019 14:11:34 +0100 Subject: optargpm.h: fix memory leaks in error code paths. Coverity CID 193537 --- src/apps/optargpm.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/apps') diff --git a/src/apps/optargpm.h b/src/apps/optargpm.h index 035c6f92..e7f4f8e5 100644 --- a/src/apps/optargpm.h +++ b/src/apps/optargpm.h @@ -534,6 +534,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, *equals = '='; if (opt_is_flag (o, c)) { fprintf (stderr, "Option \"%s\" takes no arguments\n", crepr); + free (o); return nullptr; } o->optarg[c] = equals + 1; @@ -544,6 +545,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, if (!opt_is_flag (o, c)) { if ((argc==i + 1) || ('+'==argv[i+1][0]) || ('-'==argv[i+1][0])) { fprintf (stderr, "Missing argument for option \"%s\"\n", crepr); + free (o); return nullptr; } o->optarg[c] = argv[i + 1]; @@ -553,6 +555,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, if (!opt_is_flag (o, c)) { fprintf (stderr, "Expected flag style long option here, but got \"%s\"\n", crepr); + free (o); return nullptr; } @@ -564,6 +567,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, /* classic short options */ if (nullptr==o->optarg[c]) { fprintf (stderr, "Invalid option \"%s\"\n", crepr); + free (o); return nullptr; } @@ -580,6 +584,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, if ((argc==i + 1) || ('+'==argv[i+1][0]) || ('-'==argv[i+1][0])) { fprintf (stderr, "Bad or missing arg for option \"%s\"\n", crepr); + free (o); return nullptr; } o->optarg[(int) c] = argv[i + 1]; -- cgit v1.2.3 From 6c22035b270aa46f03e6252cd552be14d170e501 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 26 Mar 2019 14:12:31 +0100 Subject: gie.cpp: silence Coverity CID 193520 --- src/apps/gie.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/apps') diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index 5407c0ba..a84e77ab 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -249,6 +249,7 @@ int main (int argc, char **argv) { T.ignore = 5555; /* Error code that will not be issued by proj_create() */ T.use_proj4_init_rules = FALSE; + /* coverity[tainted_data] */ o = opt_parse (argc, argv, "hlvq", "o", longflags, longkeys); if (nullptr==o) return 0; -- cgit v1.2.3 From 60b71b6187b6190b9ff626c8b0548789aa5c54d7 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 26 Mar 2019 14:17:31 +0100 Subject: proj/emess: fix null pointer dereference. CID 193533 --- src/apps/emess.cpp | 2 +- src/apps/proj.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/apps') diff --git a/src/apps/emess.cpp b/src/apps/emess.cpp index 52f88aa3..53018ba8 100644 --- a/src/apps/emess.cpp +++ b/src/apps/emess.cpp @@ -30,7 +30,7 @@ emess(int code, const char *fmt, ...) { va_start(args, fmt); /* prefix program name, if given */ - if (fmt != nullptr) + if (emess_dat.Prog_name != nullptr) (void)fprintf(stderr,"%s\n<%s>: ",pj_get_release(), emess_dat.Prog_name); /* print file name and line, if given */ diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index 40fc5695..88074280 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -532,7 +532,7 @@ int main(int argc, char **argv) { } else { if ((fid = fopen(*eargv, "rb")) == nullptr) { - emess(-2, *eargv, "input file"); + emess(-2, "input file: %s", *eargv); continue; } emess_dat.File_name = *eargv; -- cgit v1.2.3 From 473a8c133be66af64c227e7d24cb0031ebc6ebd7 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 26 Mar 2019 14:24:48 +0100 Subject: cs2cs: remove dead code that would leak memory. Coverity CID 193534 --- src/apps/cs2cs.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src/apps') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index c68572fa..31f0ae8e 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -274,13 +274,6 @@ static std::string get_geog_crs_proj_string_from_proj_crs(PJ *src, double &toRadians, bool &isLatFirst) { auto srcType = proj_get_type(src); - if (srcType == PJ_TYPE_BOUND_CRS) { - auto base = proj_get_source_crs(nullptr, src); - assert(base); - proj_destroy(src); - src = base; - srcType = proj_get_type(src); - } if (srcType != PJ_TYPE_PROJECTED_CRS) { return std::string(); } -- cgit v1.2.3 From 920ecd18f02d67d3344a3be979748586755a2cf6 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 26 Mar 2019 14:25:27 +0100 Subject: cct.cpp: silence Coverity CID 193536 --- src/apps/cct.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/apps') diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index 34bf0777..87a60e2f 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -228,6 +228,7 @@ int main(int argc, char **argv) { fout = stdout; + /* coverity[tainted_data] */ o = opt_parse (argc, argv, "hvI", "cdozts", longflags, longkeys); if (nullptr==o) return 0; -- cgit v1.2.3 From a53f81de2f5fc5a6366dfea3806f4062abca4ecf Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 26 Mar 2019 14:27:11 +0100 Subject: cct.cpp: silence Coverity CID 193526 --- src/apps/cct.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/apps') diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index 87a60e2f..65718aca 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -369,6 +369,7 @@ int main(int argc, char **argv) { point.lpzt.phi = proj_torad (point.lpzt.phi); } err = proj_errno_reset (P); + /* coverity[returned_value] */ point = proj_trans (P, direction, point); if (HUGE_VAL==point.xyzt.x) { -- cgit v1.2.3 From 3987c3f22206768e875b45ff10b3824c52903d09 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 27 Mar 2019 12:53:20 +0100 Subject: optargpm.h: fix remaining memleak in error code path. Coverity CID 193537 --- src/apps/optargpm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/apps') diff --git a/src/apps/optargpm.h b/src/apps/optargpm.h index e7f4f8e5..f293ad98 100644 --- a/src/apps/optargpm.h +++ b/src/apps/optargpm.h @@ -526,6 +526,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, c = opt_ordinal (o, crepr); if (0==c) { fprintf (stderr, "Invalid option \"%s\"\n", crepr); + free (o); return nullptr; } -- cgit v1.2.3 From e3806d999a86a1ab0e832f1ab6586ad181f64be1 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 27 Mar 2019 12:58:42 +0100 Subject: projinfo: caught uncaught exception. Coverity CID 193527 --- src/apps/projinfo.cpp | 119 +++++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 55 deletions(-) (limited to 'src/apps') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 7d4a8399..9d724522 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -1005,69 +1005,78 @@ int main(int argc, char **argv) { } if (!user_string.empty()) { - auto obj(buildObject(dbContext, user_string, objectKind, "input string", - buildBoundCRSToWGS84, allowUseIntermediateCRS, - outputOpt.quiet)); - if (guessDialect) { - auto dialect = WKTParser().guessDialect(user_string); - std::cout << "Guessed WKT dialect: "; - if (dialect == WKTParser::WKTGuessedDialect::WKT2_2018) { - std::cout << "WKT2_2018"; - } else if (dialect == WKTParser::WKTGuessedDialect::WKT2_2015) { - std::cout << "WKT2_2015"; - } else if (dialect == WKTParser::WKTGuessedDialect::WKT1_GDAL) { - std::cout << "WKT1_GDAL"; - } else if (dialect == WKTParser::WKTGuessedDialect::WKT1_ESRI) { - std::cout << "WKT1_ESRI"; - } else { - std::cout << "Not WKT / unknown"; + try { + auto obj(buildObject(dbContext, user_string, objectKind, + "input string", buildBoundCRSToWGS84, + allowUseIntermediateCRS, outputOpt.quiet)); + if (guessDialect) { + auto dialect = WKTParser().guessDialect(user_string); + std::cout << "Guessed WKT dialect: "; + if (dialect == WKTParser::WKTGuessedDialect::WKT2_2018) { + std::cout << "WKT2_2018"; + } else if (dialect == WKTParser::WKTGuessedDialect::WKT2_2015) { + std::cout << "WKT2_2015"; + } else if (dialect == WKTParser::WKTGuessedDialect::WKT1_GDAL) { + std::cout << "WKT1_GDAL"; + } else if (dialect == WKTParser::WKTGuessedDialect::WKT1_ESRI) { + std::cout << "WKT1_ESRI"; + } else { + std::cout << "Not WKT / unknown"; + } + std::cout << std::endl; } - std::cout << std::endl; - } - outputObject(dbContext, obj, allowUseIntermediateCRS, outputOpt); - if (identify) { - auto crs = dynamic_cast(obj.get()); - if (crs) { - try { - auto res = crs->identify( - dbContext - ? AuthorityFactory::create(NN_NO_CHECK(dbContext), - authority) - .as_nullable() - : nullptr); - std::cout << std::endl; - std::cout << "Identification match count: " << res.size() - << std::endl; - for (const auto &pair : res) { - const auto &identifiedCRS = pair.first; - const auto &ids = identifiedCRS->identifiers(); - if (!ids.empty()) { - std::cout << *ids[0]->codeSpace() << ":" - << ids[0]->code() << ": " << pair.second - << " %" << std::endl; - } else { - auto boundCRS = - dynamic_cast(identifiedCRS.get()); - if (boundCRS && - !boundCRS->baseCRS()->identifiers().empty()) { - const auto &idsBase = - boundCRS->baseCRS()->identifiers(); - std::cout << "BoundCRS of " - << *idsBase[0]->codeSpace() << ":" - << idsBase[0]->code() << ": " + outputObject(dbContext, obj, allowUseIntermediateCRS, outputOpt); + if (identify) { + auto crs = dynamic_cast(obj.get()); + if (crs) { + try { + auto res = crs->identify( + dbContext + ? AuthorityFactory::create( + NN_NO_CHECK(dbContext), authority) + .as_nullable() + : nullptr); + std::cout << std::endl; + std::cout + << "Identification match count: " << res.size() + << std::endl; + for (const auto &pair : res) { + const auto &identifiedCRS = pair.first; + const auto &ids = identifiedCRS->identifiers(); + if (!ids.empty()) { + std::cout << *ids[0]->codeSpace() << ":" + << ids[0]->code() << ": " << pair.second << " %" << std::endl; } else { - std::cout - << "un-identifier CRS: " << pair.second - << " %" << std::endl; + auto boundCRS = dynamic_cast( + identifiedCRS.get()); + if (boundCRS && + !boundCRS->baseCRS() + ->identifiers() + .empty()) { + const auto &idsBase = + boundCRS->baseCRS()->identifiers(); + std::cout << "BoundCRS of " + << *idsBase[0]->codeSpace() << ":" + << idsBase[0]->code() << ": " + << pair.second << " %" + << std::endl; + } else { + std::cout + << "un-identifier CRS: " << pair.second + << " %" << std::endl; + } } } + } catch (const std::exception &e) { + std::cerr << "Identification failed: " << e.what() + << std::endl; } - } catch (const std::exception &e) { - std::cerr << "Identification failed: " << e.what() - << std::endl; } } + } catch (const std::exception &e) { + std::cerr << "buildObject failed: " << e.what() << std::endl; + std::exit(1); } } else { -- cgit v1.2.3 From 095d2204f8bb05d172936aebbb1e9e44852c049f Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Fri, 29 Mar 2019 19:17:37 +0000 Subject: Remove duplicate instances of #include "proj_internal.h" Introduced by "Merge projects.h into proj_internal.h" 8ab6f683. --- src/apps/cct.cpp | 1 - src/apps/gie.cpp | 1 - 2 files changed, 2 deletions(-) (limited to 'src/apps') diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index 65718aca..d29b58fb 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -81,7 +81,6 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-10-26 #include "proj.h" #include "proj_internal.h" #include "proj_strtod.h" -#include "proj_internal.h" #include "optargpm.h" diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index a84e77ab..47211aa8 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -117,7 +117,6 @@ Thomas Knudsen, thokn@sdfe.dk, 2017-10-01/2017-10-08 #include "proj_internal.h" #include "proj_math.h" #include "proj_strtod.h" -#include "proj_internal.h" #include "optargpm.h" -- cgit v1.2.3 From 20300c1fd5b35bf1d577a3726f02940d02c73f54 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 2 Apr 2019 13:30:33 +0200 Subject: Make sure that ISO19111 C++ code sets pj_errno on errors --- src/apps/gie.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/apps') diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index 47211aa8..912113b4 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -1151,6 +1151,7 @@ static const struct errno_vs_err_const lookup[] = { {"pjd_err_invalid_arg" , -58}, {"pjd_err_inconsistent_unit" , -59}, {"pjd_err_mutually_exclusive_args" , -60}, + {"pjd_err_generic_error" , -61}, {"pjd_err_dont_skip" , 5555}, {"pjd_err_unknown" , 9999}, {"pjd_err_enomem" , ENOMEM}, -- cgit v1.2.3 From c1f5b5105065d6cb9f4e547b6b79c83357f1d759 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 2 Apr 2019 23:04:37 +0200 Subject: gie: fix tolerance checking When comparing expected result with got result, in the case the distance computation returns NaN, gie incorrectly considered the test to be OK. Adapt / comment out a few broken tests revealed after that fix. --- src/apps/gie.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/apps') diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index 47211aa8..03dc1556 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -1005,7 +1005,8 @@ Tell GIE what to expect, when transforming the ACCEPTed input else d = proj_xyz_dist (co, ce); - if (d > T.tolerance) + // Test written like that to handle NaN + if (!(d <= T.tolerance)) return expect_message (d, args); succs++; -- cgit v1.2.3 From 70ed3efe60718be74d73d92ec2d121e2de268e53 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 4 Apr 2019 22:36:00 +0200 Subject: Reject negative e parameter to avoid division by zero Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14044 Credit to OSS Fuzz --- src/apps/gie.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/apps') diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index f0f7968f..5a86ebb7 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -1097,7 +1097,7 @@ static const struct errno_vs_err_const lookup[] = { {"pjd_err_no_colon_in_init_string" , -3}, {"pjd_err_proj_not_named" , -4}, {"pjd_err_unknown_projection_id" , -5}, - {"pjd_err_eccentricity_is_one" , -6}, + {"pjd_err_invalid_eccentricity" , -6}, {"pjd_err_unknown_unit_id" , -7}, {"pjd_err_invalid_boolean_param" , -8}, {"pjd_err_unknown_ellp_param" , -9}, -- cgit v1.2.3 From 8a31ed4036888ff2039919f8c998a90cb2143bc2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 19 Apr 2019 23:47:39 +0200 Subject: proj/cs2cs: validate value of -f parameter to avoid potential crashes (fixes #124) --- src/apps/cs2cs.cpp | 8 ++++++++ src/apps/proj.cpp | 9 ++++++++- src/apps/utils.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/apps/utils.h | 29 +++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 src/apps/utils.cpp create mode 100644 src/apps/utils.h (limited to 'src/apps') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 877a68ff..40b0d584 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -45,6 +45,7 @@ #include "proj.h" #include "proj_internal.h" #include "emess.h" +#include "utils.h" // clang-format on #define MAX_LINE 1000 @@ -522,6 +523,13 @@ int main(int argc, char **argv) { if (eargc == 0) /* if no specific files force sysin */ eargv[eargc++] = const_cast("-"); + if( oform ) { + if( !validate_form_string_for_numbers(oform) ) { + emess(3, "invalid format string"); + exit(0); + } + } + /* * If the user has requested inverse, then just reverse the * coordinate systems. diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index 2af49c34..888d723f 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -7,6 +7,7 @@ #include #include #include "emess.h" +#include "utils.h" #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__WIN32__) # include @@ -461,6 +462,13 @@ int main(int argc, char **argv) { if (eargc == 0) /* if no specific files force sysin */ eargv[eargc++] = const_cast("-"); + if( oform ) { + if( !validate_form_string_for_numbers(oform) ) { + emess(3, "invalid format string"); + exit(0); + } + } + /* done with parameter and control input */ if (inverse && postscale) { prescale = 1; @@ -487,7 +495,6 @@ int main(int argc, char **argv) { proj.inv = pj_inv; } else proj.fwd = pj_fwd; - /* set input formatting control */ if (mon) { pj_pr_list(Proj); diff --git a/src/apps/utils.cpp b/src/apps/utils.cpp new file mode 100644 index 00000000..7dc809c9 --- /dev/null +++ b/src/apps/utils.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: Utilities for command line arguments + * Author: Even Rouault + * + ****************************************************************************** + * Copyright (c) 2019, Even Rouault + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#include "utils.h" + +#include + +bool validate_form_string_for_numbers(const char* formatString) { + /* Only accepts '%[+]?[number]?[.]?[number]?[e|E|f|F|g|G]' */ + bool valid = true; + if( formatString[0] != '%' ) + valid = false; + else { + auto oformLen = strlen(formatString); + for( int i = 1; i < static_cast(oformLen) - 1; i++ ) { + if( !(formatString[i] == '.' || + formatString[i] == '+' || + (formatString[i] >= '0' && formatString[i] <= '9')) ) { + valid = false; + break; + } + } + if( valid ) { + valid = formatString[oformLen-1] == 'e' || + formatString[oformLen-1] == 'E' || + formatString[oformLen-1] == 'f' || + formatString[oformLen-1] == 'F' || + formatString[oformLen-1] == 'g' || + formatString[oformLen-1] == 'G'; + } + } + return valid; +} diff --git a/src/apps/utils.h b/src/apps/utils.h new file mode 100644 index 00000000..99c14091 --- /dev/null +++ b/src/apps/utils.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: Utilities for command line arguments + * Author: Even Rouault + * + ****************************************************************************** + * Copyright (c) 2019, Even Rouault + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +bool validate_form_string_for_numbers(const char* formatString); -- cgit v1.2.3 From c5346c7c25ca9fe281df39eaeefebc1aa4009266 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 3 May 2019 20:54:42 +0200 Subject: cs2cs: set time value to HUGE_VAL if not explicitly specified --- src/apps/cs2cs.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/apps') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 40b0d584..20e5e73c 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -123,6 +123,8 @@ static void process(FILE *fid) /* is forward verbatim from the input. */ char *before_time = s; double t = strtod(s, &s); + if( s == before_time ) + t = HUGE_VAL; s = before_time; if (data.v == HUGE_VAL) -- cgit v1.2.3 From 96af6dbf69dd38421916438702be80f73276d879 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 5 May 2019 20:28:59 +0200 Subject: geos: avoid division by zero Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14602 Credit to OSS Fuzz --- src/apps/gie.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/apps') diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index 5a86ebb7..2f401984 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -1121,7 +1121,7 @@ static const struct errno_vs_err_const lookup[] = { {"pjd_err_w_or_m_zero_or_less" , -27}, {"pjd_err_lsat_not_in_range" , -28}, {"pjd_err_path_not_in_range" , -29}, - {"pjd_err_h_less_than_zero" , -30}, + {"pjd_err_invalid_h" , -30}, {"pjd_err_k_less_than_zero" , -31}, {"pjd_err_lat_1_or_2_zero_or_90" , -32}, {"pjd_err_lat_0_or_alpha_eq_90" , -33}, -- cgit v1.2.3