diff options
Diffstat (limited to 'linden/indra/mac_updater/mac_updater.cpp')
-rw-r--r-- | linden/indra/mac_updater/mac_updater.cpp | 194 |
1 files changed, 143 insertions, 51 deletions
diff --git a/linden/indra/mac_updater/mac_updater.cpp b/linden/indra/mac_updater/mac_updater.cpp index 58819a2..a30f024 100644 --- a/linden/indra/mac_updater/mac_updater.cpp +++ b/linden/indra/mac_updater/mac_updater.cpp | |||
@@ -537,8 +537,7 @@ bool isDirWritable(FSRef &dir) | |||
537 | 537 | ||
538 | static void utf8str_to_HFSUniStr255(HFSUniStr255 *dest, const char* src) | 538 | static void utf8str_to_HFSUniStr255(HFSUniStr255 *dest, const char* src) |
539 | { | 539 | { |
540 | LLWString wstr = utf8str_to_wstring(src); | 540 | llutf16string utf16str = utf8str_to_utf16str(src); |
541 | llutf16string utf16str = wstring_to_utf16str(wstr); | ||
542 | 541 | ||
543 | dest->length = utf16str.size(); | 542 | dest->length = utf16str.size(); |
544 | if(dest->length > 255) | 543 | if(dest->length > 255) |
@@ -550,6 +549,13 @@ static void utf8str_to_HFSUniStr255(HFSUniStr255 *dest, const char* src) | |||
550 | memcpy(dest->unicode, utf16str.data(), sizeof(UniChar)* dest->length); /* Flawfinder: ignore */ | 549 | memcpy(dest->unicode, utf16str.data(), sizeof(UniChar)* dest->length); /* Flawfinder: ignore */ |
551 | } | 550 | } |
552 | 551 | ||
552 | static std::string HFSUniStr255_to_utf8str(const HFSUniStr255* src) | ||
553 | { | ||
554 | llutf16string string16((U16*)&(src->unicode), src->length); | ||
555 | std::string result = utf16str_to_utf8str(string16); | ||
556 | return result; | ||
557 | } | ||
558 | |||
553 | int restoreObject(const char* aside, const char* target, const char* path, const char* object) | 559 | int restoreObject(const char* aside, const char* target, const char* path, const char* object) |
554 | { | 560 | { |
555 | char source[PATH_MAX]; /* Flawfinder: ignore */ | 561 | char source[PATH_MAX]; /* Flawfinder: ignore */ |
@@ -598,6 +604,123 @@ void filterFile(const char* filename) | |||
598 | system(temp); /* Flawfinder: ignore */ | 604 | system(temp); /* Flawfinder: ignore */ |
599 | } | 605 | } |
600 | 606 | ||
607 | static bool isFSRefViewerBundle(FSRef *targetRef) | ||
608 | { | ||
609 | bool result = false; | ||
610 | CFURLRef targetURL = NULL; | ||
611 | CFBundleRef targetBundle = NULL; | ||
612 | CFStringRef targetBundleID = NULL; | ||
613 | |||
614 | targetURL = CFURLCreateFromFSRef(NULL, targetRef); | ||
615 | |||
616 | if(targetURL == NULL) | ||
617 | { | ||
618 | llinfos << "Error creating target URL." << llendl; | ||
619 | } | ||
620 | else | ||
621 | { | ||
622 | targetBundle = CFBundleCreate(NULL, targetURL); | ||
623 | } | ||
624 | |||
625 | if(targetBundle == NULL) | ||
626 | { | ||
627 | llinfos << "Failed to create target bundle." << llendl; | ||
628 | } | ||
629 | else | ||
630 | { | ||
631 | targetBundleID = CFBundleGetIdentifier(targetBundle); | ||
632 | } | ||
633 | |||
634 | if(targetBundleID == NULL) | ||
635 | { | ||
636 | llinfos << "Couldn't retrieve target bundle ID." << llendl; | ||
637 | } | ||
638 | else | ||
639 | { | ||
640 | if(CFStringCompare(targetBundleID, CFSTR("com.secondlife.indra.viewer"), 0) == kCFCompareEqualTo) | ||
641 | { | ||
642 | // This is the bundle we're looking for. | ||
643 | result = true; | ||
644 | } | ||
645 | else | ||
646 | { | ||
647 | llinfos << "Target bundle ID mismatch." << llendl; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | // Don't release targetBundleID -- since we don't retain it, it's released when targetBundle is released. | ||
652 | if(targetURL != NULL) | ||
653 | CFRelease(targetURL); | ||
654 | if(targetBundle != NULL) | ||
655 | CFRelease(targetBundle); | ||
656 | |||
657 | return result; | ||
658 | } | ||
659 | |||
660 | // Search through the directory specified by 'parent' for an item that appears to be a Second Life viewer. | ||
661 | static OSErr findAppBundleOnDiskImage(FSRef *parent, FSRef *app) | ||
662 | { | ||
663 | FSIterator iterator; | ||
664 | bool found = false; | ||
665 | |||
666 | OSErr err = FSOpenIterator( parent, kFSIterateFlat, &iterator ); | ||
667 | if(!err) | ||
668 | { | ||
669 | do | ||
670 | { | ||
671 | ItemCount actualObjects = 0; | ||
672 | Boolean containerChanged = false; | ||
673 | FSCatalogInfo info; | ||
674 | FSRef ref; | ||
675 | HFSUniStr255 unicodeName; | ||
676 | err = FSGetCatalogInfoBulk( | ||
677 | iterator, | ||
678 | 1, | ||
679 | &actualObjects, | ||
680 | &containerChanged, | ||
681 | kFSCatInfoNodeFlags, | ||
682 | &info, | ||
683 | &ref, | ||
684 | NULL, | ||
685 | &unicodeName ); | ||
686 | |||
687 | if(actualObjects == 0) | ||
688 | break; | ||
689 | |||
690 | if(!err) | ||
691 | { | ||
692 | // Call succeeded and not done with the iteration. | ||
693 | std::string name = HFSUniStr255_to_utf8str(&unicodeName); | ||
694 | |||
695 | llinfos << "Considering \"" << name << "\"" << llendl; | ||
696 | |||
697 | if(info.nodeFlags & kFSNodeIsDirectoryMask) | ||
698 | { | ||
699 | // This is a directory. See if it's a .app | ||
700 | if(name.find(".app") != std::string::npos) | ||
701 | { | ||
702 | // Looks promising. Check to see if it has the right bundle identifier. | ||
703 | if(isFSRefViewerBundle(&ref)) | ||
704 | { | ||
705 | // This is the one. Return it. | ||
706 | *app = ref; | ||
707 | found = true; | ||
708 | } | ||
709 | } | ||
710 | } | ||
711 | } | ||
712 | } | ||
713 | while(!err && !found); | ||
714 | |||
715 | FSCloseIterator(iterator); | ||
716 | } | ||
717 | |||
718 | if(!err && !found) | ||
719 | err = fnfErr; | ||
720 | |||
721 | return err; | ||
722 | } | ||
723 | |||
601 | void *updatethreadproc(void*) | 724 | void *updatethreadproc(void*) |
602 | { | 725 | { |
603 | char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ | 726 | char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ |
@@ -670,57 +793,15 @@ void *updatethreadproc(void*) | |||
670 | // Sanity check: make sure the target is a bundle with the right identifier | 793 | // Sanity check: make sure the target is a bundle with the right identifier |
671 | if(err == noErr) | 794 | if(err == noErr) |
672 | { | 795 | { |
673 | CFURLRef targetURL = NULL; | ||
674 | CFBundleRef targetBundle = NULL; | ||
675 | CFStringRef targetBundleID = NULL; | ||
676 | |||
677 | // Assume the worst... | 796 | // Assume the worst... |
678 | err = -1; | 797 | err = -1; |
679 | |||
680 | targetURL = CFURLCreateFromFSRef(NULL, &targetRef); | ||
681 | 798 | ||
682 | if(targetURL == NULL) | 799 | if(isFSRefViewerBundle(&targetRef)) |
683 | { | ||
684 | llinfos << "Error creating target URL." << llendl; | ||
685 | } | ||
686 | else | ||
687 | { | 800 | { |
688 | targetBundle = CFBundleCreate(NULL, targetURL); | 801 | // This is the bundle we're looking for. |
689 | } | 802 | err = noErr; |
690 | 803 | replacingTarget = true; | |
691 | if(targetBundle == NULL) | ||
692 | { | ||
693 | llinfos << "Failed to create target bundle." << llendl; | ||
694 | } | ||
695 | else | ||
696 | { | ||
697 | targetBundleID = CFBundleGetIdentifier(targetBundle); | ||
698 | } | ||
699 | |||
700 | if(targetBundleID == NULL) | ||
701 | { | ||
702 | llinfos << "Couldn't retrieve target bundle ID." << llendl; | ||
703 | } | ||
704 | else | ||
705 | { | ||
706 | if(CFStringCompare(targetBundleID, CFSTR("com.secondlife.indra.viewer"), 0) == kCFCompareEqualTo) | ||
707 | { | ||
708 | // This is the bundle we're looking for. | ||
709 | err = noErr; | ||
710 | replacingTarget = true; | ||
711 | } | ||
712 | else | ||
713 | { | ||
714 | llinfos << "Target bundle ID mismatch." << llendl; | ||
715 | } | ||
716 | } | 804 | } |
717 | |||
718 | // Don't release targetBundleID -- since we don't retain it, it's released when targetBundle is released. | ||
719 | if(targetURL != NULL) | ||
720 | CFRelease(targetURL); | ||
721 | if(targetBundle != NULL) | ||
722 | CFRelease(targetBundle); | ||
723 | |||
724 | } | 805 | } |
725 | 806 | ||
726 | // Make sure the target's parent directory is writable. | 807 | // Make sure the target's parent directory is writable. |
@@ -943,13 +1024,24 @@ void *updatethreadproc(void*) | |||
943 | 1024 | ||
944 | // Get an FSRef to the new application on the disk image | 1025 | // Get an FSRef to the new application on the disk image |
945 | FSRef sourceRef; | 1026 | FSRef sourceRef; |
946 | snprintf(temp, sizeof(temp), "%s/mnt/Second Life.app", tempDir); | 1027 | FSRef mountRef; |
1028 | snprintf(temp, sizeof(temp), "%s/mnt", tempDir); | ||
947 | 1029 | ||
948 | llinfos << "Source application is: " << temp << llendl; | 1030 | llinfos << "Disk image mount point is: " << temp << llendl; |
949 | 1031 | ||
950 | err = FSPathMakeRef((UInt8 *)temp, &sourceRef, NULL); | 1032 | err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL); |
951 | if(err != noErr) | 1033 | if(err != noErr) |
1034 | { | ||
1035 | llinfos << "Couldn't make FSRef to disk image mount point." << llendl; | ||
952 | throw 0; | 1036 | throw 0; |
1037 | } | ||
1038 | |||
1039 | err = findAppBundleOnDiskImage(&mountRef, &sourceRef); | ||
1040 | if(err != noErr) | ||
1041 | { | ||
1042 | llinfos << "Couldn't find application bundle on mounted disk image." << llendl; | ||
1043 | throw 0; | ||
1044 | } | ||
953 | 1045 | ||
954 | FSRef asideRef; | 1046 | FSRef asideRef; |
955 | char aside[MAX_PATH]; /* Flawfinder: ignore */ | 1047 | char aside[MAX_PATH]; /* Flawfinder: ignore */ |