From 770fd09b6e6ed8b9ce9c94b9a4dd3d1a55d5594d Mon Sep 17 00:00:00 2001 From: "Alexander G.M. Smith" Date: Sat, 13 Aug 2005 23:43:41 +0000 Subject: [PATCH] Half way through adding some more BeMail related utilities - they use libmail.so which isn't backwards compatibile so they need recompiling for Haiku - thus better to include them here. Also want spam levels of 1E-6 to be visible for genuine messages. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13955 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../spam_filter/SpamFilterConfig.cpp | 2 +- src/bin/Jamfile | 12 + src/bin/bemailtombox.cpp | 436 ++++++++++ src/bin/bemailtombox.rdef | 70 ++ src/bin/mboxtobemail.cpp | 745 ++++++++++++++++++ src/bin/mboxtobemail.rdef | 71 ++ src/bin/spamdbm/spamdbm.rdef | 10 +- 7 files changed, 1340 insertions(+), 6 deletions(-) create mode 100644 src/bin/bemailtombox.cpp create mode 100644 src/bin/bemailtombox.rdef create mode 100644 src/bin/mboxtobemail.cpp create mode 100644 src/bin/mboxtobemail.rdef diff --git a/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilterConfig.cpp b/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilterConfig.cpp index aaa5abdd4d..6be1ea6203 100644 --- a/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilterConfig.cpp +++ b/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilterConfig.cpp @@ -229,7 +229,7 @@ void AGMSBayesianSpamFilterConfig::AttachedToWindow () // Add the box displaying the genuine cutoff ratio, on a line by itself. tempStringPntr = "Genuine below and uncertain above:"; - sprintf (numberString, "%06.4f", (double) fGenuineCutoffRatio); + sprintf (numberString, "%08.6f", (double) fGenuineCutoffRatio); fGenuineCutoffRatioTextBoxPntr = new BTextControl ( tempRect, "genuinecutoffratio", diff --git a/src/bin/Jamfile b/src/bin/Jamfile index 07f8fe86d6..e512e84a30 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -99,6 +99,18 @@ StdBinCommands : be libmail.so ; +# Oddball standard commands that have a resource file or something else +# unusual, but aren't complex enough to have their own subdirectory. +StdBinCommands + bemailtombox.cpp + : be + : bemailtombox.rdef + ; +Package haiku-maildaemon-cvs : + bemailtombox : + boot home config bin ; + +# Finally (must come after all the compile related rules), all the subdirectories that are worth compiling. SubInclude OBOS_TOP src bin addattr ; SubInclude OBOS_TOP src bin bash ; SubInclude OBOS_TOP src bin bc ; diff --git a/src/bin/bemailtombox.cpp b/src/bin/bemailtombox.cpp new file mode 100644 index 0000000000..c21e353e02 --- /dev/null +++ b/src/bin/bemailtombox.cpp @@ -0,0 +1,436 @@ +/****************************************************************************** + * $Id:$ + * + * BeMailToMBox is a utility program (requested by Frank Zschockelt) that + * converts BeOS e-mail files into Unix mailbox files (the kind that Pine + * uses). All the files in the input directory are concatenated with the + * appropriate mbox header lines added between them, and trailing blank lines + * reduced. The resulting text is written to standard output. Command line + * driven. + * + * $Log: BeMailToMBox.cpp,v $ + * Revision 1.1 2002/02/24 18:16:46 agmsmith + * Initial revision + */ + +/* BeOS headers. */ + +#include +#include +#include + +/* Posix headers. */ + +#include +#include +#include +#include +#include + + +/****************************************************************************** + * Globals + */ + +time_t DateStampTime; + /* Time value used for stamping each message header. Incremented by 1 second + for each message, starts out with the current local time. */ + + +/****************************************************************************** + * Global utility function to display an error message and return. The message + * part describes the error, and if ErrorNumber is non-zero, gets the string + * ", error code $X (standard description)." appended to it. If the message + * is NULL then it gets defaulted to "Something went wrong". + */ + +static void DisplayErrorMessage ( + const char *MessageString = NULL, + int ErrorNumber = 0, + const char *TitleString = NULL) +{ + char ErrorBuffer [B_PATH_NAME_LENGTH + 80 /* error message */ + 80]; + + if (TitleString == NULL) + TitleString = "Error Message:"; + + if (MessageString == NULL) + { + if (ErrorNumber == 0) + MessageString = "No error, no message, why bother?"; + else + MessageString = "Something went wrong"; + } + + if (ErrorNumber != 0) + { + sprintf (ErrorBuffer, "%s, error code $%X/%d (%s) has occured.", + MessageString, ErrorNumber, ErrorNumber, strerror (ErrorNumber)); + MessageString = ErrorBuffer; + } + + fputs (TitleString, stderr); + fputc ('\n', stderr); + fputs (MessageString, stderr); + fputc ('\n', stderr); +} + + + +/****************************************************************************** + * Determine if a line of text is the start of another message. Pine mailbox + * files have messages that start with a line that could say something like + * "From agmsmith@achilles.net Fri Oct 31 21:19:36 EST 1997" or maybe something + * like "From POPmail Mon Oct 20 21:12:36 1997" or in a more modern format, + * "From agmsmith@achilles.net Tue Sep 4 09:04:11 2001 -0400". I generalise it + * to "From blah Day MMM NN XX:XX:XX TZONE1 YYYY TZONE2". Blah is an e-mail + * address you can ignore (just treat it as a word separated by spaces). Day + * is a 3 letter day of the week. MMM is a 3 letter month name. NN is the two + * digit day of the week, has a leading space if the day is less than 10. + * XX:XX:XX is the time, the X's are digits. TZONE1 is the old style optional + * time zone of 3 capital letters. YYYY is the four digit year. TZONE2 is the + * optional modern time zone info, a plus or minus sign and 4 digits. Returns + * true if the line of text (ended with a NUL byte, no line feed or carriage + * returns at the end) is the start of a message. + */ + +bool IsStartOfMailMessage (char *LineString) +{ + char *StringPntr; + + /* It starts with "From " */ + + if (memcmp ("From ", LineString, 5) != 0) + return false; + StringPntr = LineString + 4; + while (*StringPntr == ' ') + StringPntr++; + + /* Skip over the e-mail address (or stop at the end of string). */ + + while (*StringPntr != ' ' && *StringPntr != 0) + StringPntr++; + while (*StringPntr == ' ') + StringPntr++; + + /* Look for the 3 letter day of the week. */ + + if (memcmp (StringPntr, "Mon", 3) != 0 && + memcmp (StringPntr, "Tue", 3) != 0 && + memcmp (StringPntr, "Wed", 3) != 0 && + memcmp (StringPntr, "Thu", 3) != 0 && + memcmp (StringPntr, "Fri", 3) != 0 && + memcmp (StringPntr, "Sat", 3) != 0 && + memcmp (StringPntr, "Sun", 3) != 0) + { + fprintf (stderr, "False alarm, not a valid day of the week in \"%s\".\n", + LineString); + return false; + } + StringPntr += 3; + while (*StringPntr == ' ') + StringPntr++; + + /* Look for the 3 letter month code. */ + + if (memcmp (StringPntr, "Jan", 3) != 0 && + memcmp (StringPntr, "Feb", 3) != 0 && + memcmp (StringPntr, "Mar", 3) != 0 && + memcmp (StringPntr, "Apr", 3) != 0 && + memcmp (StringPntr, "May", 3) != 0 && + memcmp (StringPntr, "Jun", 3) != 0 && + memcmp (StringPntr, "Jul", 3) != 0 && + memcmp (StringPntr, "Aug", 3) != 0 && + memcmp (StringPntr, "Sep", 3) != 0 && + memcmp (StringPntr, "Oct", 3) != 0 && + memcmp (StringPntr, "Nov", 3) != 0 && + memcmp (StringPntr, "Dec", 3) != 0) + { + fprintf (stderr, "False alarm, not a valid month name in \"%s\".\n", + LineString); + return false; + } + StringPntr += 3; + while (*StringPntr == ' ') + StringPntr++; + + /* Skip the day of the month. Require at least one digit. */ + + if (*StringPntr < '0' || *StringPntr > '9') + { + fprintf (stderr, "False alarm, not a valid day of the " + "month number in \"%s\".\n", LineString); + return false; + } + while (*StringPntr >= '0' && *StringPntr <= '9') + StringPntr++; + while (*StringPntr == ' ') + StringPntr++; + + /* Check the time. Look for the sequence + digit-digit-colon-digit-digit-colon-digit-digit. */ + + if (StringPntr[0] < '0' || StringPntr[0] > '9' || + StringPntr[1] < '0' || StringPntr[1] > '9' || + StringPntr[2] != ':' || + StringPntr[3] < '0' || StringPntr[3] > '9' || + StringPntr[4] < '0' || StringPntr[4] > '9' || + StringPntr[5] != ':' || + StringPntr[6] < '0' || StringPntr[6] > '9' || + StringPntr[7] < '0' || StringPntr[7] > '9') + { + fprintf (stderr, "False alarm, not a valid time value in \"%s\".\n", + LineString); + return false; + } + StringPntr += 8; + while (*StringPntr == ' ') + StringPntr++; + + /* Look for the optional antique 3 capital letter time zone and skip it. */ + + if (StringPntr[0] >= 'A' && StringPntr[0] <= 'Z' && + StringPntr[1] >= 'A' && StringPntr[1] <= 'Z' && + StringPntr[2] >= 'A' && StringPntr[2] <= 'Z') + { + StringPntr += 3; + while (*StringPntr == ' ') + StringPntr++; + } + + /* Look for the 4 digit year. */ + + if (StringPntr[0] < '0' || StringPntr[0] > '9' || + StringPntr[1] < '0' || StringPntr[1] > '9' || + StringPntr[2] < '0' || StringPntr[2] > '9' || + StringPntr[3] < '0' || StringPntr[3] > '9') + { + fprintf (stderr, "False alarm, not a valid 4 digit year in \"%s\".\n", + LineString); + return false; + } + StringPntr += 4; + while (*StringPntr == ' ') + StringPntr++; + + /* Look for the optional modern time zone and skip over it if present. */ + + if ((StringPntr[0] == '+' || StringPntr[0] == '-') && + StringPntr[1] >= '0' && StringPntr[1] <= '9' && + StringPntr[2] >= '0' && StringPntr[2] <= '9' && + StringPntr[3] >= '0' && StringPntr[3] <= '9' && + StringPntr[4] >= '0' && StringPntr[4] <= '9') + { + StringPntr += 5; + while (*StringPntr == ' ') + StringPntr++; + } + + /* Look for end of string. */ + + if (*StringPntr != 0) + { + fprintf (stderr, "False alarm, extra stuff after the " + "year/time zone in \"%s\".\n", LineString); + return false; + } + + return true; +} + + + +/****************************************************************************** + * Read the input file, convert it to mbox format, and write it to standard + * output. Returns zero if successful, a negative error code if an error + * occured. + */ + +status_t ProcessMessageFile (char *FileName) +{ + char ErrorMessage [B_PATH_NAME_LENGTH + 80]; + int i; + int InputFileDescriptor = -1; + FILE *InputFile = NULL; + int LineNumber; + BString MessageText; + status_t ReturnCode = -1; + char *StringPntr; + char TempString [102400]; + time_t TimeValue; + + fprintf (stderr, "Now processing: \"%s\"\n", FileName); + + /* Open the file. Try to open it in exclusive mode, so that it doesn't + accidentally open the output file, or any other already open file. */ + + InputFileDescriptor = open (FileName, O_RDONLY); + if (InputFileDescriptor < 0) + { + ReturnCode = errno; + DisplayErrorMessage ("Unable to open file", ReturnCode); + return ReturnCode; + } + InputFile = fdopen (InputFileDescriptor, "rb"); + if (InputFile == NULL) + { + ReturnCode = errno; + close (InputFileDescriptor); + DisplayErrorMessage ("fdopen failed to convert file handle to a " + "buffered file", ReturnCode); + return ReturnCode; + } + + /* Extract a text message from the BeMail file. */ + + LineNumber = 0; + while (!feof (InputFile)) + { + /* First read in one line of text. */ + + if (!fgets (TempString, sizeof (TempString), InputFile)) + { + ReturnCode = errno; + if (ferror (InputFile)) + { + sprintf (ErrorMessage, + "Error while reading from \"%s\"", FileName); + DisplayErrorMessage (ErrorMessage, ReturnCode); + goto ErrorExit; + } + break; /* No error, just end of file. */ + } + + /* Remove any trailing control characters (line feed usually, or CRLF). + Might also nuke trailing tabs too. Doesn't usually matter. The main thing + is to allow input files with both LF and CRLF endings (and even CR endings + if you come from the Macintosh world). */ + + StringPntr = TempString + strlen (TempString) - 1; + while (StringPntr >= TempString && *StringPntr < 32) + StringPntr--; + *(++StringPntr) = 0; + + if (LineNumber == 0 && TempString[0] == 0) + continue; /* Skip leading blank lines. */ + LineNumber++; + + /* Prepend the new mbox message header, if the first line of the message + doesn't already have one. */ + + if (LineNumber == 1 && !IsStartOfMailMessage (TempString)) + { + TimeValue = DateStampTime++; + MessageText.Append ("From baron@be.com "); + MessageText.Append (ctime (&TimeValue)); + } + + /* Append the line to the current message text. */ + + MessageText.Append (TempString); + MessageText.Append ("\n"); + } + + /* Remove blank lines from the end of the message (a pet peeve of mine), but + end the message with two new lines to separate it from the next message. */ + + i = MessageText.Length (); + while (i > 0 && (MessageText[i-1] == '\n' || MessageText[i-1] == '\r')) + i--; + MessageText.Truncate (i); + MessageText.Append ("\n\n"); + + /* Write the message out. */ + + if (puts (MessageText.String()) < 0) + { + ReturnCode = errno; + DisplayErrorMessage ("Error while writing the message", ReturnCode); + goto ErrorExit; + } + + ReturnCode = 0; + +ErrorExit: + fclose (InputFile); + return ReturnCode; +} + + + +/****************************************************************************** + * Finally, the main program which drives it all. + */ + +int main (int argc, char** argv) +{ + dirent_t *DirEntPntr; + DIR *DirHandle; + status_t ErrorCode; + char InputPathName [B_PATH_NAME_LENGTH]; + int MessagesDoneCount = 0; + BApplication MyApp ("application/x-vnd.agmsmith.BeMailToMBox"); + const char *StringPntr; + char TempString [1024 + 256]; + + if (argc <= 1 || argc >= 3) + { + printf ("%s is a utility for converting BeMail e-mail\n", argv[0]); + printf ("files to Unix Pine style e-mail files. It could well\n"); + printf ("work with other Unix style mailbox files. Each message in\n"); + printf ("the input directory is converted and sent to the standard\n"); + printf ("output. Usage:\n\n"); + printf ("bemailtombox InputDirectory >OutputFile\n\n"); + printf ("Public domain, by Alexander G. M. Smith.\n"); + printf ("$Id:$\n"); + printf ("$HeadURL: $\n"); + return -10; + } + + /* Set the date stamp to the current time. */ + + DateStampTime = time (NULL); + + /* Try to open the input directory. */ + + memset (InputPathName, 0, sizeof (InputPathName)); + strncpy (InputPathName, argv[1], sizeof (InputPathName) - 2); + DirHandle = opendir (InputPathName); + if (DirHandle == NULL) + { + ErrorCode = errno; + sprintf (TempString, "Problems opening directory named \"%s\".", + InputPathName); + DisplayErrorMessage (TempString, ErrorCode); + return ErrorCode; + } + + /* Append a trailing slash to the directory name, if it needs one. */ + + if (InputPathName [strlen (InputPathName) - 1] != '/') + strcat (InputPathName, "/"); + + ErrorCode = 0; + while (ErrorCode == 0 && (DirEntPntr = readdir (DirHandle)) != NULL) + { + for (StringPntr = DirEntPntr->d_name; *StringPntr != 0; StringPntr++) + if (*StringPntr != '.') + break; + if (*StringPntr == 0) + continue; /* Skip all period names, like . or .. or ... etc. */ + + strcpy (TempString, InputPathName); + strcat (TempString, DirEntPntr->d_name); + ErrorCode = ProcessMessageFile (TempString); + MessagesDoneCount++; + } + closedir (DirHandle); + if (ErrorCode != 0) + { + DisplayErrorMessage ("Stopping early because an error occured", ErrorCode); + return ErrorCode; + } + + fprintf (stderr, "Did %d messages successfully.\n", MessagesDoneCount); + return 0; +} diff --git a/src/bin/bemailtombox.rdef b/src/bin/bemailtombox.rdef new file mode 100644 index 0000000000..5d2d276996 --- /dev/null +++ b/src/bin/bemailtombox.rdef @@ -0,0 +1,70 @@ +/* Resources for the bemailtombox program, mostly for the icon. + $Id:$ */ + +resource app_flags B_SINGLE_LAUNCH | B_ARGV_ONLY; + +resource app_signature "application/x-vnd.agmsmith.bemailtombox"; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + variety = B_APPV_FINAL, + internal = 1, + short_info = "BeMailToMbox $Rev$", + long_info = "BeMailToMbox - BeMail to Unix mailbox file converter. $Id:$" +}; + +resource large_icon array { + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF60606060606060606060606060606060606060606060FFFFFFFF" + $"FFFFFFFF60606060606060606060606060606060606060606060D2D2ACFFFFFF" + $"FFFFFF60606060606060606060606060606060606060606060D2D2D2D2ACFFFF" + $"FFFF6060606060606060606060606060606060606060606060D2D2D2D2ACFFFF" + $"FFFF8686868686868686868686868686868686868686868686D2D2D2D2ACFFFF" + $"FFFF8686868686868686868686868686868686868686868686D2D2D2D2ACFFFF" + $"FFFF8600868686008600000086868600008686008686860086D2D2D2D2ACFFFF" + $"FFFF8600008600008600868600860086860086008686860086D2D2D2ACACFFFF" + $"FFFF8600860086008600868600860086860086860086008686D2D2D2ACACFFFF" + $"FFFF8600860086008600868600860086860086860086008686D2D2D2ACACFFFF" + $"FFFF8600868686008600000086860086860086860086008686D2D2ACACACFFFF" + $"FFFF8600868686008600868600860086860086868600868686D2D2ACACACFFFF" + $"FFFF8600868686008600868600860086860086868600868686D2D2ACACACFFFF" + $"FFFF8600868686008600868600860086860086860086008686D2D2ACACACFFFF" + $"FFFF8600868686008600868600860086860086860086008686D2D2ACACACFFFF" + $"FFFF8600868686008600868600860086860086860086008686D2D2ACACACFFFF" + $"FFFF8600868686008600868600860086860086008686860086D2ACACACACFFFF" + $"FFFF8600868686008600000086868600008686008686860086D2ACACACACFFFF" + $"FFFF8686868686868686868686868686868686868686868686D2ACACFFFFFFFF" + $"FFFF8686868686868686868686868686868686868686868686FFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +}; + +resource mini_icon array { + $"FFFFFF6060606060606060606060FFFF" + $"FF6060606060606060606060D2D2ACFF" + $"FF0086008600008600860000D2D2ACFF" + $"FF0000008600008600860000D2D2ACFF" + $"FF0000008600008600860000D2D2ACFF" + $"FF0000008600868600868600D2ACACFF" + $"FF0086008600008600868600D2ACACFF" + $"FF0086008600008600860000D2ACACFF" + $"FF0086008600008600860000D2ACACFF" + $"FF0086008600008600860000D2ACFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" +}; diff --git a/src/bin/mboxtobemail.cpp b/src/bin/mboxtobemail.cpp new file mode 100644 index 0000000000..511336c342 --- /dev/null +++ b/src/bin/mboxtobemail.cpp @@ -0,0 +1,745 @@ +/****************************************************************************** + * $Id:$ + * + * MboxToBeMail is a utility program that converts Unix mailbox (mbox) files + * (the kind that Pine uses) into e-mail files for use with BeOS. It also + * handles news files from rn and trn, which have messages very similar to mail + * messages but with a different separator line. The input files store + * multiple mail messages in text format separated by "From ..." lines or + * "Article ..." lines. The output is a bunch of separate files, each one with + * one message plus BeOS BFS attributes describing that message. For + * convenience, all the messages that were from one file are put in a specified + * directory. + * + * Command line driven. Version 1.7 and up (which have support for + * international character sets (as requested by "MFC" Zahar from Russia) and + * the Thread attribute) require the libmail.so that comes with the Mail Daemon + * Replacement (MDR) version 2.2.6 or later (http://www.bebits.com/app/2289 or + * http://sourceforge.net/projects/bemaildaemon/). Use version 1.6 (get it + * from the version history pages on BeBits) if you don't want to install MDR. + * + * $Log: MailboxToBeMail.cpp,v $ (manually updated now that SVN is used) + * Revision 1.9 2003/12/31 00:37:46 agmsmith + * Use the MDR date parsing routine rather than parsedate, so it + * can handle newer date formats. + * + * Revision 1.8 2003/12/28 19:03:57 agmsmith + * Added an option to save or not save the separator text line. + * + * Revision 1.7 2003/12/28 04:23:21 agmsmith + * Now uses the Mail Daemon Replacement library to parse the headers, + * which means they now handle foreign character sets (converted + * automatically to UTF-8), so Subject and To are correct when they + * are used as part of the file name. + * + * Revision 1.6 2002/01/14 20:23:21 agmsmith + * Include the detection line with the message header, just for completeness. + * + * Revision 1.5 2002/01/14 03:21:43 agmsmith + * Added processing of UseNet articles, and allowed an older date format. + * + * Revision 1.4 2002/01/14 00:06:59 agmsmith + * Don't allow slashes in file names. + * + * Revision 1.3 2002/01/13 23:33:26 agmsmith + * First seemingly working version. + * + * Revision 1.2 2002/01/13 17:57:26 agmsmith + * Can now pick out separate messages from the inbox. + * + * Revision 1.1 2002/01/13 15:25:33 agmsmith + * Initial revision + */ + +/* BeOS headers. */ + +#include +#include +#include +#include + +/* Posix headers. */ + +#include +#include +#include +#include + +/* MDR headers (get the MDR source and add the MDR include/public and +include/numail directories to the project path settings). */ + +#include +#include + + + +/****************************************************************************** + * Globals + */ + +char InputPathName [B_PATH_NAME_LENGTH]; +FILE *InputFile; +BDirectory OutputDir; + + +typedef enum StandardHeaderEnum +{ + STD_HDR_DATE = 0, /* The Date: field. First one since it is numeric. */ + STD_HDR_FROM, /* The whole From: field, including quotes and address. */ + STD_HDR_TO, /* All the stuff in the To: field. */ + STD_HDR_CC, /* All the CC: field (originally means carbon copy). */ + STD_HDR_REPLY, /* Things in the reply-to: field. */ + STD_HDR_SUBJECT, /* The Subject: field. */ + STD_HDR_PRIORITY, /* The Priority: and related fields, usually "Normal". */ + STD_HDR_STATUS, /* The BeOS mail Read / New status text attribute. */ + STD_HDR_THREAD, /* The subject simplified. */ + STD_HDR_NAME, /* The From address simplified into a plain name. */ + STD_HDR_MAX +} StandardHeaderCodes; + +const char *g_StandardAttributeNames [STD_HDR_MAX] = +{ + B_MAIL_ATTR_WHEN, + B_MAIL_ATTR_FROM, + B_MAIL_ATTR_TO, + B_MAIL_ATTR_CC, + B_MAIL_ATTR_REPLY, + B_MAIL_ATTR_SUBJECT, + B_MAIL_ATTR_PRIORITY, + B_MAIL_ATTR_STATUS, + B_MAIL_ATTR_THREAD, + B_MAIL_ATTR_NAME +}; + + + +/****************************************************************************** + * Global utility function to display an error message and return. The message + * part describes the error, and if ErrorNumber is non-zero, gets the string + * ", error code $X (standard description)." appended to it. If the message + * is NULL then it gets defaulted to "Something went wrong". + */ + +static void DisplayErrorMessage ( + const char *MessageString = NULL, + int ErrorNumber = 0, + const char *TitleString = NULL) +{ + char ErrorBuffer [B_PATH_NAME_LENGTH + 80 /* error message */ + 80]; + + if (TitleString == NULL) + TitleString = "Error Message:"; + + if (MessageString == NULL) + { + if (ErrorNumber == 0) + MessageString = "No error, no message, why bother?"; + else + MessageString = "Something went wrong"; + } + + if (ErrorNumber != 0) + { + sprintf (ErrorBuffer, "%s, error code $%X/%d (%s) has occured.", + MessageString, ErrorNumber, ErrorNumber, strerror (ErrorNumber)); + MessageString = ErrorBuffer; + } + + fputs (TitleString, stderr); + fputc ('\n', stderr); + fputs (MessageString, stderr); + fputc ('\n', stderr); +} + + + +/****************************************************************************** + * Determine if a line of text is the start of another message. Pine mailbox + * files have messages that start with a line that could say something like + * "From agmsmith@achilles.net Fri Oct 31 21:19:36 EST 1997" or maybe something + * like "From POPmail Mon Oct 20 21:12:36 1997" or in a more modern format, + * "From agmsmith@achilles.net Tue Sep 4 09:04:11 2001 -0400". I generalise it + * to "From blah Day MMM NN XX:XX:XX TZONE1 YYYY TZONE2". Blah is an e-mail + * address you can ignore (just treat it as a word separated by spaces). Day + * is a 3 letter day of the week. MMM is a 3 letter month name. NN is the two + * digit day of the week, has a leading space if the day is less than 10. + * XX:XX:XX is the time, the X's are digits. TZONE1 is the old style optional + * time zone of 3 capital letters. YYYY is the four digit year. TZONE2 is the + * optional modern time zone info, a plus or minus sign and 4 digits. Returns + * true if the line of text (ended with a NUL byte, no line feed or carriage + * returns at the end) is the start of a message. + */ + +bool IsStartOfMailMessage (char *LineString) +{ + char *StringPntr; + + /* It starts with "From " */ + + if (memcmp ("From ", LineString, 5) != 0) + return false; + StringPntr = LineString + 4; + while (*StringPntr == ' ') + StringPntr++; + + /* Skip over the e-mail address (or stop at the end of string). */ + + while (*StringPntr != ' ' && *StringPntr != 0) + StringPntr++; + while (*StringPntr == ' ') + StringPntr++; + + /* Look for the 3 letter day of the week. */ + + if (memcmp (StringPntr, "Mon", 3) != 0 && + memcmp (StringPntr, "Tue", 3) != 0 && + memcmp (StringPntr, "Wed", 3) != 0 && + memcmp (StringPntr, "Thu", 3) != 0 && + memcmp (StringPntr, "Fri", 3) != 0 && + memcmp (StringPntr, "Sat", 3) != 0 && + memcmp (StringPntr, "Sun", 3) != 0) + { + printf ("False alarm, not a valid day of the week in \"%s\".\n", + LineString); + return false; + } + StringPntr += 3; + while (*StringPntr == ' ') + StringPntr++; + + /* Look for the 3 letter month code. */ + + if (memcmp (StringPntr, "Jan", 3) != 0 && + memcmp (StringPntr, "Feb", 3) != 0 && + memcmp (StringPntr, "Mar", 3) != 0 && + memcmp (StringPntr, "Apr", 3) != 0 && + memcmp (StringPntr, "May", 3) != 0 && + memcmp (StringPntr, "Jun", 3) != 0 && + memcmp (StringPntr, "Jul", 3) != 0 && + memcmp (StringPntr, "Aug", 3) != 0 && + memcmp (StringPntr, "Sep", 3) != 0 && + memcmp (StringPntr, "Oct", 3) != 0 && + memcmp (StringPntr, "Nov", 3) != 0 && + memcmp (StringPntr, "Dec", 3) != 0) + { + printf ("False alarm, not a valid month name in \"%s\".\n", + LineString); + return false; + } + StringPntr += 3; + while (*StringPntr == ' ') + StringPntr++; + + /* Skip the day of the month. Require at least one digit. */ + + if (*StringPntr < '0' || *StringPntr > '9') + { + printf ("False alarm, not a valid day of the month number in \"%s\".\n", + LineString); + return false; + } + while (*StringPntr >= '0' && *StringPntr <= '9') + StringPntr++; + while (*StringPntr == ' ') + StringPntr++; + + /* Check the time. Look for the sequence + digit-digit-colon-digit-digit-colon-digit-digit. */ + + if (StringPntr[0] < '0' || StringPntr[0] > '9' || + StringPntr[1] < '0' || StringPntr[1] > '9' || + StringPntr[2] != ':' || + StringPntr[3] < '0' || StringPntr[3] > '9' || + StringPntr[4] < '0' || StringPntr[4] > '9' || + StringPntr[5] != ':' || + StringPntr[6] < '0' || StringPntr[6] > '9' || + StringPntr[7] < '0' || StringPntr[7] > '9') + { + printf ("False alarm, not a valid time value in \"%s\".\n", + LineString); + return false; + } + StringPntr += 8; + while (*StringPntr == ' ') + StringPntr++; + + /* Look for the optional antique 3 capital letter time zone and skip it. */ + + if (StringPntr[0] >= 'A' && StringPntr[0] <= 'Z' && + StringPntr[1] >= 'A' && StringPntr[1] <= 'Z' && + StringPntr[2] >= 'A' && StringPntr[2] <= 'Z') + { + StringPntr += 3; + while (*StringPntr == ' ') + StringPntr++; + } + + /* Look for the 4 digit year. */ + + if (StringPntr[0] < '0' || StringPntr[0] > '9' || + StringPntr[1] < '0' || StringPntr[1] > '9' || + StringPntr[2] < '0' || StringPntr[2] > '9' || + StringPntr[3] < '0' || StringPntr[3] > '9') + { + printf ("False alarm, not a valid 4 digit year in \"%s\".\n", + LineString); + return false; + } + StringPntr += 4; + while (*StringPntr == ' ') + StringPntr++; + + /* Look for the optional modern time zone and skip over it if present. */ + + if ((StringPntr[0] == '+' || StringPntr[0] == '-') && + StringPntr[1] >= '0' && StringPntr[1] <= '9' && + StringPntr[2] >= '0' && StringPntr[2] <= '9' && + StringPntr[3] >= '0' && StringPntr[3] <= '9' && + StringPntr[4] >= '0' && StringPntr[4] <= '9') + { + StringPntr += 5; + while (*StringPntr == ' ') + StringPntr++; + } + + /* Look for end of string. */ + + if (*StringPntr != 0) + { + printf ("False alarm, extra stuff after the year/time zone in \"%s\".\n", + LineString); + return false; + } + + return true; +} + + + +/****************************************************************************** + * Determine if a line of text is the start of a news article. TRN and RN news + * article save files have messages that start with a line that looks like + * "Article 11721 of rec.games.video.3do:". Returns true if the line of text + * (ended with a NUL byte, no line feed or carriage returns at the end) is the + * start of an article. + */ + +bool IsStartOfUsenetArticle (char *LineString) +{ + char *StringPntr; + + /* It starts with "Article " */ + + if (memcmp ("Article ", LineString, 8) != 0) + return false; + StringPntr = LineString + 7; + while (*StringPntr == ' ') + StringPntr++; + + /* Skip the article number. Require at least one digit. */ + + if (*StringPntr < '0' || *StringPntr > '9') + { + printf ("False alarm, not a valid article number in \"%s\".\n", + LineString); + return false; + } + while (*StringPntr >= '0' && *StringPntr <= '9') + StringPntr++; + while (*StringPntr == ' ') + StringPntr++; + + /* Now it should have "of " */ + + if (memcmp ("of ", StringPntr, 3) != 0) + { + printf ("False alarm, article line \"of\" misssing in \"%s\".\n", + LineString); + return false; + } + StringPntr += 2; + while (*StringPntr == ' ') + StringPntr++; + + /* Skip over the newsgroup name (no spaces) to the colon. */ + + while (*StringPntr != ':' && *StringPntr != ' ' && *StringPntr != 0) + StringPntr++; + + if (StringPntr[0] != ':' || StringPntr[1] != 0) + { + printf ("False alarm, article doesn't end with a colon in \"%s\".\n", + LineString); + return false; + } + + return true; +} + + + +/****************************************************************************** + * Saves the message text to a file in the output directory. The file name is + * derived from the message headers. Returns zero if successful, a negative + * error code if an error occured. + */ + +status_t SaveMessage (BString &MessageText) +{ + time_t DateInSeconds; + status_t ErrorCode; + BString FileName; + BString HeaderValues [STD_HDR_MAX]; + int i; + int Length; + Zoidberg::Mail::Message MailMessage; + BFile OutputFile; + char TempString [80]; + struct tm TimeFields; + BString UniqueFileName; + int32 Uniquer; + + /* Remove blank lines from the end of the message (a pet peeve of mine), but + end the message with a single new line to avoid annoying text editors that + like to have it. */ + + i = MessageText.Length (); + while (i > 0 && (MessageText[i-1] == '\n' || MessageText[i-1] == '\r')) + i--; + MessageText.Truncate (i); + MessageText.Append ("\r\n"); + + /* Make a pretend file to hold the message, so the MDR library can use it. */ + + BMemoryIO FakeFile (MessageText.String (), MessageText.Length ()); + + /* Hand the message text off to the MDR library, which will parse it, extract + the subject, sender's name, and other attributes, taking into account the + character set headers. */ + + ErrorCode = MailMessage.SetToRFC822 (&FakeFile, + MessageText.Length (), false /* parse_now - decodes message body */); + if (ErrorCode != B_OK) + { + DisplayErrorMessage ("Mail library was unable to process a mail " + "message for some reason", ErrorCode); + return ErrorCode; + } + + /* Get the values for the standard attributes. NULL if missing. */ + + HeaderValues [STD_HDR_TO] = MailMessage.To (); + HeaderValues [STD_HDR_FROM] = MailMessage.From (); + HeaderValues [STD_HDR_CC] = MailMessage.CC (); + HeaderValues [STD_HDR_DATE] = MailMessage.Date (); + HeaderValues [STD_HDR_REPLY] = MailMessage.ReplyTo (); + HeaderValues [STD_HDR_SUBJECT] = MailMessage.Subject (); + HeaderValues [STD_HDR_STATUS] = "Read"; + if (MailMessage.Priority () != 3 /* Normal */) + { + sprintf (TempString, "%d", MailMessage.Priority ()); + HeaderValues [STD_HDR_PRIORITY] = TempString; + } + + HeaderValues[STD_HDR_THREAD] = HeaderValues[STD_HDR_SUBJECT]; + Zoidberg::Mail::SubjectToThread (HeaderValues[STD_HDR_THREAD]); + if (HeaderValues[STD_HDR_THREAD].Length() <= 0) + HeaderValues[STD_HDR_THREAD] = "No Subject"; + + HeaderValues[STD_HDR_NAME] = HeaderValues[STD_HDR_FROM]; + Zoidberg::Mail::extract_address_name (HeaderValues[STD_HDR_NAME]); + + // Generate a file name for the incoming message. + + FileName = HeaderValues [STD_HDR_THREAD]; + if (FileName[0] == '.') + FileName.Prepend ("_"); // Avoid hidden files, starting with a dot. + + // Convert the date into a year-month-day fixed digit width format, so that + // sorting by file name will give all the messages with the same subject in + // order of date. + + DateInSeconds = Zoidberg::Mail:: + ParseDateWithTimeZone (HeaderValues[STD_HDR_DATE].String()); + if (DateInSeconds == -1) + DateInSeconds = 0; /* Set it to the earliest time if date isn't known. */ + + localtime_r (&DateInSeconds, &TimeFields); + sprintf (TempString, "%04d%02d%02d%02d%02d%02d", + TimeFields.tm_year + 1900, + TimeFields.tm_mon + 1, + TimeFields.tm_mday, + TimeFields.tm_hour, + TimeFields.tm_min, + TimeFields.tm_sec); + FileName << " " << TempString << " " << HeaderValues[STD_HDR_NAME]; + FileName.Truncate (240); // reserve space for the uniquer + + // Get rid of annoying characters which are hard to use in the shell. + FileName.ReplaceAll('/','_'); + FileName.ReplaceAll('\'','_'); + FileName.ReplaceAll('"','_'); + FileName.ReplaceAll('!','_'); + FileName.ReplaceAll('<','_'); + FileName.ReplaceAll('>','_'); + while (FileName.FindFirst(" ") >= 0) // Remove multiple spaces. + FileName.Replace(" " /* Old */, " " /* New */, 1024 /* Count */); + + Uniquer = 0; + UniqueFileName = FileName; + while (true) + { + ErrorCode = OutputFile.SetTo (&OutputDir, + const_cast (UniqueFileName.String ()), + B_READ_WRITE | B_CREATE_FILE | B_FAIL_IF_EXISTS); + if (ErrorCode == B_OK) + break; + if (ErrorCode != B_FILE_EXISTS) + { + UniqueFileName.Prepend ("Unable to create file \""); + UniqueFileName.Append ("\" for writing a message to"); + DisplayErrorMessage (UniqueFileName.String (), ErrorCode); + return ErrorCode; + } + Uniquer++; + UniqueFileName = FileName; + UniqueFileName << " " << Uniquer; + } + + /* Write the message contents to the file, use the unchanged original one. */ + + ErrorCode = OutputFile.Write (MessageText.String (), MessageText.Length ()); + if (ErrorCode < 0) + { + UniqueFileName.Prepend ("Error while writing file \""); + UniqueFileName.Append ("\""); + DisplayErrorMessage (UniqueFileName.String (), ErrorCode); + return ErrorCode; + } + + /* Attach the attributes to the file. Save the MIME type first, otherwise + the live queries don't pick up the new file. Theoretically it would be + better to do it last so that other programs don't start reading the message + before the other attributes are set. */ + + OutputFile.WriteAttr ("BEOS:TYPE", B_MIME_STRING_TYPE, 0, + "text/x-email", 13); + + OutputFile.WriteAttr (g_StandardAttributeNames[STD_HDR_DATE], + B_TIME_TYPE, 0, &DateInSeconds, sizeof (DateInSeconds)); + + /* Write out all the string based attributes. */ + + for (i = 1 /* The date was zero */; i < STD_HDR_MAX; i++) + { + if ((Length = HeaderValues[i].Length()) > 0) + OutputFile.WriteAttr (g_StandardAttributeNames[i], B_STRING_TYPE, 0, + HeaderValues[i].String(), Length + 1); + } + + return 0; +} + + + +/****************************************************************************** + * Finally, the main program which drives it all. + */ + +int main (int argc, char** argv) +{ + char ErrorMessage [B_PATH_NAME_LENGTH + 80]; + bool HaveOldMessage = false; + int MessagesDoneCount = 0; + BString MessageText; + BApplication MyApp ("application/x-vnd.agmsmith.MailboxFileToBeMail"); + int NextArgIndex; + char OutputDirectoryPathName [B_PATH_NAME_LENGTH]; + status_t ReturnCode = -1; + bool SaveSeparatorLine = false; + char *StringPntr; + char TempString [102400]; + + if (argc <= 1) + { + printf ("%s is a utility for converting Pine e-mail\n", + argv[0]); + printf ("files (mbox files) to BeOS e-mail files with attributes. It\n"); + printf ("could well work with other Unix style mailbox files, and\n"); + printf ("saved Usenet article files. Each message in the input\n"); + printf ("mailbox is converted into a separate file. You can\n"); + printf ("optionally specify a directory (will be created if needed) to\n"); + printf ("put all the output files in, otherwise it scatters them into\n"); + printf ("the current directory. The -s option makes it leave in the\n"); + printf ("separator text line at the top of each message, the default\n"); + printf ("is to lose it.\n\n"); + printf ("Usage:\n\n"); + printf ("MailboxFileToBeMail [-s] InputFile [OutputDirectory]\n\n"); + printf ("Public domain, by Alexander G. M. Smith.\n"); + printf ("$Header: /CommonBe/agmsmith/Programming/MailboxFileToBeMail/RCS/MailboxToBeMail.cpp,v 1.9 2003/12/31 00:37:46 agmsmith Exp $\n"); + return -10; + } + + NextArgIndex = 1; + if (strcmp (argv[NextArgIndex], "-s") == 0) + { + SaveSeparatorLine = true; + NextArgIndex++; + } + + /* Try to open the input file. */ + + if (NextArgIndex >= argc) + { + ReturnCode = -20; + DisplayErrorMessage ("Missing the input file (mbox file) name argument."); + goto ErrorExit; + } + strncpy (InputPathName, argv[NextArgIndex], sizeof (InputPathName) - 1); + NextArgIndex++; + InputFile = fopen (InputPathName, "rb"); + if (InputFile == NULL) + { + ReturnCode = errno; + sprintf (ErrorMessage, "Unable to open file \"%s\" for reading", + InputPathName); + DisplayErrorMessage (ErrorMessage, ReturnCode); + goto ErrorExit; + } + + /* Try to make the output directory. First get its name. */ + + if (NextArgIndex < argc) + { + strncpy (OutputDirectoryPathName, argv[NextArgIndex], + sizeof (OutputDirectoryPathName) - 2 + /* Leave space for adding trailing slash and NUL byte */); + NextArgIndex++; + } + else + strcpy (OutputDirectoryPathName, "."); + + /* Remove trailing '/' characters from the output directory path. */ + + StringPntr = + OutputDirectoryPathName + (strlen (OutputDirectoryPathName) - 1); + while (StringPntr >= OutputDirectoryPathName) + { + if (*StringPntr != '/') + break; + StringPntr--; + } + *(++StringPntr) = 0; + + if (StringPntr - OutputDirectoryPathName > 0 && + strcmp (OutputDirectoryPathName, ".") != 0) + { + if (mkdir (OutputDirectoryPathName, 0777)) + { + ReturnCode = errno; + if (ReturnCode != B_FILE_EXISTS) + { + sprintf (ErrorMessage, "Unable to make output directory \"%s\"", + OutputDirectoryPathName); + DisplayErrorMessage (ErrorMessage, ReturnCode); + goto ErrorExit; + } + } + } + + /* Set the output BDirectory. */ + + ReturnCode = OutputDir.SetTo (OutputDirectoryPathName); + if (ReturnCode != B_OK) + { + sprintf (ErrorMessage, "Unable to set output BDirectory to \"%s\"", + OutputDirectoryPathName); + DisplayErrorMessage (ErrorMessage, ReturnCode); + goto ErrorExit; + } + + printf ("Input file: \"%s\", Output directory: \"%s\", ", + InputPathName, OutputDirectoryPathName); + printf ("%ssaving separator text line at the top of each message. Working", + SaveSeparatorLine ? "" : "not "); + + /* Extract a text message from the mail file. It starts with a line that + says "From blah Day MM NN XX:XX:XX YYYY TZONE". Blah is an e-mail address + you can ignore (just treat it as a word separated by spaces). Day is a 3 + letter day of the week. MM is a 3 letter month name. NN is the two digit + day of the week, has a leading space if the day is less than 10. XX:XX:XX is + the time, the X's are digits. YYYY is the four digit year. TZONE is the + optional time zone info, a plus or minus sign and 4 digits. */ + + while (!feof (InputFile)) + { + /* First read in one line of text. */ + + if (!fgets (TempString, sizeof (TempString), InputFile)) + { + ReturnCode = errno; + if (ferror (InputFile)) + { + sprintf (ErrorMessage, + "Error while reading from \"%s\"", InputPathName); + DisplayErrorMessage (ErrorMessage, ReturnCode); + goto ErrorExit; + } + break; /* No error, just end of file. */ + } + + /* Remove any trailing control characters (line feed usually, or CRLF). + Might also nuke trailing tabs too. Doesn't usually matter. The main thing + is to allow input files with both LF and CRLF endings (and even CR endings + if you come from the Macintosh world). */ + + StringPntr = TempString + strlen (TempString) - 1; + while (StringPntr >= TempString && *StringPntr < 32) + StringPntr--; + *(++StringPntr) = 0; + + /* See if this is the start of a new message. */ + + if (IsStartOfUsenetArticle (TempString) || + IsStartOfMailMessage (TempString)) + { + if (HaveOldMessage) + { + if ((ReturnCode = SaveMessage (MessageText)) != 0) + goto ErrorExit; + putchar ('.'); + fflush (stdout); + MessagesDoneCount++; + } + HaveOldMessage = true; + MessageText.SetTo (SaveSeparatorLine ? TempString : ""); + } + else + { + /* Append the line to the current message text. */ + + if (MessageText.Length () > 0) + MessageText.Append ("\r\n"); /* Yes, BeMail expects CR/LF line ends. */ + MessageText.Append (TempString); + } + } + + /* Flush out the last message. */ + + if (HaveOldMessage) + { + if ((ReturnCode = SaveMessage (MessageText)) != 0) + goto ErrorExit; + putchar ('.'); + MessagesDoneCount++; + } + printf (" Did %d messages.\n", MessagesDoneCount); + + ReturnCode = 0; + +ErrorExit: + if (InputFile != NULL) + fclose (InputFile); + OutputDir.Unset (); + return ReturnCode; +} diff --git a/src/bin/mboxtobemail.rdef b/src/bin/mboxtobemail.rdef new file mode 100644 index 0000000000..31c462fa63 --- /dev/null +++ b/src/bin/mboxtobemail.rdef @@ -0,0 +1,71 @@ +/* Resources for the mboxtobemail program, mostly for the icon. + $Id:$ */ + +resource app_flags B_SINGLE_LAUNCH | B_ARGV_ONLY; + +resource app_signature "application/x-vnd.agmsmith.mboxtobemail"; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + variety = B_APPV_FINAL, + internal = 1, + short_info = "MboxToBeMail $Rev$", + long_info = "MboxToBeMail - Unix mailbox to BeMail file converter. $Id:$" +}; + + +resource large_icon { + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF60606060606060606060606060606060606060606060FFFFFFFF" + $"FFFFFFFF60606060606060606060606060606060606060606060D2D2ACFFFFFF" + $"FFFFFF60606060606060606060606060606060606060606060D2D2D2D2ACFFFF" + $"FFFF6060606060606060606060606060606060606060606060D2D2D2D2ACFFFF" + $"FFFF8686868686868686868686868686868686868686868686D2D2D2D2ACFFFF" + $"FFFF8686868686868686868686868686868686868686868686D2D2D2D2ACFFFF" + $"FFFF8686262626268686262626862686868626862626262686D2D2D2D2ACFFFF" + $"FFFF8686268686862686862686862686868626862686868686D2D2D2ACACFFFF" + $"FFFF8686268686862686862686862626868626862686868686D2D2D2ACACFFFF" + $"FFFF8686268686862686862686862626868626862686868686D2D2D2ACACFFFF" + $"FFFF8686262626268686862686862626868626862686868686D2D2ACACACFFFF" + $"FFFF8686268686868686862686862686268626862626868686D2D2ACACACFFFF" + $"FFFF8686268686868686862686862686268626862686868686D2D2ACACACFFFF" + $"FFFF8686268686868686862686862686268626862686868686D2D2ACACACFFFF" + $"FFFF8686268686868686862686862686862626862686868686D2D2ACACACFFFF" + $"FFFF8686268686868686862686862686862626862686868686D2D2ACACACFFFF" + $"FFFF8686268686868686862686862686868626862686868686D2ACACACACFFFF" + $"FFFF8686268686868686262626862686868626862626262686D2ACACACACFFFF" + $"FFFF8686868686868686868686868686868686868686868686D2ACACFFFFFFFF" + $"FFFF8686868686868686868686868686868686868686868686FFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF1519191515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +}; + +resource mini_icon { + $"FFFFFF6060606060606060606060FFFF" + $"FF6060606060606060606060D2D2ACFF" + $"FF8686868686868686868686D2D2ACFF" + $"FF862626862686268626862626D2ACFF" + $"FF8626268626862686268626D2D2ACFF" + $"FF862626862686262626862626ACACFF" + $"FF8626868626862626268626D2ACACFF" + $"FF8626868626862686268626D2ACACFF" + $"FF862686862686268626862626ACACFF" + $"FF8686868686868686868686D2ACFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFF1915FFFFFFFFFFFFFFFF" +}; diff --git a/src/bin/spamdbm/spamdbm.rdef b/src/bin/spamdbm/spamdbm.rdef index a525ab056c..f6185fb06f 100644 --- a/src/bin/spamdbm/spamdbm.rdef +++ b/src/bin/spamdbm/spamdbm.rdef @@ -4,6 +4,8 @@ resource app_flags B_SINGLE_LAUNCH; +resource app_signature "application/x-vnd.agmsmith.spamdbm"; + resource app_version { major = 3, @@ -15,9 +17,7 @@ resource app_version { long_info = "SpamDBM - a spam analysis database manager for Haiku. $Id$" }; -resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.agmsmith.spamdbm"; - -resource(1, "BEOS:FILE_TYPES") message { +resource file_types message { "types" = "text/x-vnd.agmsmith.spam_probability_database", "types" = "text/x-email" }; @@ -63,7 +63,7 @@ resource(0, "BEOS:L:text/x-vnd.agmsmith.spam_probability_database") #'ICON' arra $"FFFFFFFFFFFFFFFFFFFF00000000000000000000000000FFFFFFFFFFFFFFFFFF" }; -resource(1, "BEOS:L:STD_ICON") #'ICON' array { +resource large_icon array { $"FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFFFFFFFFFF" $"FFFFFFFFFFFFFFFFFFFF00002A2A2A2A2A2A2A2A000000FFFFFFFFFFFFFFFFFF" $"FFFFFFFFFFFFFFFF00002A2A2A2A2A2A2A2A2A2A2A2A2A0000FFFFFFFFFFFFFF" @@ -117,7 +117,7 @@ resource(0, "BEOS:M:text/x-vnd.agmsmith.spam_probability_database") #'MICN' arra $"FFFFFFFF0F2F2F2F2F2F2FD0FFFFFFFF" }; -resource(1, "BEOS:M:STD_ICON") #'MICN' array { +resource mini_icon array { $"FFFFFFFFFFFF2F2F2F2FFFFFFFFFFFFF" $"FFFFFFFF2A2A2A2A2A2A2A2DD0FFFFFF" $"FFFFD02A2F00FFFFFEFEFF2F2A2DFFFF"