]> granicus.if.org Git - neomutt/commitdiff
Add an URL parser, and support for mailto URLs.
authorThomas Roessler <roessler@does-not-exist.org>
Tue, 22 Aug 2000 21:55:33 +0000 (21:55 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Tue, 22 Aug 2000 21:55:33 +0000 (21:55 +0000)
Makefile.am
main.c
parse.c
protos.h
url.c [new file with mode: 0644]
url.h [new file with mode: 0644]

index d05ab3a9779d024a93e8a80294961e8e9eca6075..3dfb8a52d25b7e43e15c46cf7fcba65c08d807e6 100644 (file)
@@ -30,7 +30,8 @@ mutt_SOURCES = $(BUILT_SOURCES) \
        rfc822.c rfc1524.c rfc2047.c rfc2231.c \
        score.c send.c sendlib.c signal.c sort.c \
        status.c system.c thread.c charset.c history.c lib.c \
-       muttlib.c editmsg.c utf8.c mbyte.c wcwidth.c gettext.c
+       muttlib.c editmsg.c utf8.c mbyte.c wcwidth.c gettext.c \
+       url.c
 
 mutt_LDADD = @MUTT_LIB_OBJECTS@ @LIBOBJS@ $(LIBIMAP) $(MUTTLIBS) \
        $(INTLLIBS) $(LIBICONV)
@@ -72,7 +73,7 @@ non_us_sources = pgp.c pgpinvoke.c pgpkey.c pgplib.c sha1dgst.c \
 
 EXTRA_mutt_SOURCES = account.c mutt_sasl.c mutt_socket.c pop.c pgp.c \
        pgpinvoke.c pgpkey.c pgplib.c sha1dgst.c gnupgparse.c resize.c \
-       dotlock.c remailer.c browser.h mbyte.h remailer.h
+       dotlock.c remailer.c browser.h mbyte.h remailer.h url.h
 
 EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h account.h \
        attach.h buffy.h charset.h copy.h dotlock.h functions.h gen_defs \
diff --git a/main.c b/main.c
index 219f6163fe43ee2518f4179496084f7519012a1f..b59dd11ed90551ff72d67021a2972e90932fa09d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -23,6 +23,7 @@
 #include "mutt_curses.h"
 #include "keymap.h"
 #include "mailbox.h"
+#include "url.h"
 #include "reldate.h"
 
 #include <string.h>
@@ -657,7 +658,8 @@ int main (int argc, char **argv)
     FILE *fin = NULL;
     char buf[LONG_STRING];
     char *tempfile = NULL, *infile = NULL;
-
+    char *bodytext = NULL;
+    
     if (!option (OPTNOCURSES))
       mutt_flushinp ();
 
@@ -672,7 +674,12 @@ int main (int argc, char **argv)
        msg->env = mutt_new_envelope ();
 
       for (i = optind; i < argc; i++)
-       msg->env->to = rfc822_parse_adrlist (msg->env->to, argv[i]);
+      {
+       if (url_check_scheme (argv[i]) == U_MAILTO)
+         url_parse_mailto (msg->env, &bodytext, argv[i]);
+       else
+         msg->env->to = rfc822_parse_adrlist (msg->env->to, argv[i]);
+      }
 
       if (option (OPTAUTOEDIT) && !msg->env->to && !msg->env->cc)
       {
@@ -682,36 +689,45 @@ int main (int argc, char **argv)
        exit (1);
       }
 
-      msg->env->subject = safe_strdup (subject);
-      
+      if (subject)
+       msg->env->subject = safe_strdup (subject);
+
       if (includeFile)
        infile = includeFile;
     }
 
