Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from OSGeo:master #51

Merged
merged 4 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions autotest/cpp/test_cpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,21 @@ TEST_F(test_cpl, CPLFormFilename)
EXPECT_TRUE(
EQUAL(CPLFormFilename("\\\\$\\c:", "..", nullptr), "\\\\$\\c:/..") ||
EQUAL(CPLFormFilename("\\\\$\\c:", "..", nullptr), "\\\\$\\c:\\.."));
EXPECT_STREQ(CPLFormFilename("/a", "../", nullptr), "/");
EXPECT_STREQ(CPLFormFilename("/a/", "../", nullptr), "/");
EXPECT_STREQ(CPLFormFilename("/a", "../b", nullptr), "/b");
EXPECT_STREQ(CPLFormFilename("/a/", "../b", nullptr), "/b");
EXPECT_STREQ(CPLFormFilename("/a", "../b/c", nullptr), "/b/c");
EXPECT_STREQ(CPLFormFilename("/a/", "../b/c/d", nullptr), "/b/c/d");
EXPECT_STREQ(CPLFormFilename("/a/b", "../../c", nullptr), "/c");
EXPECT_STREQ(CPLFormFilename("/a/b/", "../../c/d", nullptr), "/c/d");
EXPECT_STREQ(CPLFormFilename("/a/b", "../..", nullptr), "/");
EXPECT_STREQ(CPLFormFilename("/a/b", "../../", nullptr), "/");
EXPECT_STREQ(CPLFormFilename("/a/b/c", "../../d", nullptr), "/a/d");
EXPECT_STREQ(CPLFormFilename("/a/b/c/", "../../d", nullptr), "/a/d");
// we could also just error out, but at least this preserves the original
// semantics
EXPECT_STREQ(CPLFormFilename("/a", "../../b", nullptr), "/a/../../b");
EXPECT_STREQ(
CPLFormFilename("/vsicurl/http://example.com?foo", "bar", nullptr),
"/vsicurl/http://example.com/bar?foo");
Expand Down
2 changes: 1 addition & 1 deletion doc/source/drivers/raster/vrt_processed_dataset.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ defined as a child element of ``VRTDataset``, with the following 2 attributes:
returned by the initialization function of the last step, or an integer value.

