home *** CD-ROM | disk | FTP | other *** search
- /*
- ** openurl.library - universal URL display and browser launcher library
- ** Written by Troels Walsted Hansen <troels@thule.no>
- ** Placed in the public domain.
- **
- ** Module with utility functions used by the other library functions.
- */
-
- #include "library_common.h"
- #include "library_api.h"
- #include "library_prefs.h"
- #include "library_util.h"
- #include "handler.h"
-
- /**************************************************************************
- *
- * Definitions.
- *
- */
-
- #define FINDPORT_NUM 100 /* how many FindPort() to do while waiting */
- #define FINDPORT_TIME 10 /* how many seconds to spread those FindPort() over */
-
- struct PlaceHolder
- {
- char ph_Char;
- char *ph_String;
- };
-
- /**************************************************************************
- *
- * Prototypes.
- *
- */
-
- static STRPTR ExpandPlaceHolders(STRPTR template, struct PlaceHolder *ph, int num);
- static BOOL WriteToFile(STRPTR filename, STRPTR str);
- static STRPTR WaitForRexxPort(STRPTR port);
- static STRPTR FindRexxPort(struct List *list, STRPTR name);
- static BOOL SendRexxMsg(struct MsgPort *replyport, STRPTR rxport, STRPTR rxcmd);
-
- /**************************************************************************
- *
- * Externally visible functions.
- *
- */
-
- BOOL SendToBrowser(STRPTR url, struct List *portlist, struct MsgPort *mp,
- BOOL Show, BOOL ToFront, BOOL NewWindow, BOOL Launch)
- {
- BOOL retval = FALSE;
- STRPTR cmd = NULL;
- struct PlaceHolder ph[1];
- struct URL_BrowserNode *bn;
-
- /* set up the placeholder mapping */
-
- ph[0].ph_Char = 'u'; ph[0].ph_String = url;
-
- /* try to find one of the browsers in the list */
-
- for(bn = (struct URL_BrowserNode *)Prefs->up_BrowserList.mlh_Head;
- bn->ubn_Node.mln_Succ;
- bn = (struct URL_BrowserNode *)bn->ubn_Node.mln_Succ)
- {
- STRPTR port = FindRexxPort(portlist, bn->ubn_Port);
- if(port)
- {
- /* send uniconify msg */
-
- if(Show && *bn->ubn_ShowCmd)
- SendRexxMsg(mp, port, bn->ubn_ShowCmd);
-
- /* send screentofront command */
-
- if(ToFront && *bn->ubn_ToFrontCmd)
- SendRexxMsg(mp, port, bn->ubn_ToFrontCmd);
-
- /* try sending openurl msg */
-
- if(!(cmd = ExpandPlaceHolders(NewWindow ? bn->ubn_OpenURLWCmd : bn->ubn_OpenURLCmd, ph, 1)))
- goto done;
-
- if(!(retval = SendRexxMsg(mp, port, cmd)))
- {
- FreeVec(cmd);
- cmd = NULL;
- }
- else goto done;
- }
- }
-
- /* no running browser, launch a new one */
-
- if(!Launch) goto done;
-
- for(bn = (struct URL_BrowserNode *)Prefs->up_BrowserList.mlh_Head;
- bn->ubn_Node.mln_Succ;
- bn = (struct URL_BrowserNode *)bn->ubn_Node.mln_Succ)
- {
- BOOL startonly;
- STRPTR filepart;
- char c = '\0';
- BPTR lock;
- LONG error;
-
- if(!*bn->ubn_Path) continue;
-
- /* compose commandline */
-
- if(strstr(bn->ubn_Path, "%u"))
- startonly = TRUE;
- else
- startonly = FALSE;
-
- if(!(cmd = ExpandPlaceHolders(bn->ubn_Path, ph, 1)))
- goto done;
-
- filepart = FilePart(bn->ubn_Path);
-
- if(filepart)
- {
- c = *filepart;
- *filepart = '\0';
- }
-
- lock = Lock(bn->ubn_Path, ACCESS_READ);
-
- if(filepart) *filepart = c;
-
- /* start the browser */
-
- error = SystemTags(cmd, SYS_Asynch, TRUE,
- SYS_Input, Open("NIL:", MODE_NEWFILE),
- SYS_Output, NULL,
- lock ? NP_CurrentDir : TAG_IGNORE, lock,
- TAG_DONE);
-
- FreeVec(cmd);
- cmd = NULL;
-
- if(error)
- {
- if(lock) UnLock(lock);
- continue;
- }
-
- if(!startonly)
- {
- STRPTR rxport;
-
- /* send urlopen command */
-
- if(!(cmd = ExpandPlaceHolders(bn->ubn_OpenURLCmd, ph, 1)))
- goto done;
-
- /* wait for the port to appear */
-
- if((rxport = WaitForRexxPort(bn->ubn_Port)))
- retval = SendRexxMsg(mp, rxport, cmd);
-
- break;
- }
- else
- {
- retval = TRUE;
- break;
- }
- }
-
- done:
- if(cmd) FreeVec(cmd);
- return(retval);
- }
-
- /**************************************************************************/
-
- BOOL SendToMailer(STRPTR url, struct List *portlist, struct MsgPort *mp,
- BOOL Show, BOOL ToFront, BOOL Launch)
- {
- BOOL retval = FALSE, written = FALSE;
- struct PlaceHolder ph[5];
- STRPTR start, end, address = NULL, subject = NULL, body = NULL, cmd = NULL;
- char filename[32];
- struct URL_MailerNode *mn;
-
- /* parse the URL "mailto:user@host.domain?subject=Subject?body=Body" */
-
- start = url;
-
- while(start)
- {
- STRPTR *tag = NULL;
- int offset = 1;
-
- if(!strnicmp(start, "mailto:", 7))
- {
- tag = &address;
- offset = 7;
- }
- else if(!strnicmp(start, "?subject=", 9))
- {
- tag = &subject;
- offset = 9;
- }
- else if(!strnicmp(start, "?body=", 6))
- {
- tag = &body;
- offset = 6;
- }
-
- end = strchr(start + offset, '?');
-
- if(tag && !*tag)
- {
- if(end) *end = '\0';
-
- if(!(*tag = AllocVec(strlen(start + offset) + 1, MEMF_ANY)))
- goto done;
-
- strcpy(*tag, start + offset);
-
- if(end) *end = '?';
- }
-
- start = end;
- }
-
- if(body)
- SPrintf(filename, "T:OpenURL-MailBody.%08lx", FindTask(NULL));
- else
- {
- written = TRUE;
- strcpy(filename, "NIL:");
- }
-
- /* set up the placeholder mapping */
-
- ph[0].ph_Char = 'a'; ph[0].ph_String = address ? address : (STRPTR)"";
- ph[1].ph_Char = 's'; ph[1].ph_String = subject ? subject : url;
- ph[2].ph_Char = 'b'; ph[2].ph_String = body ? body : (STRPTR)"";
- ph[3].ph_Char = 'f'; ph[3].ph_String = filename;
- ph[4].ph_Char = 'u'; ph[4].ph_String = url;
-
- /* try to find one of the mailers in the list */
-
- for(mn = (struct URL_MailerNode *)Prefs->up_MailerList.mlh_Head;
- mn->umn_Node.mln_Succ;
- mn = (struct URL_MailerNode *)mn->umn_Node.mln_Succ)
- {
- STRPTR port = FindRexxPort(portlist, mn->umn_Port);
-
- if(port)
- {
- /* send uniconify msg */
-
- if(Show && *mn->umn_ShowCmd)
- SendRexxMsg(mp, port, mn->umn_ShowCmd);
-
- /* send screentofront command */
-
- if(ToFront && *mn->umn_ToFrontCmd)
- SendRexxMsg(mp, port, mn->umn_ToFrontCmd);
-
- /* write to temp file */
-
- if(!written && strstr(mn->umn_WriteMailCmd, "%f"))
- written = WriteToFile(filename, body);
-
- /* try sending writemail msg */
-
- if(!(cmd = ExpandPlaceHolders(mn->umn_WriteMailCmd, ph, 5)))
- goto done;
-
- if(!(retval = SendRexxMsg(mp, port, cmd)))
- {
- FreeVec(cmd);
- cmd = NULL;
- }
- else goto done;
- }
- }
-
- /* no running browser, launch a new one */
-
- if(!Launch) goto done;
-
- for(mn = (struct URL_MailerNode *)Prefs->up_MailerList.mlh_Head;
- mn->umn_Node.mln_Succ;
- mn = (struct URL_MailerNode *)mn->umn_Node.mln_Succ)
- {
- BOOL startonly;
- STRPTR filepart;
- char c = '\0';
- BPTR lock;
- LONG error;
-
- if(!*mn->umn_Path) continue;
-
- /* compose commandline */
-
- if(strstr(mn->umn_Path, "%a"))
- startonly = TRUE;
- else
- startonly = FALSE;
-
- if(!written && strstr(mn->umn_Path, "%f"))
- written = WriteToFile(filename, body);
-
- if(!(cmd = ExpandPlaceHolders(mn->umn_Path, ph, 5)))
- goto done;
-
- filepart = FilePart(mn->umn_Path);
-
- if(filepart)
- {
- c = *filepart;
- *filepart = '\0';
- }
-
- lock = Lock(mn->umn_Path, ACCESS_READ);
-
- if(filepart) *filepart = c;
-
- /* start the mailer */
-
- error = SystemTags(cmd, SYS_Asynch, TRUE,
- SYS_Input, Open("NIL:", MODE_NEWFILE),
- SYS_Output, NULL,
- lock ? NP_CurrentDir : TAG_IGNORE, lock,
- TAG_DONE);
-
- FreeVec(cmd);
- cmd = NULL;
-
- if(error)
- {
- if(lock) UnLock(lock);
- continue;
- }
-
- if(!startonly)
- {
- STRPTR rxport;
-
- /* send write mail command */
-
- if(!written && strstr(mn->umn_WriteMailCmd, "%f"))
- written = WriteToFile(filename, body);
-
- if(!(cmd = ExpandPlaceHolders(mn->umn_WriteMailCmd, ph, 5)))
- goto done;
-
- /* wait for the port to appear */
-
- if((rxport = WaitForRexxPort(mn->umn_Port)))
- retval = SendRexxMsg(mp, rxport, cmd);
-
- break;
- }
- else
- {
- retval = TRUE;
- break;
- }
- }
-
- done:
- if(cmd) FreeVec(cmd);
- if(body) FreeVec(body);
- if(subject) FreeVec(subject);
- if(address) FreeVec(address);
-
- return(retval);
- }
-
- /**************************************************************************/
-
- BOOL CopyList(struct List *dst, struct List *src, ULONG size)
- {
- struct Node *n, *new;
-
- /* copy src list into dst, and return success */
-
- for(n = src->lh_Head; n->ln_Succ; n = n->ln_Succ)
- {
- if(!(new = AllocMem(size, MEMF_ANY)))
- {
- FreeList(dst, size);
- return(FALSE);
- }
-
- memcpy(new, n, size);
- AddTail(dst, new);
- }
-
- return(TRUE);
- }
-
- /**************************************************************************/
-
- VOID FreeList(struct List *list, ULONG size)
- {
- struct Node *n;
-
- while((n = RemHead(list)))
- FreeMem(n, size);
- }
-
- /**************************************************************************/
-
- BOOL isdigits(STRPTR str)
- {
- for(;;)
- {
- if(!*str)
- return(TRUE);
- else if(!isdigit(*str))
- return(FALSE);
-
- str++;
- }
- }
-
- /**************************************************************************/
-
- VOID SPrintf(STRPTR to, STRPTR fmt, ...)
- {
- static ULONG fmtfunc = 0x16C04E75;
- RawDoFmt(fmt, &fmt + 1, (APTR)&fmtfunc, to);
- }
-
- /**************************************************************************
- *
- * Local functions.
- *
- */
-
- static STRPTR ExpandPlaceHolders(STRPTR template, struct PlaceHolder *ph, int num)
- {
- STRPTR p, result;
- int i, length = 0;
-
- /* calculate length of result string */
-
- for(p = template; *p; p++)
- {
- for(i = 0; i < num; i++)
- {
- if((*p == '%') && (*(p + 1)== ph[i].ph_Char))
- length += strlen(ph[i].ph_String);
- }
- length++;
- }
-
- /* allocate result string */
-
- if(!(result = AllocVec(length + 1, MEMF_PUBLIC)))
- return(NULL);
-
- /* perform substitution */
-
- for(p = result; *template; template++)
- {
- for(i = 0; i < num; i++)
- if((*template == '%') && (*(template + 1)== ph[i].ph_Char))
- break;
-
- if(i < num)
- {
- strcpy(p, ph[i].ph_String);
- p += strlen(ph[i].ph_String);
- template++;
- continue;
- }
-
- *p++ = *template;
- }
-
- *p = '\0';
-
- return(result);
- }
-
- /**************************************************************************/
-
- static BOOL WriteToFile(STRPTR filename, STRPTR str)
- {
- BOOL retval = FALSE;
- BPTR fh;
- LONG len = strlen(str);
-
- if((fh = Open(filename, MODE_NEWFILE)))
- {
- if(Write(fh, str, len) == len)
- retval = TRUE;
-
- Close(fh);
- }
-
- return(retval);
- }
-
- /**************************************************************************/
-
- static STRPTR WaitForRexxPort(STRPTR port)
- {
- LONG i, delay;
-
- /* (busy) wait for the port to appear */
-
- delay = (FINDPORT_TIME * TICKS_PER_SECOND) / FINDPORT_NUM;
-
- for(i = 0; i < FINDPORT_NUM; i++)
- {
- STRPTR rxport;
-
- Forbid();
- rxport = FindRexxPort(&SysBase->PortList, port);
- Permit();
-
- if(rxport) return(rxport);
-
- if(SetSignal(0, 0) & SIGBREAKF_CTRL_C)
- return(NULL);
-
- Delay(delay);
- }
-
- return(NULL);
- }
-
- /**************************************************************************/
-
- static STRPTR FindRexxPort(struct List *list, STRPTR name)
- {
- struct Node *n;
- ULONG len;
-
- /* find a rexx port, allowing a .<number> extension */
-
- len = strlen(name);
-
- for(n = list->lh_Head; n->ln_Succ; n = n->ln_Succ)
- {
- if(n->ln_Name && !strncmp(n->ln_Name, name, len) &&
- (n->ln_Name[len] == '\0' ||
- (n->ln_Name[len] == '.' && isdigits(&n->ln_Name[len+1]))))
- {
- return(n->ln_Name);
- }
- }
-
- return(NULL);
- }
-
- /**************************************************************************/
-
- static BOOL SendRexxMsg(struct MsgPort *replyport, STRPTR rxport, STRPTR rxcmd)
- {
- struct HandlerMsg hm = {0};
- hm.hm_Msg.mn_ReplyPort = replyport;
- hm.hm_Msg.mn_Length = sizeof(struct HandlerMsg);
- hm.hm_Type = HMT_AREXX;
- hm.hm_ARexxPort = rxport;
- hm.hm_ARexxCmd = rxcmd;
-
- /* check that the handler is still there */
-
- if(!AttemptSemaphore(&HandlerSemaphore))
- {
- /* yup, still there */
-
- PutMsg(HandlerMsgPort, (struct Message *)&hm);
- WaitPort(replyport);
- GetMsg(replyport);
- return(hm.hm_Success);
- }
- else
- {
- /* eek, gone */
-
- ReleaseSemaphore(&HandlerSemaphore);
- return(FALSE);
- }
- }
-