-    if (infile)
+    if (infile || bodytext)
     {
-      if (mutt_strcmp ("-", infile) == 0)
-       fin = stdin;
-      else
+      if (infile)
       {
-       char path[_POSIX_PATH_MAX];
-
-       strfcpy (path, infile, sizeof (path));
-       mutt_expand_path (path, sizeof (path));
-       if ((fin = fopen (path, "r")) == NULL)
+       if (mutt_strcmp ("-", infile) == 0)
+         fin = stdin;
+       else 
        {
-         if (!option (OPTNOCURSES))
-           mutt_endwin (NULL);
-         perror (path);
-         exit (1);
+         char path[_POSIX_PATH_MAX];
+         
+         strfcpy (path, infile, sizeof (path));
+         mutt_expand_path (path, sizeof (path));
+         if ((fin = fopen (path, "r")) == NULL)
+         {
+           if (!option (OPTNOCURSES))
+             mutt_endwin (NULL);
+           perror (path);
+           exit (1);
+         }
        }
       }
+      else
+       fin = NULL;
+
       mutt_mktemp (buf);
       tempfile = safe_strdup (buf);
 
       if (draftFile)
        msg->env = mutt_read_rfc822_header (fin, NULL, 1, 0);
 
+      /* is the following if still needed? */
+      
       if (tempfile)
       {
        FILE *fout;
@@ -725,14 +741,18 @@ int main (int argc, char **argv)
          FREE (&tempfile);
          exit (1);
        }
-
-       mutt_copy_stream (fin, fout);
+       if (fin)
+         mutt_copy_stream (fin, fout);
+       else if (bodytext)
+         fputs (bodytext, fout);
        fclose (fout);
-       if (fin != stdin)
+       if (fin && fin != stdin)
          fclose (fin);
       }
     }
 
+    safe_free ((void **) &bodytext);
+    
     if (attach)
     {
       LIST *t = attach;
diff --git a/parse.c b/parse.c
index ddc6ea79698470b8f7b2c27c41ebeddbe03178f2..95d62fa1ffd47b942e291686f087a7b9bb825059 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -908,6 +908,304 @@ void mutt_parse_mime_message (CONTEXT *ctx, HEADER *cur)
   }
 }
 