* ``dataType`` whose value can be ``FROM_SOURCE`` to indicate that the output band
data type must be the same as one of the input dataset,
data type must be the same as the one of the input dataset,
``FROM_LAST_STEP`` to indicate that it must be the one returned by the
initialization function of the last step, or a value among
Byte, Int8, UInt16, Int16, UInt32, Int32, UInt64, Int64, Float32, Float64, CInt16, CInt32, CFloat32 or CFloat64
Expand Down
1 change: 1 addition & 0 deletions frmts/gti/gdaltileindexdataset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4122,6 +4122,7 @@ void GDALTileIndexDataset::InitBuffer(void *pData, int nBufXSize, int nBufYSize,
nBandNr == 0
? m_poMaskBand.get()
: cpl::down_cast<GDALTileIndexBand *>(papoBands[nBandNr - 1]);
CPLAssert(poVRTBand);
const double dfNoData = poVRTBand->m_dfNoDataValue;
if (dfNoData == 0.0)
{
Expand Down
13 changes: 8 additions & 5 deletions ogr/ogrsf_frmts/pg/ogrpglayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1943,9 +1943,12 @@ OGRErr OGRPGLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
OGRErr OGRPGLayer::GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
int bForce)
{
auto poLayerDefn = GetLayerDefn();

// If the geometry field is not 3D go for 2D
if (GetLayerDefn()->GetGeomFieldCount() > iGeomField &&
!OGR_GT_HasZ(GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType()))
if (poLayerDefn->GetGeomFieldCount() > iGeomField &&
!OGR_GT_HasZ(CPLAssertNotNull(poLayerDefn->GetGeomFieldDefn(iGeomField))
->GetType()))
{
const OGRErr retVal{GetExtent(iGeomField, psExtent3D, bForce)};
psExtent3D->MinZ = std::numeric_limits<double>::infinity();
Expand All @@ -1955,8 +1958,8 @@ OGRErr OGRPGLayer::GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,

CPLString osCommand;

if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
CPLAssertNotNull(GetLayerDefn()->GetGeomFieldDefn(iGeomField))
if (iGeomField < 0 || iGeomField >= poLayerDefn->GetGeomFieldCount() ||
CPLAssertNotNull(poLayerDefn->GetGeomFieldDefn(iGeomField))
->GetType() == wkbNone)
{
if (iGeomField != 0)
Expand All @@ -1968,7 +1971,7 @@ OGRErr OGRPGLayer::GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
}

OGRPGGeomFieldDefn *poGeomFieldDefn =
poFeatureDefn->GetGeomFieldDefn(iGeomField);
poLayerDefn->GetGeomFieldDefn(iGeomField);

if (TestCapability(OLCFastGetExtent3D))
{
Expand Down
81 changes: 58 additions & 23 deletions port/cpl_path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ const char *CPLResetExtension(const char *pszPath, const char *pszExt)
* CPLFormFilename(NULL,"def", NULL ) == "def"
* CPLFormFilename(NULL, "abc/def.dat", NULL ) == "abc/def.dat"
* CPLFormFilename("/abc/xyz/", "def.dat", NULL ) == "/abc/xyz/def.dat"
* CPLFormFilename("/a/b/c", "../d", NULL ) == "/a/b/d" (since 3.10.1)
* \endcode
*
* @param pszPath directory path to the directory containing the file. This
Expand Down Expand Up @@ -631,33 +632,67 @@ const char *CPLFormFilename(const char *pszPath, const char *pszBasename,
pszAddedPathSep = "/";
}

if (!CPLIsFilenameRelative(pszPath) && strcmp(pszBasename, "..") == 0)
if (!CPLIsFilenameRelative(pszPath) && pszBasename[0] == '.' &&
pszBasename[1] == '.' &&
(pszBasename[2] == 0 || pszBasename[2] == '\\' ||
pszBasename[2] == '/'))
{
// /a/b + .. --> /a
// "/a/b/" + "..[/something]" --> "/a[/something]"
// "/a/b" + "..[/something]" --> "/a[/something]"
if (pszPath[nLenPath - 1] == '\\' || pszPath[nLenPath - 1] == '/')
nLenPath--;
size_t nLenPathOri = nLenPath;
while (nLenPath > 0 && pszPath[nLenPath - 1] != '\\' &&
pszPath[nLenPath - 1] != '/')
while (true)
{
nLenPath--;
}
if (nLenPath == 1 && pszPath[0] == '/')
{
pszBasename = "";
}
else if ((nLenPath > 1 && pszPath[0] == '/') ||
(nLenPath > 2 && pszPath[1] == ':') ||
(nLenPath > 6 && strncmp(pszPath, "\\\\$\\", 4) == 0))
{
nLenPath--;
pszBasename = "";
}
else
{
nLenPath = nLenPathOri;
if (pszAddedPathSep[0] == 0)
pszAddedPathSep = VSIGetDirectorySeparator(pszPath);
const char *pszBasenameOri = pszBasename;
const size_t nLenPathOri = nLenPath;
while (nLenPath > 0 && pszPath[nLenPath - 1] != '\\' &&
pszPath[nLenPath - 1] != '/')
{
nLenPath--;
}
if (nLenPath == 1 && pszPath[0] == '/')
{
pszBasename += 2;
if (pszBasename[0] == '/' || pszBasename[0] == '\\')
pszBasename++;
if (*pszBasename == '.')
{
pszBasename = pszBasenameOri;
nLenPath = nLenPathOri;
if (pszAddedPathSep[0] == 0)
pszAddedPathSep =
pszPath[0] == '/'
? "/"
: VSIGetDirectorySeparator(pszPath);
}
break;
}
else if ((nLenPath > 1 && pszPath[0] == '/') ||
(nLenPath > 2 && pszPath[1] == ':') ||
(nLenPath > 6 && strncmp(pszPath, "\\\\$\\", 4) == 0))
{
nLenPath--;
pszBasename += 2;
if ((pszBasename[0] == '/' || pszBasename[0] == '\\') &&
pszBasename[1] == '.' && pszBasename[2] == '.')
{
pszBasename++;
}
else
{
break;
}
}
else
{
pszBasename = pszBasenameOri;
nLenPath = nLenPathOri;
if (pszAddedPathSep[0] == 0)
pszAddedPathSep = pszPath[0] == '/'
? "/"
: VSIGetDirectorySeparator(pszPath);
break;
}
}
}
else if (nLenPath > 0 && pszPath[nLenPath - 1] != '/' &&
Expand Down
2 changes: 1 addition & 1 deletion port/cpl_vsil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ char **VSISiblingFiles(const char *pszFilename)
/** Return the directory separator for the specified path.
*
* Default is forward slash. The only exception currently is the Windows
* file system which returns anti-slash, unless the specified path is of the
* file system which returns backslash, unless the specified path is of the
* form "{drive_letter}:/{rest_of_the_path}".
*
* @since 3.9
Expand Down
Loading