Skip to content

Commit

Permalink
Now looks at multiple XML tags to determine product version in MacOS's
Browse files Browse the repository at this point in the history
 Info.plist. Furthermore, if MacOS fails to find the package, it can prompt
 the user to locate the product, so there're some new entry points in the UI
 abstraction.

Also added a cheezy means to check multiple versions, such as:
  "1.0 or 1.1 or 1.2"

Obviously, that needs more robustness.
  • Loading branch information
icculus committed May 25, 2004
1 parent dbf5cbe commit 9d2ea42
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 22 deletions.
20 changes: 20 additions & 0 deletions mojopatch.c
Expand Up @@ -538,6 +538,26 @@ static void _current_operation(const char *fmt, ...)
} /* _current_operation */


/* don't taunt this function. */
int version_ok(const char *ver, const char *allowed_ver)
{
char *ptr;
char *buf = (char *) alloca(strlen(allowed_ver) + 1);
strcpy(buf, allowed_ver);

while ((ptr = strstr(buf, " or ")) != NULL)
{
*ptr = '\0';
if (strcmp(ver, buf) == 0)
return(1);

buf = ptr + 4;
} /* while */

return(strcmp(ver, buf) == 0);
} /* version_ok */


static int _do_xdelta(const char *fmt, ...)
{
char buf[512];
Expand Down
2 changes: 2 additions & 0 deletions platform.h
Expand Up @@ -46,6 +46,8 @@ void _log(const char *fmt, ...);
/* Call this for logging (debug info). */
void _dlog(const char *fmt, ...);

int version_ok(const char *ver, const char *allowed);

/* platform-specific stuff you implement. */
int file_exists(const char *fname);
int file_is_directory(const char *fname);
Expand Down
64 changes: 48 additions & 16 deletions platform_unix.c
Expand Up @@ -220,8 +220,17 @@ static char *find_info_plist_version(char *ptr)
continue;
} /* if */

if ((strcasecmp(tag,"key")==0)&&(strcasecmp(val,"CFBundleVersion")==0))
have_key = 1;
/* You should only use CFBundleShortVersionString, for various
* reasons not worth explaining here. CFBundleVersion is here
* for older products that need to update to the other tag.
*/
if (strcasecmp(tag,"key") == 0)
{
if (strcasecmp(val,"CFBundleVersion") == 0)
have_key = 1;
if (strcasecmp(val,"CFBundleShortVersionString") == 0)
have_key = 1;
} /* if */
} /* while */

return(NULL);
Expand All @@ -245,10 +254,28 @@ static int parse_info_dot_plist(const char *version)
io = NULL;
mem[fsize] = '\0';

ptr = find_info_plist_bundle_id(mem);
if ((ptr == NULL) || (strcasecmp(ptr, ident) != 0))
{
int yes = ui_prompt_ny("We don't think we're looking at the right directory!"
" Are you SURE this is the right place?"
" If you aren't sure, clicking 'Yes' can destroy unrelated files!");
if (!yes)
{
_fatal("Stopping at user's request.");
free(mem);
return(0);
} /* if */
} /* if */

if ( (io = fopen(fname, "r")) == NULL ) goto parse_info_plist_bailed;
if ( (fread(mem, fsize, 1, io)) != 1 ) goto parse_info_plist_bailed;
fclose(io);

ptr = find_info_plist_version(mem);
if (ptr != NULL)
{
if (strcmp(version, ptr) == 0)
if (version_ok(ptr, version))
retval = 1;
else
{
Expand Down Expand Up @@ -311,6 +338,8 @@ int update_version(const char *ver)
} /* update_version */


int manually_locate_product(char *buf, size_t bufsize);

int chdir_by_identifier(const char *str, const char *version)
{
char buf[MAXPATHLEN];
Expand All @@ -322,18 +351,24 @@ int chdir_by_identifier(const char *str, const char *version)

rc = LSFindApplicationForInfo(kLSUnknownCreator, id, NULL, NULL, &url);
CFRelease(id);
if (rc != noErr)
if (rc == noErr)
{
_fatal("Couldn't find product. Perhaps it isn't installed?");
return(0);
b = CFURLGetFileSystemRepresentation(url, TRUE, buf, sizeof (buf));
CFRelease(url);
if (!b)
{
_fatal("Internal error.");
return(0);
} /* if */
} /* if */

b = CFURLGetFileSystemRepresentation(url, TRUE, buf, sizeof (buf));
CFRelease(url);
if (!b)
else
{
_fatal("Internal error.");
return(0);
_log("Couldn't find product. Perhaps it isn't installed?");
if (!manually_locate_product(buf, sizeof (buf)))
{
_fatal("We can't patch the product if we can't find it!");
return(0);
} /* if */
} /* if */

_log("I think the product is installed at [%s].", buf);
Expand All @@ -344,10 +379,7 @@ int chdir_by_identifier(const char *str, const char *version)
return(0);
} /* if */

if (strcmp(version, "") != 0)
return(parse_info_dot_plist(version));

return(1);
return(parse_info_dot_plist(str, version));
} /* chdir_by_identifier */