+int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short user_hdrs, short weed,
+                           short do_2047, LIST **lastp, char **in_reply_to)
+{
+  int matched = 0;
+  LIST *last = NULL;
+  
+  if (lastp)
+    last = *lastp;
+  
+  switch (tolower (line[0]))
+  {
+    case 'a':
+    if (mutt_strcasecmp (line+1, "pparently-to") == 0)
+    {
+      e->to = rfc822_parse_adrlist (e->to, p);
+      matched = 1;
+    }
+    else if (mutt_strcasecmp (line+1, "pparently-from") == 0)
+    {
+      e->from = rfc822_parse_adrlist (e->from, p);
+      matched = 1;
+    }
+    break;
+    
+    case 'b':
+    if (mutt_strcasecmp (line+1, "cc") == 0)
+    {
+      e->bcc = rfc822_parse_adrlist (e->bcc, p);
+      matched = 1;
+    }
+    break;
+    
+    case 'c':
+    if (mutt_strcasecmp (line+1, "c") == 0)
+    {
+      e->cc = rfc822_parse_adrlist (e->cc, p);
+      matched = 1;
+    }
+    else if (mutt_strncasecmp (line + 1, "ontent-", 7) == 0)
+    {
+      if (mutt_strcasecmp (line+8, "type") == 0)
+      {
+       if (hdr)
+         mutt_parse_content_type (p, hdr->content);
+       matched = 1;
+      }
+      else if (mutt_strcasecmp (line+8, "transfer-encoding") == 0)
+      {
+       if (hdr)
+         hdr->content->encoding = mutt_check_encoding (p);
+       matched = 1;
+      }
+      else if (mutt_strcasecmp (line+8, "length") == 0)
+      {
+       if (hdr)
+       {
+         if ((hdr->content->length = atoi (p)) < 0)
+           hdr->content->length = -1;
+       }
+       matched = 1;
+      }
+      else if (mutt_strcasecmp (line+8, "description") == 0)
+      {
+       if (hdr)
+       {
+         mutt_str_replace (&hdr->content->description, p);
+         rfc2047_decode (&hdr->content->description);
+       }
+       matched = 1;
+      }
+      else if (mutt_strcasecmp (line+8, "disposition") == 0)
+      {
+       if (hdr)
+         parse_content_disposition (p, hdr->content);
+       matched = 1;
+      }
+    }
+    break;
+    
+    case 'd':
+    if (!mutt_strcasecmp ("ate", line + 1))
+    {
+      mutt_str_replace (&e->date, p);
+      if (hdr)
+       hdr->date_sent = mutt_parse_date (p, hdr);
+      matched = 1;
+    }
+    break;
+    
+    case 'e':
+    if (!mutt_strcasecmp ("xpires", line + 1) &&
+       hdr && mutt_parse_date (p, NULL) < time (NULL))
+      hdr->expired = 1;
+    break;
+    
+    case 'f':
+    if (!mutt_strcasecmp ("rom", line + 1))
+    {
+      e->from = rfc822_parse_adrlist (e->from, p);
+      matched = 1;
+    }
+    break;
+    
+    case 'i':
+    if (!mutt_strcasecmp (line+1, "n-reply-to"))
+    {
+      if (hdr && in_reply_to)
+      {
+       *in_reply_to = strdup (p);
+       if (do_2047)
+         rfc2047_decode (in_reply_to);
+      }
+    }
+    break;
+    
+    case 'l':
+    if (!mutt_strcasecmp (line + 1, "ines"))
+    {
+      if (hdr)
+       hdr->lines = atoi (p);
+      matched = 1;
+    }
+    break;
+    
+    case 'm':
+    if (!mutt_strcasecmp (line + 1, "ime-version"))
+    {
+      if (hdr)
+       hdr->mime = 1;
+      matched = 1;
+    }
+    else if (!mutt_strcasecmp (line + 1, "essage-id"))
+    {
+      /* We add a new "Message-Id:" when building a message */
+      safe_free ((void **) &e->message_id);
+      e->message_id = extract_message_id (p);
+      matched = 1;
+    }
+    else if (!mutt_strncasecmp (line + 1, "ail-", 4))
+    {
+      if (!mutt_strcasecmp (line + 5, "reply-to"))
+      {
+       /* override the Reply-To: field */
+       rfc822_free_address (&e->reply_to);
+       e->reply_to = rfc822_parse_adrlist (e->reply_to, p);
+       matched = 1;
+      }
+      else if (!mutt_strcasecmp (line + 5, "followup-to"))
+      {
+       e->mail_followup_to = rfc822_parse_adrlist (e->mail_followup_to, p);
+       matched = 1;
+      }
+    }
+    break;
+    
+    case 'r':
+    if (!mutt_strcasecmp (line + 1, "eferences"))
+    {
+      mutt_free_list (&e->references);
+      e->references = mutt_parse_references (p);
+      matched = 1;
+    }
+    else if (!mutt_strcasecmp (line + 1, "eply-to"))
+    {
+      e->reply_to = rfc822_parse_adrlist (e->reply_to, p);
+      matched = 1;
+    }
+    else if (!mutt_strcasecmp (line + 1, "eturn-path"))
+    {
+      e->return_path = rfc822_parse_adrlist (e->return_path, p);
+      matched = 1;
+    }
+    else if (!mutt_strcasecmp (line + 1, "eceived"))
+    {
+      if (hdr && !hdr->received)
+      {
+       char *d = strchr (p, ';');
+       
+       if (d)
+         hdr->received = mutt_parse_date (d + 1, NULL);
+      }
+    }
+    break;
+    
+    case 's':
+    if (!mutt_strcasecmp (line + 1, "ubject"))
+    {
+      if (!e->subject)
+       e->subject = safe_strdup (p);
+      matched = 1;
+    }
+    else if (!mutt_strcasecmp (line + 1, "ender"))
+    {
+      e->sender = rfc822_parse_adrlist (e->sender, p);
+      matched = 1;
+    }
+    else if (!mutt_strcasecmp (line + 1, "tatus"))
+    {
+      if (hdr)
+      {
+       while (*p)
+       {
+         switch(*p)
+         {
+           case 'r':
+           hdr->replied = 1;
+           break;
+           case 'O':
+           if (option (OPTMARKOLD))
+             hdr->old = 1;
+           break;
+           case 'R':
+           hdr->read = 1;
+           break;
+         }
+         p++;
+       }
+      }
+      matched = 1;
+    }
+    else if ((!mutt_strcasecmp ("upersedes", line + 1) ||
+             !mutt_strcasecmp ("upercedes", line + 1)) && hdr)
+      e->supersedes = safe_strdup (p);
+    break;
+    
+    case 't':
+    if (mutt_strcasecmp (line+1, "o") == 0)
+    {
+      e->to = rfc822_parse_adrlist (e->to, p);
+      matched = 1;
+    }
+    break;
+    
+    case 'x':
+    if (mutt_strcasecmp (line+1, "-status") == 0)
+    {
+      if (hdr)
+      {
+       while (*p)
+       {
+         switch (*p)
+         {
+           case 'A':
+           hdr->replied = 1;
+           break;
+           case 'D':
+           hdr->deleted = 1;
+           break;
+           case 'F':
+           hdr->flagged = 1;
+           break;
+           default:
+           break;
+         }
+         p++;
+       }
+      }
+      matched = 1;
+    }
+    else if (mutt_strcasecmp (line+1, "-label") == 0)
+    {
+      e->x_label = safe_strdup(p);
+      matched = 1;
+    }
+    
+    default:
+    break;
+  }
+  
+  /* Keep track of the user-defined headers */
+  if (!matched && user_hdrs)
+  {
+    /* restore the original line */
+    line[strlen (line)] = ':';
+    
+    if (weed && option (OPTWEED) && mutt_matches_ignore (line, Ignore)
+       && !mutt_matches_ignore (line, UnIgnore))
+      goto done;
+
+    if (last)
+    {
+      last->next = mutt_new_list ();
+      last = last->next;
+    }
+    else
+      last = e->userhdrs = mutt_new_list ();
+    last->data = safe_strdup (line);
+    if (do_2047)
+      rfc2047_decode (&last->data);
+  }
+
+  done:
+  
+  *lastp = last;
+  return matched;
+}
+  
+  
 /* mutt_read_rfc822_header() -- parses a RFC822 header
  *
  * Args:
@@ -984,285 +1282,8 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs,
     if (!*p)
       continue; /* skip empty header fields */
 
