349{
350 BOOST_LOG_TRIVIAL(info) << "Syncing configuration cache";
351
353
354
355
356
357 fs::path archive_path(
cache_path /
"vendor_indices.zip");
358 if (index_archive_url.empty()) {
359 BOOST_LOG_TRIVIAL(
error) <<
"Downloading profile archive failed - url has no value.";
360 return;
361 }
362 BOOST_LOG_TRIVIAL(info) << "Downloading vedor profiles archive zip from " << index_archive_url;
363
364 if (!boost::starts_with(index_archive_url, "http://files.prusa3d.com/wp-content/uploads/repository/") &&
365 !boost::starts_with(index_archive_url, "https://files.prusa3d.com/wp-content/uploads/repository/"))
366 {
367 BOOST_LOG_TRIVIAL(
error) <<
"Unsafe url path for vedor profiles archive zip. Download is rejected.";
368 return;
369 }
370 if (!
get_file(index_archive_url, archive_path)) {
371 BOOST_LOG_TRIVIAL(
error) <<
"Download of vedor profiles archive zip failed.";
372 return;
373 }
375 return;
376 }
377
378 enum class VendorStatus
379 {
381 IN_CACHE,
382 NEW_VERSION,
383 INSTALLED
384 };
385
386 std::vector<std::pair<std::string, VendorStatus>> vendors_with_status;
387
391 BOOST_LOG_TRIVIAL(
error) <<
"Couldn't open zipped bundle.";
392 return;
393 } else {
395
397 for (
mz_uint i = 0; i < num_entries; ++i) {
399 std::string name(
stat.m_filename);
400 if (
stat.m_uncomp_size > 0) {
401 std::string buffer((
size_t)
stat.m_uncomp_size, 0);
403 if (res == 0) {
404 BOOST_LOG_TRIVIAL(
error) <<
"Failed to unzip " <<
stat.m_filename;
405 continue;
406 }
407
409 if (!fs::exists(tmp_path.parent_path())) {
410 BOOST_LOG_TRIVIAL(
error) <<
"Failed to unzip file " << name <<
". Directories are not supported. Skipping file.";
411 continue;
412 }
414 fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
415 file.write(buffer.c_str(), buffer.size());
416 file.close();
417 boost::system::error_code ec;
418 bool exists = fs::exists(tmp_path, ec);
420 BOOST_LOG_TRIVIAL(
error) <<
"Failed to find unzipped file at " << tmp_path <<
". Terminating Preset updater synchorinzation." ;
422 return;
423 }
424 fs::rename(tmp_path, target_path, ec);
425 if (ec) {
426 BOOST_LOG_TRIVIAL(
error) <<
"Failed to rename unzipped file at " << tmp_path <<
". Terminating Preset updater synchorinzation. Error message: " << ec.message();
428 return;
429 }
430
431
432 if (name.substr(name.size() - 3) == "idx")
433 vendors_with_status.emplace_back(name.substr(0, name.size() - 4), VendorStatus::IN_ARCHIVE);
434 }
435 }
436 }
438 }
439
440
441
444 return;
445 }
446 auto archive_it = std::find_if(vendors_with_status.begin(), vendors_with_status.end(),
447 [&index](const std::pair<std::string, VendorStatus>& element) { return element.first == index.vendor(); });
448
449
450 const auto vendor_it = vendors.find(index.vendor());
451 if (vendor_it == vendors.end()) {
452
453 BOOST_LOG_TRIVIAL(debug) << "No such vendor: " << index.vendor();
454 if (archive_it != vendors_with_status.end())
455 archive_it->second = VendorStatus::IN_CACHE;
456 continue;
457 }
458
459 if (archive_it != vendors_with_status.end())
460 archive_it->second = VendorStatus::INSTALLED;
461
462 const VendorProfile &vendor = vendor_it->second;
463 const std::string idx_path = (
cache_path / (vendor.id +
".idx")).string();
464 const std::string idx_path_temp = (
cache_vendor_path / (vendor.id +
".idx")).string();
465
466
467 {
469 try {
470 new_index.
load(idx_path_temp);
471 } catch (const std::exception & ) {
472 BOOST_LOG_TRIVIAL(
error) <<
format(
"Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_temp, vendor.name);
473 continue;
474 }
475 if (new_index.
version() < index.version()) {
476 BOOST_LOG_TRIVIAL(info) <<
format(
"The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.", idx_path_temp, vendor.name);
477 continue;
478 }
480
481
482
483 try {
484 index.load(idx_path);
485 }
486 catch (const std::exception& ) {
487 BOOST_LOG_TRIVIAL(
error) <<
format(
"Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path, vendor.name);
488 continue;
489 }
491 return;
492 }
493
494
495 const auto recommended_it = index.recommended();
496 if (recommended_it == index.end()) {
497 BOOST_LOG_TRIVIAL(
error) <<
format(
"No recommended version for vendor: %1%, invalid index?", vendor.name);
498 continue;
499 }
500
501 const auto recommended = recommended_it->config_version;
502
503 BOOST_LOG_TRIVIAL(debug) <<
format(
"Got index for vendor: %1%: current version: %2%, recommended version: %3%",
504 vendor.name,
505 vendor.config_version.to_string(),
506 recommended.to_string());
507
508 if (vendor.config_version >= recommended) { continue; }
509
510
511 if (archive_it != vendors_with_status.end())
512 archive_it->second = VendorStatus::NEW_VERSION;
513
514
515 const auto path_in_cache =
cache_path / (vendor.id +
".ini");
516 BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for vendor: " << vendor.name;
517 const auto bundle_url =
format(
"%1%/%2%.ini", vendor.config_update_url, recommended.to_string());
518 const auto bundle_path =
cache_path / (vendor.id +
".ini");
519 if (!
get_file(bundle_url, bundle_path))
520 continue;
522 return;
523
524 VendorProfile vp;
525 try {
527 } catch (const std::exception& e) {
528 BOOST_LOG_TRIVIAL(
error) <<
format(
"Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.id, bundle_path, e.what());
529 continue;
530 }
531
532
533 for (const auto& model : vp.models) {
534 for (const std::string& res : { model.bed_texture, model.bed_model, model.thumbnail} ) {
535 if (! res.empty()) {
536 try
537 {
539 }
540 catch (const std::exception& e)
541 {
542 BOOST_LOG_TRIVIAL(
error) <<
"Failed to get " << res <<
" for " << vp.id <<
" " << model.id <<
": " << e.what();
543 }
544
545 }
547 return;
548 }
549 }
550 }
551
552
553 for (const std::pair<std::string, VendorStatus >& vendor : vendors_with_status) {
554 if (vendor.second == VendorStatus::IN_ARCHIVE) {
555
556
559 if (!fs::exists(idx_path_in_archive))
560 continue;
562 try {
563 index.
load(idx_path_in_archive);
564 }
565 catch (const std::exception& ) {
566 BOOST_LOG_TRIVIAL(
error) <<
format(
"Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_in_archive, vendor.first);
567 continue;
568 }
570 if (recommended_it == index.
end()) {
571 BOOST_LOG_TRIVIAL(
error) <<
format(
"No recommended version for vendor: %1%, invalid index? (%2%)", vendor.first, idx_path_in_archive);
572 continue;
573 }
574 const auto recommended = recommended_it->config_version;
575 if (!fs::exists(ini_path_in_archive)){
576
577 const std::string fixed_url = GUI::wxGetApp().app_config->profile_folder_url();
578 const auto bundle_url =
format(
"%1%/%2%/%3%.ini", fixed_url, vendor.first, recommended.to_string());
579 if (!
get_file(bundle_url, ini_path_in_archive))
580 continue;
581 } else {
582
583
584 VendorProfile vp;
585 try {
587 } catch (const std::exception& e) {
588 BOOST_LOG_TRIVIAL(
error) <<
format(
"Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_archive, e.what());
589 continue;
590 }
591 if (vp.config_version != recommended) {
592 const std::string fixed_url = GUI::wxGetApp().app_config->profile_folder_url();
593 const auto bundle_url =
format(
"%1%/%2%/%3%.ini", fixed_url, vendor.first, recommended.to_string());
594 if (!
get_file(bundle_url, ini_path_in_archive))
595 continue;
596 }
597 }
598
599 VendorProfile vp;
600 try {
602 }
603 catch (const std::exception& e) {
604 BOOST_LOG_TRIVIAL(
error) <<
format(
"Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_archive, e.what());
605 continue;
606 }
607 for (const auto& model : vp.models) {
608 if (!model.thumbnail.empty()) {
609 try
610 {
612 }
613 catch (const std::exception& e)
614 {
615 BOOST_LOG_TRIVIAL(
error) <<
"Failed to get " << model.thumbnail <<
" for " << vp.id <<
" " << model.id <<
": " << e.what();
616 }
617 }
619 return;
620 }
621 } else if (vendor.second == VendorStatus::IN_CACHE) {
622
625 const auto idx_path_in_cache =
cache_path / (vendor.first +
".idx");
626
627 if (!fs::exists(idx_path_in_archive) || !fs::exists(idx_path_in_cache))
628 continue;
629
630
632 try {
633 index_cache.
load(idx_path_in_cache);
634 }
635 catch (const std::exception& ) {
636 BOOST_LOG_TRIVIAL(
error) <<
format(
"Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_in_cache, vendor.first);
637 continue;
638 }
639 const auto recommended_it_cache = index_cache.
recommended();
640 if (recommended_it_cache == index_cache.
end()) {
641 BOOST_LOG_TRIVIAL(
error) <<
format(
"No recommended version for vendor: %1%, invalid index? (%2%)", vendor.first, idx_path_in_cache);
642 continue;
643 }
644 const auto recommended_cache = recommended_it_cache->config_version;
645
647 try {
648 index_archive.
load(idx_path_in_archive);
649 }
650 catch (const std::exception& ) {
651 BOOST_LOG_TRIVIAL(
error) <<
format(
"Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_in_archive, vendor.first);
652 continue;
653 }
654 const auto recommended_it_archive = index_archive.
recommended();
655 if (recommended_it_archive == index_archive.
end()) {
656 BOOST_LOG_TRIVIAL(
error) <<
format(
"No recommended version for vendor: %1%, invalid index? (%2%)", vendor.first, idx_path_in_archive);
657 continue;
658 }
659 const auto recommended_archive = recommended_it_archive->config_version;
660
661 if (recommended_archive <= recommended_cache) {
662
663
664
665 continue;
666 }
667
668
669 if (!fs::exists(ini_path_in_archive) || fs::is_empty(ini_path_in_archive)) {
670
671 const fs::path ini_path_in_rsrc =
rsrc_path / (vendor.first +
".ini");
672 if (!fs::exists(ini_path_in_rsrc)) {
673
674 continue;
675 }
676
677 VendorProfile vp;
678 try {
680 }
681 catch (const std::exception& e) {
682 BOOST_LOG_TRIVIAL(
error) <<
format(
"Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_rsrc, e.what());
683 continue;
684 }
685 const auto bundle_url =
format(
"%1%/%2%.ini", vp.config_update_url, recommended_archive.to_string());
686 if (!
get_file(bundle_url, ini_path_in_archive)) {
687 BOOST_LOG_TRIVIAL(
error) <<
format(
"Failed to open vendor .ini file when checking missing resources: %1%", ini_path_in_rsrc);
688 continue;
689 }
690 } else {
691
692
693 VendorProfile vp;
694 try {
696 }
697 catch (const std::exception& e) {
698 BOOST_LOG_TRIVIAL(
error) <<
format(
"Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_archive, e.what());
699 continue;
700 }
701 if (vp.config_version != recommended_archive) {
702 const auto bundle_url =
format(
"%1%/%2%.ini", vp.config_update_url, recommended_archive.to_string());
703 if (!
get_file(bundle_url, ini_path_in_archive)) {
704 BOOST_LOG_TRIVIAL(
error) <<
format(
"Failed to open vendor .ini file when checking missing resources: %1%", ini_path_in_archive);
705 continue;
706 }
707 }
708 }
709
710 if (!fs::exists(ini_path_in_archive)) {
711 BOOST_LOG_TRIVIAL(
error) <<
"Resources check failed to find ini file for vendor: " << vendor.first;
712 continue;
713 }
714
715 VendorProfile vp;
716 try {
718 }
719 catch (const std::exception& e) {
720 BOOST_LOG_TRIVIAL(
error) <<
format(
"Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_archive, e.what());
721 continue;
722 }
723 for (const auto& model : vp.models) {
724 if (!model.thumbnail.empty()) {
725 try
726 {
728 }
729 catch (const std::exception& e)
730 {
731 BOOST_LOG_TRIVIAL(
error) <<
"Failed to get " << model.thumbnail <<
" for " << vp.id <<
" " << model.id <<
": " << e.what();
732 }
733 }
735 return;
736 }
737 } else if (vendor.second == VendorStatus::INSTALLED || vendor.second == VendorStatus::NEW_VERSION) {
738
739
740
741 const auto path_in_vendor =
vendor_path / (vendor.first +
".ini");
742 if(!fs::exists(path_in_vendor))
743 continue;
744 VendorProfile vp;
745 try {
747 }
748 catch (const std::exception& e) {
749 BOOST_LOG_TRIVIAL(
error) <<
format(
"Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, path_in_vendor, e.what());
750 continue;
751 }
752 for (const auto& model : vp.models) {
753 for (const std::string& res : { model.bed_texture, model.bed_model, model.thumbnail }) {
754 if (!model.thumbnail.empty()) {
755 try
756 {
758 }
759 catch (const std::exception& e)
760 {
761 BOOST_LOG_TRIVIAL(
error) <<
"Failed to get " << model.thumbnail <<
" for " << vp.id <<
" " << model.id <<
": " << e.what();
762 }
763 }
765 return;
766 }
767 }
768 }
769 }
770}
int exists(char *filename)
Definition loaddrv.c:45
mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
Definition miniz.c:7870
void mz_zip_zero_struct(mz_zip_archive *pZip)
Definition miniz.c:3792
mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
Definition miniz.c:4528
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
Definition miniz.c:7959
unsigned int mz_uint
Definition miniz.h:489
int mz_bool
Definition miniz.h:492
@ IN_ARCHIVE
Definition ConfigWizard_private.hpp:63
bool open_zip_reader(mz_zip_archive *zip, const std::string &fname)
Definition miniz_extension.cpp:62
bool close_zip_reader(mz_zip_archive *zip)
Definition miniz_extension.cpp:72
void get_missing_resource(const std::string &vendor, const std::string &filename, const std::string &url) const
Definition PresetUpdater.cpp:264
#define stat
Definition unistd.h:53