char * url_os_specified_browser(char *url) { #ifdef _WINDOWS return(mswin_reg_default_browser(url)); #elif OSX_TARGET if(mime_os_specific_access()){ return(cpystr("open")); } #endif /* do nothing here */ return(NULL); }
/* * Return the command based on either the mimetype or the file * extension. Mime-type always takes precedence. * * mime_type - mime-type of the file we're looking at * mime_ext - file extension given us by the mime data * cmd - buffer to copy the resulting command into * chk - whether or not we should check the file extension * * Returns: 1 on success, 0 on failure */ int mime_get_os_mimetype_command(char *mime_type, char *mime_ext, char *cmd, int clen, int chk, int *sp_hndlp) { #ifdef _WINDOWS int ret; LPTSTR mime_type_lpt, mime_ext_lpt; mime_type_lpt = utf8_to_lptstr(mime_type); mime_ext_lpt = utf8_to_lptstr(mime_ext); ret = mswin_reg_viewer(mime_type_lpt, mime_ext_lpt, cmd, clen, chk); if(mime_type_lpt) fs_give((void **) &mime_type_lpt); if(mime_ext_lpt) fs_give((void **) &mime_ext_lpt); return ret; #elif OSX_TARGET /* * if we wanted to be more like PC-Pine, we'd try checking * the mime-type of mime_ext and seeing if that matches * with our mime-type, which is safe for opening */ if(!mime_os_specific_access()) return(0); /* don't want to use Mail or something for a part alpine is good at */ if(!strucmp(mime_type, "message/rfc822")) return(0); return(osx_build_mime_type_cmd(mime_type, cmd, clen, sp_hndlp) || (chk && mime_ext && *mime_ext && osx_build_mime_ext_cmd(mime_ext, cmd, clen, sp_hndlp))); #else return 0; #endif }
/* * Given a mime-type, return the file extension if there is one * * Returns: 1 on success, 0 on failure */ int mime_get_os_ext_from_mimetype(char *mime_type, char *file_ext, int file_ext_len) { #ifdef _WINDOWS int ret; LPTSTR x, mime_type_lpt, file_ext_lpt; mime_type_lpt = utf8_to_lptstr(mime_type); if(mime_type_lpt){ if(file_ext){ file_ext_lpt = (LPTSTR) fs_get(file_ext_len * sizeof(TCHAR)); file_ext_lpt[0] = '\0'; } else file_ext_lpt = NULL; } ret = mswin_reg_mime_ext(mime_type_lpt, file_ext_lpt, (size_t) file_ext_len); /* convert answer back to UTF-8 */ if(ret && file_ext_lpt && file_ext){ char *u; u = lptstr_to_utf8(file_ext_lpt); if(u){ strncpy(file_ext, u, file_ext_len); file_ext[file_ext_len-1] = '\0'; fs_give((void **) &u); } } if(mime_type_lpt) fs_give((void **) &mime_type_lpt); if(file_ext_lpt) fs_give((void **) &file_ext_lpt); return ret; #elif OSX_TARGET if(!mime_os_specific_access()) return(0); #ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER CFStringRef mime_ref = NULL, type_id_ref = NULL, ext_ref = NULL; if(!mime_type || !*mime_type) return 0; /* This for if we built on OS X >= 10.3 but run on < 10.3 */ if(&UTTypeCreatePreferredIdentifierForTag == NULL) return 0; if((mime_ref = CFStringCreateWithCString(NULL, mime_type, kCFStringEncodingASCII)) == NULL) return 0; if((type_id_ref = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mime_ref, NULL)) == NULL) return 0; if((ext_ref = UTTypeCopyPreferredTagWithClass(type_id_ref, kUTTagClassFilenameExtension)) == NULL) return 0; if((CFStringGetCString(ext_ref, file_ext, (CFIndex)file_ext_len - 1, kCFStringEncodingASCII)) == false) return 0; file_ext[file_ext_len - 1] = '\0'; return 1; #else return 0; #endif /* AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER */ #else return 0; #endif /* OSX_TARGET */ }
/* ---------------------------------------------------------------------- Execute the given mailcap command Args: cmd -- the command to execute image_file -- the file the data is in needsterminal -- does this command want to take over the terminal? ----*/ void exec_mailcap_cmd(MCAP_CMD_S *mc_cmd, char *image_file, int needsterminal) { #ifdef _WINDOWS STARTUPINFO start_info; PROCESS_INFORMATION proc_info; WINHAND childProcess; int success = 0; char *cmd; LPTSTR image_file_lpt = NULL; LPTSTR cmd_lpt = NULL; /* no special handling yet, but could be used to replace '*' hack */ if(mc_cmd) cmd = mc_cmd->command; else return; dprint((9, "run_viewer: command=%s\n", cmd ? cmd : "?")) ; if(image_file) image_file_lpt = utf8_to_lptstr(image_file); /* Set to READONLY so the viewer can't try to edit it and keep it around */ if(image_file_lpt) SetFileAttributes(image_file_lpt, FILE_ATTRIBUTE_READONLY); if(*cmd == '*' || (*cmd == '\"' && *(cmd+1) == '*')){ /* * It has been asked that there be the ability to do an * "Open With..." on attachments like you can from the * Windows file browser. After looking into this, it * seems that the only way to do this would be through * an undocumented hack. Here, we would pass "openas" as * the verb to mswin_shell_exec (also some changes in * mswin_shell_exec). Since this is the delicate world * of attachment handling, it seems right not to rely on * a hack. The interface wouldn't be too clean anyways, * as we would have to download the attachment only to * display the "Open With..." dialog. Go figure, some * things Microsoft just wants to keep to themselves. */ /* * 2/1/2007. No idea when the above comment was written, but it is * documented now at least. The below two urls describe the "openas" verb: * * http://blogs.msdn.com/oldnewthing/archive/2004/11/26/270710.aspx * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ * shellcc/platform/shell/programmersguide/shell_basics/ * shell_basics_extending/context.asp */ success = mswin_shell_exec(cmd, &childProcess) == 0; } else{ memset(&proc_info, 0, sizeof(proc_info)); memset(&start_info, 0, sizeof(start_info)); start_info.dwFlags = STARTF_FORCEONFEEDBACK; start_info.wShowWindow = SW_SHOWNORMAL; if(cmd) cmd_lpt = utf8_to_lptstr(cmd); if(CreateProcess(NULL, cmd_lpt, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &start_info, &proc_info) == TRUE){ q_status_message(SM_ORDER, 0, 4, "VIEWER command completed"); dprint ((3, "CreatProcess(%s) Success.\n", cmd ? cmd : "?")); childProcess = proc_info.hProcess; success = 1; } if(cmd_lpt) fs_give((void **) &cmd_lpt); } if(!success){ int rc = (int) GetLastError(); if(image_file_lpt) SetFileAttributes(image_file_lpt, FILE_ATTRIBUTE_NORMAL); our_unlink(image_file); q_status_message2(SM_ORDER, 3, 4, "\007Can't start viewer. %s%s.", (rc == 2 || rc == 3) ? "Viewer not found: " : (rc == 8) ? "Not enough memory" : "Windows error ", (rc == 2 || rc == 3) ? cmd : (rc == 8) ? "" : int2string(rc)); } if(image_file_lpt) fs_give((void **) &image_file_lpt); #elif OSX_TARGET char *command = NULL, *result_file = NULL, *p; char **r_file_h; PIPE_S *syspipe; int mode; if(!mc_cmd) return; if(mc_cmd->special_handling){ char *rhost; if(mime_os_specific_access()) osx_launch_special_handling(mc_cmd, image_file); else{ q_status_message(SM_ORDER, 0, 4, "VIEWER command cancelled"); our_unlink(image_file); } } else { char *cmd = mc_cmd->command; size_t l; l = 32 + strlen(cmd) + (2*strlen(image_file)); p = command = (char *) fs_get((l+1) * sizeof(char)); if(!needsterminal) /* put in background if it doesn't need terminal */ *p++ = '('; snprintf(p, l+1-(p-command), "%s", cmd); p += strlen(p); if(!needsterminal){ if(p-command+2 < l+1){ *p++ = ')'; *p++ = ' '; *p++ = '&'; } } if(p-command < l+1) *p++ = '\n'; if(p-command < l+1) *p = '\0'; dprint((9, "exec_mailcap_cmd: command=%s\n", command ? command : "?")); mode = PIPE_RESET; if(needsterminal == 1) r_file_h = NULL; else{ mode |= PIPE_WRITE | PIPE_STDERR; result_file = temp_nam(NULL, "pine_cmd"); r_file_h = &result_file; } if(syspipe = open_system_pipe(command, r_file_h, NULL, mode, 0, pipe_callback, NULL)){ close_system_pipe(&syspipe, NULL, pipe_callback); if(needsterminal == 1) q_status_message(SM_ORDER, 0, 4, "VIEWER command completed"); else if(needsterminal == 2) display_output_file(result_file, "VIEWER", " command result", 1); else display_output_file(result_file, "VIEWER", " command launched", 1); } else q_status_message1(SM_ORDER, 3, 4, "Cannot spawn command : %s", cmd); fs_give((void **)&command); if(result_file) fs_give((void **)&result_file); } #else char *command = NULL, *result_file = NULL, *p, *cmd, *q, *psef; char **r_file_h; PIPE_S *syspipe; int mode; size_t l; /* no os-specific command handling */ if(mc_cmd) cmd = mc_cmd->command; else return; #ifdef PSEFCMD psef = fs_get((60 + strlen(PSEFCMD) + strlen(image_file))*sizeof(char)); sprintf(psef, "PSEF=`%s | /bin/grep \"%s\" | /bin/grep -v grep`", PSEFCMD, image_file); q = fs_get((80 + 2*strlen(psef))*sizeof(char)); /* bigger than 62 */ sprintf(q, "/bin/sh -c '(%s; while test -n \"$PSEF\" ; do %s ; sleep %d ; done)' ;", psef, psef, ps_global->sleep); fs_give((void **) &psef); #else q = cpystr(""); #endif /* PSEFCMD */ l = 32 + strlen(cmd) + 2*strlen(image_file) + strlen(q); p = command = (char *)fs_get((l+1) * sizeof(char)); if(!needsterminal) /* put in background if it doesn't need terminal */ *p++ = '('; snprintf(p, l+1-(p-command), "%s ; %s rm -f %s", cmd, q, image_file); fs_give((void **)&q); command[l] = '\0'; p += strlen(p); if(!needsterminal && (p-command)+5 < l){ *p++ = ')'; *p++ = ' '; *p++ = '&'; } *p++ = '\n'; *p = '\0'; dprint((9, "exec_mailcap_cmd: command=%s\n", command ? command : "?")); mode = PIPE_RESET; if(needsterminal == 1) r_file_h = NULL; else{ mode |= PIPE_WRITE | PIPE_STDERR; result_file = temp_nam(NULL, "pine_cmd"); r_file_h = &result_file; } if((syspipe = open_system_pipe(command, r_file_h, NULL, mode, 0, pipe_callback, NULL)) != NULL){ close_system_pipe(&syspipe, NULL, pipe_callback); if(needsterminal == 1) q_status_message(SM_ORDER, 0, 4, "VIEWER command completed"); else if(needsterminal == 2) display_output_file(result_file, "VIEWER", " command result", 1); else display_output_file(result_file, "VIEWER", " command launched", 1); } else q_status_message1(SM_ORDER, 3, 4, "Cannot spawn command : %s", cmd); fs_give((void **)&command); if(result_file) fs_give((void **)&result_file); #endif }
/* * Returns the mailcap entry for type/subtype from the successfull * mailcap entry, or NULL if none. Command string still contains % stuff. */ MailcapEntry * mc_get_command(int type, char *subtype, BODY *body, int check_extension, int *sp_handlingp) { MailcapEntry *mc; char tmp_subtype[256], tmp_ext[16], *ext = NULL; dprint((5, "- mc_get_command(%s/%s) -\n", body_type_names(type), subtype ? subtype : "?")); if(type == TYPETEXT && (!subtype || !strucmp(subtype, "plain")) && F_ON(F_SHOW_TEXTPLAIN_INT, ps_global)) return(NULL); mc_init(); if(check_extension){ char *fname; MT_MAP_T e2b; /* * Special handling for when we're looking at what's likely * binary application data. Look for a file name extension * that we might use to hook a helper app to. * * NOTE: This used to preclude an "app/o-s" mailcap entry * since this took precedence. Now that there are * typically two scans through the check_extension * mechanism, the mailcap entry now takes precedence. */ if((fname = get_filename_parameter(NULL, 0, body, &e2b.from.ext)) != NULL && e2b.from.ext && e2b.from.ext[0]){ if(strlen(e2b.from.ext) < sizeof(tmp_ext) - 2){ strncpy(ext = tmp_ext, e2b.from.ext - 1, sizeof(tmp_ext)); /* remember it */ tmp_ext[sizeof(tmp_ext)-1] = '\0'; if(mt_srch_mime_type(mt_srch_by_ext, &e2b)){ type = e2b.to.mime.type; /* mapped type */ strncpy(subtype = tmp_subtype, e2b.to.mime.subtype, sizeof(tmp_subtype)-1); tmp_subtype[sizeof(tmp_subtype)-1] = '\0'; fs_give((void **) &e2b.to.mime.subtype); body = NULL; /* the params no longer apply */ } } fs_give((void **) &fname); } else{ if(fname) fs_give((void **) &fname); return(NULL); } } for(mc = MailcapData.head; mc; mc = mc->next) if(mc_ctype_match(type, subtype, mc->contenttype) && mc_passes_test(mc, type, subtype, body)){ dprint((9, "mc_get_command: type=%s/%s, command=%s\n", body_type_names(type), subtype ? subtype : "?", mc->command ? mc->command : "?")); return(mc); } if(mime_os_specific_access()){ static MailcapEntry fake_mc; static char fake_cmd[1024]; char tmp_mime_type[256]; memset(&fake_mc, 0, sizeof(MailcapEntry)); fake_cmd[0] = '\0'; fake_mc.command = fake_cmd; snprintf(tmp_mime_type, sizeof(tmp_mime_type), "%s/%s", body_types[type], subtype); if(mime_get_os_mimetype_command(tmp_mime_type, ext, fake_cmd, sizeof(fake_cmd), check_extension, sp_handlingp)) return(&fake_mc); } return(NULL); }