-    switch (tolower (line[0]))
-    {
-      case 'a':
-       if (mutt_strcasecmp (line+1, "pparently-to") == 0)
-       {
-         e->to = rfc822_parse_adrlist (e->to, p);
-         matched = 1;
-       }
-       else if (mutt_strcasecmp (line+1, "pparently-from") == 0)
-       {
-         e->from = rfc822_parse_adrlist (e->from, p);
-         matched = 1;
-       }
-       break;
-
-      case 'b':
-       if (mutt_strcasecmp (line+1, "cc") == 0)
-       {
-         e->bcc = rfc822_parse_adrlist (e->bcc, p);
-         matched = 1;
-       }
-       break;
-
-      case 'c':
-       if (mutt_strcasecmp (line+1, "c") == 0)
-       {
-         e->cc = rfc822_parse_adrlist (e->cc, p);
-         matched = 1;
-       }
-       else if (mutt_strncasecmp (line + 1, "ontent-", 7) == 0)
-       {
-         if (mutt_strcasecmp (line+8, "type") == 0)
-         {
-           if (hdr)
-             mutt_parse_content_type (p, hdr->content);
-           matched = 1;
-         }
-         else if (mutt_strcasecmp (line+8, "transfer-encoding") == 0)
-         {
-           if (hdr)
-             hdr->content->encoding = mutt_check_encoding (p);
-           matched = 1;
-         }
-         else if (mutt_strcasecmp (line+8, "length") == 0)
-         {
-           if (hdr)
-           {
-             if ((hdr->content->length = atoi (p)) < 0)
-               hdr->content->length = -1;
-           }
-           matched = 1;
-         }
-         else if (mutt_strcasecmp (line+8, "description") == 0)
-         {
-           if (hdr)
-           {
-             mutt_str_replace (&hdr->content->description, p);
-             rfc2047_decode (&hdr->content->description);
-           }
-           matched = 1;
-         }
-         else if (mutt_strcasecmp (line+8, "disposition") == 0)
-         {
-           if (hdr)
-             parse_content_disposition (p, hdr->content);
-           matched = 1;
-         }
-       }
-       break;
-
-      case 'd':
-       if (!mutt_strcasecmp ("ate", line + 1))
-       {
-         mutt_str_replace (&e->date, p);
-         if (hdr)
-           hdr->date_sent = mutt_parse_date (p, hdr);
-         matched = 1;
-       }
-       break;
-
-      case 'e':
-       if (!mutt_strcasecmp ("xpires", line + 1) &&
-           hdr && mutt_parse_date (p, NULL) < time (NULL))
-         hdr->expired = 1;
-       break;
-
-      case 'f':
-       if (!mutt_strcasecmp ("rom", line + 1))
-       {
-         e->from = rfc822_parse_adrlist (e->from, p);
-         matched = 1;
-       }
-       break;
-
-      case 'i':
-       if (!mutt_strcasecmp (line+1, "n-reply-to"))
-       {
-         if (hdr)
-         {
-           in_reply_to = strdup (p);
-           rfc2047_decode (&in_reply_to);
-         }
-       }
-       break;
-
-      case 'l':
-       if (!mutt_strcasecmp (line + 1, "ines"))
-       {
-         if (hdr)
-           hdr->lines = atoi (p);
-         matched = 1;
-       }
-       break;
-
-      case 'm':
-       if (!mutt_strcasecmp (line + 1, "ime-version"))
-       {
-         if (hdr)
-           hdr->mime = 1;
-         matched = 1;
-       }
-       else if (!mutt_strcasecmp (line + 1, "essage-id"))
-       {
-         /* We add a new "Message-Id:" when building a message */
-         safe_free ((void **) &e->message_id);
-         e->message_id = extract_message_id (p);
-         matched = 1;
-       }
-       else if (!mutt_strncasecmp (line + 1, "ail-", 4))
-       {
-         if (!mutt_strcasecmp (line + 5, "reply-to"))
-         {
-           /* override the Reply-To: field */
-           rfc822_free_address (&e->reply_to);
-           e->reply_to = rfc822_parse_adrlist (e->reply_to, p);
-           matched = 1;
-         }
-         else if (!mutt_strcasecmp (line + 5, "followup-to"))
-         {
-           e->mail_followup_to = rfc822_parse_adrlist (e->mail_followup_to, p);
-           matched = 1;
-         }
-       }
-       break;
-
-      case 'r':
-       if (!mutt_strcasecmp (line + 1, "eferences"))
-       {
-         mutt_free_list (&e->references);
-         e->references = mutt_parse_references (p);
-         matched = 1;
-       }
-       else if (!mutt_strcasecmp (line + 1, "eply-to"))
-       {
-         e->reply_to = rfc822_parse_adrlist (e->reply_to, p);
-         matched = 1;
-       }
-       else if (!mutt_strcasecmp (line + 1, "eturn-path"))
-       {
-         e->return_path = rfc822_parse_adrlist (e->return_path, p);
-         matched = 1;
-       }
-       else if (!mutt_strcasecmp (line + 1, "eceived"))
-       {
-         if (hdr && !hdr->received)
-         {
-           char *d = strchr (p, ';');
-
-           if (d)
-             hdr->received = mutt_parse_date (d + 1, NULL);
-         }
-       }
-       break;
-
-      case 's':
-       if (!mutt_strcasecmp (line + 1, "ubject"))
-       {
-         if (!e->subject)
-           e->subject = safe_strdup (p);
-         matched = 1;
-       }
-       else if (!mutt_strcasecmp (line + 1, "ender"))
-       {
-         e->sender = rfc822_parse_adrlist (e->sender, p);
-         matched = 1;
-       }
-       else if (!mutt_strcasecmp (line + 1, "tatus"))
-       {
-         if (hdr)
-         {
-           while (*p)
-           {
-             switch(*p)
-             {
-               case 'r':
-                 hdr->replied = 1;
-                 break;
-               case 'O':
-                 if (option (OPTMARKOLD))
-                   hdr->old = 1;
-                 break;
-               case 'R':
-                 hdr->read = 1;
-                 break;
-             }
-             p++;
-           }
-         }
-         matched = 1;
-       }
-       else if ((!mutt_strcasecmp ("upersedes", line + 1) ||
-                 !mutt_strcasecmp ("upercedes", line + 1)) && hdr)
-         e->supersedes = safe_strdup (p);
-       break;
-
-      case 't':
-       if (mutt_strcasecmp (line+1, "o") == 0)
-       {
-         e->to = rfc822_parse_adrlist (e->to, p);
-         matched = 1;
-       }
-       break;
-
-      case 'x':
-       if (mutt_strcasecmp (line+1, "-status") == 0)
-       {
-         if (hdr)
-         {
-           while (*p)
-           {
-             switch (*p)
-             {
-               case 'A':
-                 hdr->replied = 1;
-                 break;
-               case 'D':
-                 hdr->deleted = 1;
-                 break;
-               case 'F':
-                 hdr->flagged = 1;
-                 break;
-               default:
-                 break;
-             }
-             p++;
-           }
-         }
-         matched = 1;
-       }
-       else if (mutt_strcasecmp (line+1, "-label") == 0)
-       {
-         e->x_label = safe_strdup(p);
-         matched = 1;
-       }
-           
-      default:
-       break;
-    }
-
-     /* Keep track of the user-defined headers */
-    if (!matched && user_hdrs)
-    {
-      /* restore the original line */
-      line[strlen (line)] = ':';
-
-      if (weed && option (OPTWEED) && mutt_matches_ignore (line, Ignore)
-         && !mutt_matches_ignore (line, UnIgnore))
-       continue;
-
-      if (last)
-      {
-       last->next = mutt_new_list ();
-       last = last->next;
-      }
-      else
-       last = e->userhdrs = mutt_new_list ();
-      last->data = safe_strdup (line);
-      rfc2047_decode (&last->data);
-    }
+    matched = mutt_parse_rfc822_line (e, hdr, line, p, user_hdrs, weed, 1, &last, &in_reply_to);
+    
   }
 
   FREE (&line);