Expand Down
2 changes: 2 additions & 0 deletions ui.h
Expand Up @@ -16,6 +16,8 @@ void ui_success(const char *str);
void ui_total_progress(int percent);
void ui_status(const char *str);
void ui_title(const char *str);
int ui_prompt_yn(const char *question);
int ui_prompt_ny(const char *question);

#ifdef __cplusplus
}
Expand Down
114 changes: 108 additions & 6 deletions ui_carbon.c
Expand Up @@ -68,39 +68,141 @@ void ui_add_to_log(const char *str, int debugging)
} /* ui_add_to_log */


static void do_msgbox(const char *str, AlertType alert_type)
static int do_msgbox(const char *str, AlertType alert_type,
AlertStdCFStringAlertParamRec *param,
DialogItemIndex *idx)
{
const char *_title = "MojoPatch";
int retval = 0;
DialogItemIndex val = 0;
CFStringRef title = CFStringCreateWithBytes(NULL, _title, strlen(_title),
kCFStringEncodingISOLatin1, 0);
CFStringRef msg = CFStringCreateWithBytes(NULL, str, strlen(str),
kCFStringEncodingISOLatin1, 0);
if ((msg != NULL) && (title != NULL))
{
DialogItemIndex val = 0;
DialogRef dlg = NULL;

if (CreateStandardAlert(alert_type, title, msg, NULL, &dlg) == noErr)
RunStandardAlert(dlg, NULL, &val);
if (CreateStandardAlert(alert_type, title, msg, param, &dlg) == noErr)
{
RunStandardAlert(dlg, NULL, (idx) ? idx : &val);
retval = 1;
} /* if */
} /* if */

if (msg != NULL)
CFRelease(msg);

if (title != NULL)
CFRelease(title);

return(retval);
} /* do_msgbox */


static int ui_prompt_yes_or_no(const char *question, int yes)
{
OSStatus err;
DialogItemIndex item;
AlertStdCFStringAlertParamRec params;
err = GetStandardAlertDefaultParams(&params, kStdCFStringAlertVersionOne);
if (err != noErr)
return(0);

params.movable = TRUE;
params.helpButton = FALSE;
params.defaultText = CFSTR("Yes");
params.cancelText = CFSTR("No");
params.defaultButton = (yes) ? kAlertStdAlertOKButton :
kAlertStdAlertCancelButton;
params.cancelButton = kAlertStdAlertCancelButton;
if (!do_msgbox(question, kAlertCautionAlert, &params, &item))
return(0); /* oh well. */

return(item == kAlertStdAlertOKButton);
} /* ui_prompt_yes_or_no */

int ui_prompt_yn(const char *question)
{
return(ui_prompt_yes_or_no(question, 1));
} /* ui_prompt_yn */

int ui_prompt_ny(const char *question)
{
return(ui_prompt_yes_or_no(question, 1)); /* !!! FIXME! should be zero. */
} /* ui_prompt_ny */


int manually_locate_product(char *buf, size_t bufsize)
{
NavDialogCreationOptions dlgopt;
NavDialogRef dlg;
NavReplyRecord reply;
NavUserAction action;
AEKeyword keyword;
AEDesc desc;
FSRef fsref;
OSStatus rc;
int retval = 0;
int yn;

yn = ui_prompt_yn("We can't find your installation."
" Would you like to show us where it is?");
if (!yn)
{
_log("User chose not to manually locate installation");
return(0);
} /* if */

_log("Creating file selector dialog...");
NavGetDefaultDialogCreationOptions(&dlgopt);
dlgopt.optionFlags |= kNavSupportPackages;
dlgopt.optionFlags |= kNavAllowOpenPackages;
dlgopt.optionFlags &= ~kNavAllowMultipleFiles;
dlgopt.windowTitle = CFSTR("Please select the product's icon and click 'OK'.");
dlgopt.actionButtonLabel = CFSTR("OK");
NavCreateChooseFolderDialog(&dlgopt, NULL, NULL, NULL, &dlg);
NavDialogRun(dlg);
action = NavDialogGetUserAction(dlg);
if (action == kNavUserActionCancel)
_log("User cancelled file selector!");
else
{
NavDialogGetReply(dlg, &reply);
rc = AEGetNthDesc(&reply.selection, 1, typeFSRef, &keyword, &desc);
if (rc != noErr)
_fatal("Unexpected error in AEGetNthDesc: %d\n", (int) rc);
else
{
/* !!! FIXME: Check return values here! */
BlockMoveData(*desc.dataHandle, &fsref, sizeof (fsref));
FSRefMakePath(&fsref, buf, bufsize - 1);
buf[bufsize - 1] = '\0';
AEDisposeDesc(&desc);
retval = 1;
} /* if */

NavDisposeReply(&reply);
} /* else */

NavDialogDispose(dlg);

_log("File selector complete. User %s path.",
retval ? "selected" : "did NOT select");

return(retval);
}


void ui_fatal(const char *str)
{
do_msgbox(str, kAlertStopAlert);
do_msgbox(str, kAlertStopAlert, NULL, NULL);
} /* ui_fatal */


void ui_success(const char *str)
{
do_msgbox(str, kAlertNoteAlert);
do_msgbox(str, kAlertNoteAlert, NULL, NULL);
} /* ui_success */


Expand Down

0 comments on commit 9d2ea42

Please sign in to comment.