DataPromisePtr DirectorySharingPromise::data (const Path & subPath, const String & user) const { if (sf::checkDangerousPath(subPath.toString())) { Log (LogWarning) << LOGID << subPath << " looks dangerous, rejecting" << std::endl; } if (user.empty()){ // Check if it is a directory DataPromisePtr tryDirectory = directoryListing (subPath); if (tryDirectory) return tryDirectory; // It must be a file return subFile (subPath); } if (user == "list"){ return directoryListing (subPath); } if (user == "file"){ return subFile (subPath); } if (user == "glob") { return DataPromisePtr (new GlobPromise (mGlobber, osPath (subPath))); } // unknown user flag Log (LogWarning) << LOGID << "Unknown user flag: " << user << std::endl; return DataPromisePtr (); }
DataPromisePtr DirectorySharingPromise::subFile (const Path & path) const { String osp = osPath (path); if (mError) { return DataPromisePtr(); } FileSharingPromisePtr p (new FileSharingPromise (osp)); if (mTransmissionUpdated){ p->transmissionUpdated() = abind (mTransmissionUpdated, weak_ptr<FileSharingPromise> (p)); } return DataPromisePtr (p); }
DataPromisePtr DirectorySharingPromise::directoryListing (const Path & path) const { String osp = osPath (path); DirectoryListing listing; Error error = sf::listDirectory(osp, &listing); if (error) { Log (LogInfo) << LOGID << "List directory of " << osp << " returned " << toString (error) << std::endl; return DataPromisePtr(); } ByteArrayPtr result = createByteArrayPtr(); *result = toJSON (listing); return sf::createDataPromise(result); }
Path & Path::operator+=( const QString & add ) { mPath = osPath( mPath + add ); return *this; }
GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Is this a SENTINEL-1 manifest.safe definition? */ /* -------------------------------------------------------------------- */ if ( !SAFEDataset::Identify( poOpenInfo ) ) { return nullptr; } /* -------------------------------------------------------------------- */ /* Get subdataset information, if relevant */ /* -------------------------------------------------------------------- */ CPLString osMDFilename; //Subdataset 1st level selection (ex: for swath selection) CPLString osSelectedSubDS1; //Subdataset 2nd level selection (ex: for polarisation selection) CPLString osSelectedSubDS2; if (STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL1_DS:")) { osMDFilename = poOpenInfo->pszFilename + strlen("SENTINEL1_DS:"); const char* pszSelection1 = strrchr(osMDFilename.c_str(), ':'); if (pszSelection1 == nullptr || pszSelection1 == osMDFilename.c_str() ) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid syntax for SENTINEL1_DS:"); return nullptr; } osMDFilename.resize( pszSelection1 - osMDFilename.c_str() ); osSelectedSubDS1 = pszSelection1 + strlen(":"); const char* pszSelection2 = strchr(osSelectedSubDS1.c_str(), '_'); if (pszSelection2 != nullptr && pszSelection2 != pszSelection1 ) { osSelectedSubDS1.resize( pszSelection2 - osSelectedSubDS1.c_str() ); osSelectedSubDS2 = pszSelection2 + strlen("_"); } //update directory check: VSIStatBufL sStat; if( VSIStatL( osMDFilename.c_str(), &sStat ) == 0 ) poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode ); } else { osMDFilename = poOpenInfo->pszFilename; } if( poOpenInfo->bIsDirectory ) { osMDFilename = CPLFormCIFilename( osMDFilename.c_str(), "manifest.safe", nullptr ); } /* -------------------------------------------------------------------- */ /* Ingest the manifest.safe file. */ /* -------------------------------------------------------------------- */ //TODO REMOVE CPLXMLNode *psImageAttributes, *psImageGenerationParameters; CPLXMLNode *psManifest = CPLParseXMLFile( osMDFilename ); if( psManifest == nullptr ) return nullptr; CPLString osPath(CPLGetPath( osMDFilename )); /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_NotSupported, "The SAFE driver does not support update access to existing" " datasets.\n" ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get contentUnit parent element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psContentUnits = CPLGetXMLNode( psManifest, "=xfdu:XFDU.informationPackageMap.xfdu:contentUnit" ); if( psContentUnits == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><informationPackageMap>" "<xfdu:contentUnit> in manifest file." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get Metadata Objects element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psMetaDataObjects = CPLGetXMLNode( psManifest, "=xfdu:XFDU.metadataSection" ); if( psMetaDataObjects == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><metadataSection>" "in manifest file." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get Data Objects element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDataObjects = CPLGetXMLNode( psManifest, "=xfdu:XFDU.dataObjectSection" ); if( psDataObjects == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><dataObjectSection> in document." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Create the dataset. */ /* -------------------------------------------------------------------- */ SAFEDataset *poDS = new SAFEDataset(); poDS->psManifest = psManifest; /* -------------------------------------------------------------------- */ /* Look for "Measurement Data Unit" contentUnit elements. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAnnotation = nullptr; //Map with all measures aggregated by swath std::map<CPLString, std::set<CPLString> > oMapSwaths2Pols; for( CPLXMLNode *psContentUnit = psContentUnits->psChild; psContentUnit != nullptr; psContentUnit = psContentUnit->psNext ) { if( psContentUnit->eType != CXT_Element || !(EQUAL(psContentUnit->pszValue,"xfdu:contentUnit")) ) { continue; } const char *pszUnitType = CPLGetXMLValue( psContentUnit, "unitType", "" ); const char *pszAnnotation = nullptr; const char *pszCalibration = nullptr; const char *pszMeasurement = nullptr; if ( EQUAL(pszUnitType, "Measurement Data Unit") ) { /* Get dmdID and dataObjectID */ const char *pszDmdID = CPLGetXMLValue(psContentUnit, "dmdID", ""); const char *pszDataObjectID = CPLGetXMLValue( psContentUnit, "dataObjectPointer.dataObjectID", "" ); if( *pszDataObjectID == '\0' || *pszDmdID == '\0' ) { continue; } CPLXMLNode *psDataObject = SAFEDataset::GetDataObject( psDataObjects, pszDataObjectID); const char *pszRepId = CPLGetXMLValue( psDataObject, "repID", "" ); if ( !EQUAL(pszRepId, "s1Level1MeasurementSchema") ) { continue; } pszMeasurement = CPLGetXMLValue( psDataObject, "byteStream.fileLocation.href", ""); if( *pszMeasurement == '\0' ) { continue; } char** papszTokens = CSLTokenizeString2( pszDmdID, " ", CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES ); for( int j = 0; j < CSLCount( papszTokens ); j++ ) { const char* pszId = papszTokens[j]; if( *pszId == '\0' ) { continue; } //Map the metadata ID to the object element CPLXMLNode *psDO = SAFEDataset::GetDataObject( psMetaDataObjects, psDataObjects, pszId); if (psDO == nullptr) { continue; } //check object type pszRepId = CPLGetXMLValue( psDO, "repID", "" ); if( EQUAL(pszRepId, "s1Level1ProductSchema") ) { /* Get annotation filename */ pszAnnotation = CPLGetXMLValue( psDO, "byteStream.fileLocation.href", ""); if( *pszAnnotation == '\0' ) { continue; } } else if( EQUAL(pszRepId, "s1Level1CalibrationSchema") ) { pszCalibration = CPLGetXMLValue( psDO, "byteStream.fileLocation.href", ""); if( *pszCalibration == '\0' ) { continue; } } else { continue; } } CSLDestroy(papszTokens); if (pszAnnotation == nullptr || pszCalibration == nullptr ) { continue; } //open Annotation XML file CPLString osAnnotationFilePath = CPLFormFilename( osPath, pszAnnotation, nullptr ); if( psAnnotation ) CPLDestroyXMLNode(psAnnotation); psAnnotation = CPLParseXMLFile( osAnnotationFilePath ); if( psAnnotation == nullptr ) continue; /* -------------------------------------------------------------------- */ /* Get overall image information. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = atoi(CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.numberOfSamples", "-1" )); poDS->nRasterYSize = atoi(CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.numberOfLines", "-1" )); if (poDS->nRasterXSize <= 1 || poDS->nRasterYSize <= 1) { CPLError( CE_Failure, CPLE_OpenFailed, "Non-sane raster dimensions provided in manifest.safe. " "If this is a valid SENTINEL-1 scene, please contact your " "data provider for a corrected dataset." ); delete poDS; CPLDestroyXMLNode(psAnnotation); return nullptr; } CPLString osProductType = CPLGetXMLValue( psAnnotation, "=product.adsHeader.productType", "UNK" ); CPLString osMissionId = CPLGetXMLValue( psAnnotation, "=product.adsHeader.missionId", "UNK" ); CPLString osPolarisation = CPLGetXMLValue( psAnnotation, "=product.adsHeader.polarisation", "UNK" ); CPLString osMode = CPLGetXMLValue( psAnnotation, "=product.adsHeader.mode", "UNK" ); CPLString osSwath = CPLGetXMLValue( psAnnotation, "=product.adsHeader.swath", "UNK" ); oMapSwaths2Pols[osSwath].insert(osPolarisation); if (osSelectedSubDS1.empty()) { // If not subdataset was selected, // open the first one we can find. osSelectedSubDS1 = osSwath; } if (!EQUAL(osSelectedSubDS1.c_str(), osSwath.c_str())) { //do not mix swath, otherwise it does not work for SLC products continue; } if (!osSelectedSubDS2.empty() && (osSelectedSubDS2.find(osPolarisation)== std::string::npos)) { // Add only selected polarisations. continue; } poDS->SetMetadataItem("PRODUCT_TYPE", osProductType.c_str()); poDS->SetMetadataItem("MISSION_ID", osMissionId.c_str()); poDS->SetMetadataItem("MODE", osMode.c_str()); poDS->SetMetadataItem("SWATH", osSwath.c_str()); /* -------------------------------------------------------------------- */ /* Get dataType (so we can recognize complex data), and the */ /* bitsPerSample. */ /* -------------------------------------------------------------------- */ const char *pszDataType = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.outputPixels", "" ); GDALDataType eDataType; if( EQUAL(pszDataType,"16 bit Signed Integer") ) eDataType = GDT_CInt16; else if( EQUAL(pszDataType,"16 bit Unsigned Integer") ) eDataType = GDT_UInt16; else { delete poDS; CPLError( CE_Failure, CPLE_AppDefined, "dataType=%s: not a supported configuration.", pszDataType ); CPLDestroyXMLNode(psAnnotation); return nullptr; } /* Extract pixel spacing information */ const char *pszPixelSpacing = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.rangePixelSpacing", "UNK" ); poDS->SetMetadataItem( "PIXEL_SPACING", pszPixelSpacing ); const char *pszLineSpacing = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.azimuthPixelSpacing", "UNK" ); poDS->SetMetadataItem( "LINE_SPACING", pszLineSpacing ); /* -------------------------------------------------------------------- */ /* Form full filename (path of manifest.safe + measurement file). */ /* -------------------------------------------------------------------- */ char *pszFullname = CPLStrdup(CPLFormFilename( osPath, pszMeasurement, nullptr )); /* -------------------------------------------------------------------- */ /* Try and open the file. */ /* -------------------------------------------------------------------- */ GDALDataset *poBandFile = reinterpret_cast<GDALDataset *>( GDALOpen( pszFullname, GA_ReadOnly ) ); if( poBandFile == nullptr ) { // NOP } else if (poBandFile->GetRasterCount() == 0) { GDALClose( (GDALRasterBandH) poBandFile ); } else { poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles, osAnnotationFilePath ); poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles, pszFullname ); /* -------------------------------------------------------------------- */ /* Create the band. */ /* -------------------------------------------------------------------- */ SAFERasterBand *poBand = new SAFERasterBand( poDS, eDataType, osSwath.c_str(), osPolarisation.c_str(), poBandFile ); poDS->SetBand( poDS->GetRasterCount() + 1, poBand ); } CPLFree( pszFullname ); } } //loop through all Swath/pols to add subdatasets int iSubDS = 1; for (std::map<CPLString, std::set<CPLString> >::iterator iterSwath=oMapSwaths2Pols.begin(); iterSwath!=oMapSwaths2Pols.end(); ++iterSwath) { CPLString osSubDS1 = iterSwath->first; CPLString osSubDS2; for (std::set<CPLString>::iterator iterPol=iterSwath->second.begin(); iterPol!=iterSwath->second.end(); ++iterPol) { if (!osSubDS2.empty()) { osSubDS2 += "+"; } osSubDS2 += *iterPol; //Create single band SubDataset SAFEDataset::AddSubDataset(poDS, iSubDS, CPLSPrintf("SENTINEL1_DS:%s:%s_%s", osPath.c_str(), osSubDS1.c_str(), (*iterPol).c_str()), CPLSPrintf("Single band with %s swath and %s polarisation", osSubDS1.c_str(), (*iterPol).c_str()) ); iSubDS++; } if (iterSwath->second.size()>1) { //Create single band SubDataset with all polarisations SAFEDataset::AddSubDataset(poDS, iSubDS, CPLSPrintf("SENTINEL1_DS:%s:%s", osPath.c_str(), osSubDS1.c_str()), CPLSPrintf("%s swath with all polarisations as bands", osSubDS1.c_str()) ); iSubDS++; } } if (poDS->GetRasterCount() == 0) { CPLError( CE_Failure, CPLE_OpenFailed, "Measurement bands not found." ); delete poDS; if( psAnnotation ) CPLDestroyXMLNode(psAnnotation); return nullptr; } /* -------------------------------------------------------------------- */ /* Collect more metadata elements */ /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ /* Platform information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psPlatformAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "platform"); if (psPlatformAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:familyName", "" ); poDS->SetMetadataItem( "SATELLITE_IDENTIFIER", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:familyName.abbreviation", "" ); poDS->SetMetadataItem( "SENSOR_IDENTIFIER", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:extension" ".s1sarl1:instrumentMode.s1sarl1:mode", "UNK" ); poDS->SetMetadataItem( "BEAM_MODE", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:extension" ".s1sarl1:instrumentMode.s1sarl1:swath", "UNK" ); poDS->SetMetadataItem( "BEAM_SWATH", pszItem ); } /* -------------------------------------------------------------------- */ /* Acquisition Period information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAcquisitionAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "acquisitionPeriod"); if (psAcquisitionAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psAcquisitionAttrs, "metadataWrap.xmlData.safe:acquisitionPeriod" ".safe:startTime", "UNK" ); poDS->SetMetadataItem( "ACQUISITION_START_TIME", pszItem ); pszItem = CPLGetXMLValue( psAcquisitionAttrs, "metadataWrap.xmlData.safe:acquisitionPeriod" ".safe:stopTime", "UNK" ); poDS->SetMetadataItem( "ACQUISITION_STOP_TIME", pszItem ); } /* -------------------------------------------------------------------- */ /* Processing information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psProcessingAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "processing"); if (psProcessingAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psProcessingAttrs, "metadataWrap.xmlData.safe:processing.safe:facility.name", "UNK" ); poDS->SetMetadataItem( "FACILITY_IDENTIFIER", pszItem ); } /* -------------------------------------------------------------------- */ /* Measurement Orbit Reference information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psOrbitAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "measurementOrbitReference"); if (psOrbitAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psOrbitAttrs, "metadataWrap.xmlData.safe:orbitReference" ".safe:orbitNumber", "UNK" ); poDS->SetMetadataItem( "ORBIT_NUMBER", pszItem ); pszItem = CPLGetXMLValue( psOrbitAttrs, "metadataWrap.xmlData.safe:orbitReference" ".safe:extension.s1:orbitProperties.s1:pass", "UNK" ); poDS->SetMetadataItem( "ORBIT_DIRECTION", pszItem ); } /* -------------------------------------------------------------------- */ /* Collect Annotation Processing Information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psProcessingInfo = CPLGetXMLNode( psAnnotation, "=product.imageAnnotation.processingInformation" ); if ( psProcessingInfo != nullptr ) { OGRSpatialReference oLL, oPrj; const char *pszEllipsoidName = CPLGetXMLValue( psProcessingInfo, "ellipsoidName", "" ); const double minor_axis = CPLAtof(CPLGetXMLValue( psProcessingInfo, "ellipsoidSemiMinorAxis", "0.0" )); const double major_axis = CPLAtof(CPLGetXMLValue( psProcessingInfo, "ellipsoidSemiMajorAxis", "0.0" )); if ( EQUAL(pszEllipsoidName, "") || ( minor_axis == 0.0 ) || ( major_axis == 0.0 ) ) { CPLError(CE_Warning,CPLE_AppDefined,"Warning- incomplete" " ellipsoid information. Using wgs-84 parameters.\n"); oLL.SetWellKnownGeogCS( "WGS84" ); oPrj.SetWellKnownGeogCS( "WGS84" ); } else if ( EQUAL( pszEllipsoidName, "WGS84" ) ) { oLL.SetWellKnownGeogCS( "WGS84" ); oPrj.SetWellKnownGeogCS( "WGS84" ); } else { const double inv_flattening = major_axis/(major_axis - minor_axis); oLL.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening); oPrj.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening); } CPLFree( poDS->pszGCPProjection ); poDS->pszGCPProjection = nullptr; oLL.exportToWkt( &(poDS->pszGCPProjection) ); } /* -------------------------------------------------------------------- */ /* Collect GCPs. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psGeoGrid = CPLGetXMLNode( psAnnotation, "=product.geolocationGrid.geolocationGridPointList" ); if( psGeoGrid != nullptr ) { /* count GCPs */ poDS->nGCPCount = 0; for( CPLXMLNode *psNode = psGeoGrid->psChild; psNode != nullptr; psNode = psNode->psNext ) { if( EQUAL(psNode->pszValue,"geolocationGridPoint") ) poDS->nGCPCount++ ; } poDS->pasGCPList = reinterpret_cast<GDAL_GCP *>( CPLCalloc( sizeof(GDAL_GCP), poDS->nGCPCount ) ); poDS->nGCPCount = 0; for( CPLXMLNode *psNode = psGeoGrid->psChild; psNode != nullptr; psNode = psNode->psNext ) { GDAL_GCP *psGCP = poDS->pasGCPList + poDS->nGCPCount; if( !EQUAL(psNode->pszValue,"geolocationGridPoint") ) continue; poDS->nGCPCount++ ; char szID[32]; snprintf( szID, sizeof(szID), "%d", poDS->nGCPCount ); psGCP->pszId = CPLStrdup( szID ); psGCP->pszInfo = CPLStrdup(""); psGCP->dfGCPPixel = CPLAtof(CPLGetXMLValue(psNode,"pixel","0")); psGCP->dfGCPLine = CPLAtof(CPLGetXMLValue(psNode,"line","0")); psGCP->dfGCPX = CPLAtof(CPLGetXMLValue(psNode,"longitude","")); psGCP->dfGCPY = CPLAtof(CPLGetXMLValue(psNode,"latitude","")); psGCP->dfGCPZ = CPLAtof(CPLGetXMLValue(psNode,"height","")); } } CPLDestroyXMLNode(psAnnotation); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ const CPLString osDescription = osMDFilename; /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( osDescription ); poDS->SetPhysicalFilename( osMDFilename ); poDS->SetSubdatasetName( osDescription ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" ); return poDS; }