index 1d4b33ab8143a62e808c30c8ec36fc25fb93eb83..b32e2859f9293a4ee6c22a76646ca40ed5b93c09 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -281,6 +281,8 @@ int mutt_parse_mono (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_unmono (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_push (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_rc_line (/* const */ char *, BUFFER *, BUFFER *);
+int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short user_hdrs, short weed,
+                           short do_2047, LIST **lastp, char **in_reply_to);
 int mutt_parse_score (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_unscore (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_unhook (BUFFER *, BUFFER *, unsigned long, BUFFER *);
diff --git a/url.c b/url.c
new file mode 100644 (file)
index 0000000..fa21032
--- /dev/null
+++ b/url.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2000 Thomas Roessler <roessler@guug.de>
+ * 
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ */ 
+
+/*
+ * A simple URL parser.
+ */
+
+#include "mutt.h"
+#include "mapping.h"
+#include "url.h"
+
+#include "mime.h"
+
+#include <ctype.h>
+
+static struct mapping_t UrlMap[] =
+{
+  { "file",    U_FILE },
+#ifdef USE_IMAP
+  { "imap",    U_IMAP },
+#endif
+#ifdef USE_POP
+  { "pop",     U_POP  },
+#endif
+#ifdef USE_SSL
+# ifdef USE_IMAP
+  { "imaps",   U_IMAPS },
+# endif
+# ifdef USE_POP
+  { "pops",    U_POPS  },
+# endif
+#endif
+  { "mailto",  U_MAILTO },
+  { NULL,      U_UNKNOWN}
+};
+
+
+static void url_pct_decode (char *s)
+{
+  char *d;
+  for (d = s; *s; s++)
+  {
+    if (*s == '%' && s[1] && s[2] &&
+       hexval (s[1]) >= 0 && hexval(s[2]) >= 0)
+    {
+      *d++ = (hexval (s[1]) << 4) | (hexval (s[2]));
+      s += 2;
+    }
+    else
+      *d++ = *s;
+  }
+  *d ='\0';
+}
+
+url_scheme_t url_check_scheme (const char *s)
+{
+  char sbuf[STRING];
+  char *t;
+  int i;
+  
+  if (!(t = strchr (s, ':')))
+    return U_UNKNOWN;
+  if ((t - s) + 1 >= sizeof (sbuf))
+    return U_UNKNOWN;
+  
+  strfcpy (sbuf, s, t - s + 1);
+  for (t = sbuf; *t; t++)
+    *t = tolower (*t);
+
+  if ((i = mutt_getvaluebyname (sbuf, UrlMap)) == -1)
+    return U_UNKNOWN;
+  else
+    return (url_scheme_t) i;
+}
+
+int url_parse_file (char *d, const char *src, size_t dl)
+{
+  if (strncasecmp (src, "file:", 5))
+    return -1;
+  else if (!strncasecmp (src, "file://", 7))   /* we don't support remote files */
+    return -1;
+  else
+    strfcpy (d, src + 5, dl);
+  
+  url_pct_decode (d);
+  return 0;
+}
+
+static char *ciss_parse_userhost (ciss_url_t *ciss, char *src)
+{
+  char *t;
+  char *p;
+  char *path;
+  
+  if (strncmp (src, "//", 2))
+    return src;
+  
+  src += 2;
+  
+  if ((path = strchr (src, '/')))
+    *path++ = '\0';
+  
+  if ((t = strchr (src, '@')))
+  {
+    *t = '\0';
+    if ((p = strchr (src, ':')))
+    {
+      *p = '\0';
+      ciss->pass = safe_strdup (p + 1);
+    }
+    ciss->user = safe_strdup (src);
+    t++;
+  }
+  else
+    t = src;
+  
+  if ((p = strchr (t, ':')))
+  {
+    *p++ = '\0';
+    ciss->port = atoi (p);
+  }
+  else
+    ciss->port = 0;
+  
+  ciss->host = safe_strdup (t);
+  return path;
+}
+
+static void ciss_parse_path (ciss_url_t *ciss, char *src)
+{
+  ciss->path = src;
+  url_pct_decode (ciss->path);
+}
+
+int url_parse_ciss (ciss_url_t *ciss, const char *src)
+{
+  char *t, *tmp;
+  
+  if (!(t = strchr (src, ':')))
+    return -1;
+  
+  tmp = safe_strdup (t + 1);
+
+  t = ciss_parse_userhost (ciss, tmp);
+  ciss_parse_path (ciss, t);
+  
+  safe_free ((void **) &tmp);
+
+  return 0;
+}
+
+int url_parse_mailto (ENVELOPE *e, char **body, const char *src)
+{
+  char *t;
+  char *tmp;
+  char *headers;
+  char *tag, *value;
+  char scratch[HUGE_STRING];
+
+  int taglen;
+
+  LIST *last = NULL;
+  
+  if (!(t = strchr (src, ':')))
+    return -1;
+  
+  tmp = safe_strdup (t + 1);
+  if ((headers = strchr (tmp, '?')))
+    *headers++ = '\0';
+
+  url_pct_decode (tmp);
+  e->to = rfc822_parse_adrlist (e->to, tmp);
+
+  tag = headers ? strtok (headers, "&") : NULL;
+  
+  for (; tag; tag = strtok (NULL, "&"))
+  {
+    if ((value = strchr (tag, '=')))
+      *value++ = '\0';
+    if (!value || !*value)
+      continue;
+
+    url_pct_decode (tag);
+    url_pct_decode (value);
+
+    if (!strcasecmp (tag, "body"))
+      mutt_str_replace (body, value);
+    else 
+    {
+      taglen = strlen (tag);
+      /* mutt_parse_rfc822_line makes some assumptions */
+      snprintf (scratch, sizeof (scratch), "%s: %s", tag, value);
+      scratch[taglen] = '\0';
+      value = &scratch[taglen+1];
+      SKIPWS (value);
+      mutt_parse_rfc822_line (e, NULL, scratch, value, 1, 0, 0, &last, NULL);
+    }
+  }
+  
+  safe_free ((void **) &tmp);
+  return 0;
+}
+
diff --git a/url.h b/url.h
new file mode 100644 (file)
index 0000000..5648c34
--- /dev/null
+++ b/url.h
@@ -0,0 +1,43 @@
+#ifndef _URL_H
+# define _URL_H
+
+# include "config.h"
+
+typedef enum url_scheme
+{
+  U_FILE,
+# ifdef USE_POP
+  U_POP,
+# endif
+# ifdef USE_IMAP
+  U_IMAP,
+# endif
+# ifdef USE_SSL
+#  ifdef USE_IMAP
+  U_IMAPS,
+#  endif
+#  ifdef USE_POP
+  U_POPS,
+#  endif
+# endif
+  U_MAILTO,
+  U_UNKNOWN
+}
+url_scheme_t;
+
+typedef struct ciss_url
+{
+  char *user;
+  char *pass;
+  char *host;
+  short port;
+  char  *path;
+} 
+ciss_url_t;
+
+url_scheme_t url_check_scheme (const char *s);
+int url_parse_file (char *d, const char *src, size_t dl);
+int url_parse_ciss (ciss_url_t *ciss, const char *src);
+int url_parse_mailto (ENVELOPE *e, char **body, const char *src);
+
+#endif