| 302 | } |
| 303 | |
| 304 | Expected<void> decompressZip_( zip_t * zip, const std::filesystem::path& targetFolder, const char * password ) |
| 305 | { |
| 306 | assert( zip ); |
| 307 | |
| 308 | std::error_code ec; |
| 309 | if ( !std::filesystem::is_directory( targetFolder, ec ) ) |
| 310 | return unexpected( "Directory does not exist " + utf8string( targetFolder ) ); |
| 311 | |
| 312 | if ( password ) |
| 313 | zip_set_default_password( zip, password ); |
| 314 | |
| 315 | zip_stat_t stats; |
| 316 | zip_file_t* zfile; |
| 317 | std::vector<char> fileBufer; |
| 318 | for ( int i = 0; i < zip_get_num_entries( zip, 0 ); ++i ) |
| 319 | { |
| 320 | if ( zip_stat_index( zip, i, 0, &stats ) == -1 ) |
| 321 | return unexpected( "Cannot process zip content" ); |
| 322 | |
| 323 | std::string nameFixed = stats.name; |
| 324 | std::replace( nameFixed.begin(), nameFixed.end(), '\\', '/' ); |
| 325 | std::filesystem::path relativeName = pathFromUtf8( nameFixed ); |
| 326 | relativeName.make_preferred(); |
| 327 | std::filesystem::path newItemPath = targetFolder / relativeName; |
| 328 | if ( !nameFixed.empty() && nameFixed.back() == '/' ) |
| 329 | { |
| 330 | if ( !std::filesystem::exists( newItemPath.parent_path(), ec ) ) |
| 331 | if ( !std::filesystem::create_directories( newItemPath.parent_path(), ec ) ) |
| 332 | return unexpected( "Cannot create folder " + utf8string( newItemPath.parent_path() ) ); |
| 333 | } |
| 334 | else |
| 335 | { |
| 336 | zfile = zip_fopen_index(zip,i,0); |
| 337 | if ( !zfile ) |
| 338 | return unexpected( "Cannot open zip file " + nameFixed ); |
| 339 | |
| 340 | // in some manually created zip-files there is no folder entries for files in sub-folders; |
| 341 | // so let us create directory each time before saving a file in it |
| 342 | if ( !std::filesystem::exists( newItemPath.parent_path(), ec ) ) |
| 343 | if ( !std::filesystem::create_directories( newItemPath.parent_path(), ec ) ) |
| 344 | return unexpected( "Cannot create folder " + utf8string( newItemPath.parent_path() ) ); |
| 345 | |
| 346 | std::ofstream ofs( newItemPath, std::ios::binary ); |
| 347 | if ( !ofs || ofs.bad() ) |
| 348 | return unexpected( "Cannot create file " + utf8string( newItemPath ) ); |
| 349 | |
| 350 | fileBufer.resize(stats.size); |
| 351 | auto bitesRead = zip_fread(zfile,(void*)fileBufer.data(),fileBufer.size()); |
| 352 | if ( bitesRead != (zip_int64_t)stats.size ) |
| 353 | return unexpected( "Cannot read file from zip " + nameFixed ); |
| 354 | |
| 355 | zip_fclose(zfile); |
| 356 | if ( !ofs.write( fileBufer.data(), fileBufer.size() ) ) |
| 357 | return unexpected( "Cannot write file from zip " + utf8string( newItemPath ) ); |
| 358 | ofs.close(); |
| 359 | } |
| 360 | } |
| 361 | return {}; |
no test coverage detected