--- /dev/null
+Changes since 0.8.3
+-------------------
+Just changed include() calls to require_once() calls.
+
+Changes since 0.8.2
+-------------------
+Added many new FREE anti-spam databases to lookup from.
+Removed ORBS since they're off the air.
+
+Changes since 0.8.1
+-------------------
+Added a SpamFilters_DNScache[] array that is useful for 2 reasons:
+
+1. You can put in IPs in the cache that override the SPAMfilter's DNS
+ checking routines -- either to force 'em to NOT filter email coming from
+ a specific IP (ie. for those pesky customers who can't figure out how to
+ make Exchange not be an open relay) or to force 'em to ALWAYS filter email
+ coming from a specific IP (ie. for those pesky sites you KNOW are SPAM
+ sources or relays but that aren't added to any of the DNS databases)
+
+2. Before the SPAMfilters do a DNS query, they check to see if the IP in
+ question is already in the cache. If not and the query is performed, the
+ result is put in the DNS cache. This makes the SPAM filters a LOT faster
+ when you get lots of email from various mailing lists (all coming from a
+ very small number of IPs). The SPAM filters don't have to do a DNS query
+ on every message coming from the squirrelmail-plugins mailing list -- only
+ one the first time through to confirm the list server isn't in any of the
+ DNS databases! :-)
+
+Changes since 0.8
+-------------------
+Just fixed the Bad or malformed FETCH error that occurred when the INBOX was
+empty. The spamfilter plugin did a FETCH query from MsgNum 1 to * and since
+there WAS no Msg Num 1 the IMAP server would respond with an error. Now I
+check the number of messages before calling spam_filters or user_filters
+
+Changes since 0.7
+--------------------
+Tyler made TONS of changes to incorporate the fixes I'd done and posted
+about, as well as to fix the problem with number of unread messages not
+showing up in the folder panel. He also added some code to scan the headers
+for specific IPs in order to scan only IPs on the previous hop in the
+header.
+
+This didn't work well for me (the IP of my gateway wasn't reported on the
+Received from ... by ... line, and so RSS and DUL still had tons of false
+hits. I munged it so instead it uses a single string provided at
+setup/install time to find the right line in the header to find the IPs to
+look for in the various databases. (see SpamFilters_YourHop in setup.php)
+This seems to work pretty well for me -- faster enough to turn on all the
+databases and zero (so far) false hits! (grin)
+
+I also found a bug in sqimap_read_data() in functions/imap_general.php.
+After much discussion with Tyler, I rewrote it and posted it to
+squirrelmail-devel but it hasn't been accepted/tested/blessed yet
+NOTE: THIS NEW VERSION OF sqimap_read_data() IS REQUIRED BY FILTERS 0.8
+so you'll have to edit functions/imap_general.php and replace the function
+with the contents of sqimap_read_data.php.
+
+As soon as either my version of sqimap_read_data is officially part of the
+SM 1.1.2 CVS or until a new working version is posted, this is the only way
+to guarantee filters 0.8 will work.
+
--- /dev/null
+Filters 0.8.3
+
+IMPORTANT: I've noticed at least one version of PHP that has bugs in the
+checkdnsrr() function that the SPAM filtering code RELIES ON. In my case,
+the PHP server that comes with Mandrake 8.1 has this problem -- checkdnsrr()
+NEVER finds the inaddr records, even the ones that really exist. (sigh)
+
+NOTE!!! As of the time of this writing, there is a bug in sqimap_read_data()
+in functions/imap_general.php. I rewrote it (see sqimap_read_data.php) so
+if the SPAM filters aren't filtering, make a backup copy of
+functions/imap_general.php, remove the sqimap_read_data() function in there
+and replace it with the contents of sqimap_read_data.php. Hopefully, either
+my replacement will be blessed by squirrelmail-devel or some other version
+will come out soon. Now back to your regularly scheduled README... (grin)
+
+This is a poor alternative to procmail or Elm's filter programs. This is a
+pathetic replacement for good RBL mail scanning when you get the mail. This
+is more for systems that can't/won't offer that kind of functionality and
+you still require it.
+
+This is slow. Yep. Slow.
+
+
+To configure, you should just take a peek at setup.php and set
+$SpamFilters_YourHop to some string if you want to avoid tons of false
+hits on the RSS and DUL and ORBS databases. It should also speed up the
+scan somewhat.
+
+If you do not want to enable spam filters for all users, edit setup.php and
+set the $AllowSpamFilters to false. Spam filters can take TONS of time, so
+if you don't want your users to complain and ask you tons of questions, this
+is a quick and easy method.
+
+If you use UW and if you encounter strange errors while using this plugin on
+your system, edit setup.php and set $UseSeparateImapConnection to true. This
+may not solve the problem. One problem it might fix is if you run UW 2001
+and if you don't see the number of unread messages in your left-hand folder
+pane, or if you see timeouts or IMAP server error messages. Turning on this
+feature may slow down the filters a bit more since it has to open a new
+connection.
+
+Lastly, if there are some IPs that you want to refuse email from or some IPs
+you want to accept email from REGARDLESS of what the DNS databases say, you
+can put in overrides in the SpamFilters_DNScache[] array. See the comments
+in setup.php for more info on this.
--- /dev/null
+<?php
+ /*
+ * Message and Spam Filter Plugin
+ * By Luke Ehresman <luke@squirrelmail.org>
+ * Tyler Akins
+ * Brent Bice
+ * (c) 2000 (GNU GPL - see ../../COPYING)
+ *
+ * This plugin filters your inbox into different folders based upon given
+ * criteria. It is most useful for people who are subscibed to mailing lists
+ * to help organize their messages. The argument stands that filtering is
+ * not the place of the client, which is why this has been made a plugin for
+ * SquirrelMail. You may be better off using products such as Sieve or
+ * Procmail to do your filtering so it happens even when SquirrelMail isn't
+ * running.
+ *
+ * If you need help with this, or see improvements that can be made, please
+ * email me directly at the address above. I definately welcome suggestions
+ * and comments. This plugin, as is the case with all SquirrelMail plugins,
+ * is not directly supported by the developers. Please come to me off the
+ * mailing list if you have trouble with it.
+ *
+ * Also view plugins/README.plugins for more information.
+ *
+ */
+
+ function start_filters() {
+ global $username, $key, $imapServerAddress, $imapPort, $imap,
+ $imap_general, $filters, $imap_stream, $imapConnection,
+ $UseSeparateImapConnection, $AllowSpamFilters;
+
+ // Detect if we have already connected to IMAP or not.
+ // Also check if we are forced to use a separate IMAP connection
+ if ((!isset($imap_stream) && !isset($imapConnection)) ||
+ $UseSeparateImapConnection) {
+ $stream = sqimap_login($username, $key, $imapServerAddress,
+ $imapPort, 10);
+ $previously_connected = false;
+ } elseif (isset($imapConnection)) {
+ $stream = $imapConnection;
+ $previously_connected = true;
+ } else {
+ $previously_connected = true;
+ $stream = $imap_stream;
+ }
+
+ if (sqimap_get_num_messages($stream, "INBOX") > 0) {
+ // Filter spam from inbox before we sort them into folders
+ if ($AllowSpamFilters)
+ spam_filters($stream);
+
+ // Sort into folders
+ user_filters($stream);
+ }
+
+ if (!$previously_connected)
+ sqimap_logout($stream);
+ }
+
+
+ function user_filters($imap_stream) {
+ $filters = load_filters();
+ if (! $filters) return;
+
+ sqimap_mailbox_select($imap_stream, 'INBOX');
+
+ // For every rule
+ for ($i=0; $i < count($filters); $i++) {
+ // If it is the "combo" rule
+ if ($filters[$i]["where"] == "To or Cc") {
+ /*
+ * If it's "TO OR CC", we have to do two searches, one for TO
+ * and the other for CC.
+ */
+ filter_search_and_delete($imap_stream, 'TO',
+ $filters[$i]['what'], $filters[$i]['folder']);
+ filter_search_and_delete($imap_stream, 'CC',
+ $filters[$i]['what'], $filters[$i]['folder']);
+ } else {
+ /*
+ * If it's a normal TO, CC, SUBJECT, or FROM, then handle it
+ * normally.
+ */
+ filter_search_and_delete($imap_stream, $filters[$i]['where'],
+ $filters[$i]['what'], $filters[$i]['folder']);
+ }
+ }
+ // Clean out the mailbox whether or not auto_expunge is on
+ // That way it looks like it was redirected properly
+ sqimap_mailbox_expunge($imap_stream, 'INBOX');
+ }
+
+ function filter_search_and_delete($imap, $where, $what, $where_to) {
+ fputs ($imap, 'a001 SEARCH ALL ' . $where . ' "' . addslashes($what) .
+ "\"\r\n");
+ $read = sqimap_read_data ($imap, 'a001', true, $response, $message);
+
+ // This may have problems with EIMS due to it being goofy
+
+ for ($r=0; $r < count($read) &&
+ substr($read[$r], 0, 8) != '* SEARCH'; $r++) {}
+ if ($response == 'OK') {
+ $ids = explode(' ', $read[$r]);
+ if (sqimap_mailbox_exists($imap, $where_to)) {
+ for ($j=2; $j < count($ids); $j++) {
+ $id = trim($ids[$j]);
+ sqimap_messages_copy ($imap, $id, $id, $where_to);
+ sqimap_messages_flag ($imap, $id, $id, 'Deleted');
+ }
+ }
+ }
+ }
+
+ // These are the spam filters
+ function spam_filters($imap_stream) {
+ global $data_dir, $username;
+ global $SpamFilters_YourHop;
+ global $SpamFilters_DNScache;
+
+ $filters_spam_scan = getPref($data_dir, $username, "filters_spam_scan");
+ $filters_spam_folder = getPref($data_dir, $username, "filters_spam_folder");
+ $filters = load_spam_filters();
+
+ $run = 0;
+
+ foreach ($filters as $Key=> $Value) {
+ if ($Value['enabled'])
+ $run ++;
+ }
+
+ // short-circuit
+ if ($run == 0) {
+ return;
+ }
+
+ sqimap_mailbox_select($imap_stream, 'INBOX');
+
+ // Ask for a big list of all "Received" headers in the inbox with
+ // flags for each message. Kinda big.
+ fputs($imap_stream, 'A3999 FETCH 1:* (FLAGS BODY.PEEK[HEADER.FIELDS ' .
+ "(RECEIVED)])\r\n");
+
+ $read = sqimap_read_data ($imap_stream, 'A3999', true, $response, $message);
+
+ if ($response != 'OK')
+ return;
+
+ $i = 0;
+ while ($i < count($read)) {
+ // EIMS will give funky results
+ $Chunks = explode(' ', $read[$i]);
+ if ($Chunks[0] != '*') {
+ $i ++;
+ continue;
+ }
+ $MsgNum = $Chunks[1];
+
+ $IPs = array();
+ $i ++;
+ $IsSpam = 0;
+ $Scan = 1;
+
+ // Check for normal IMAP servers
+ if ($filters_spam_scan == 'new') {
+ if (is_int(strpos($Chunks[4], '\Seen'))) {
+ $Scan = 0;
+ }
+ }
+
+ // Look through all of the Received headers for IP addresses
+ // Stop when I get ")" on a line
+ // Stop if I get "*" on a line (don't advance)
+ // and above all, stop if $i is bigger than the total # of lines
+ while (($i < count($read)) &&
+ ($read[$i][0] != ')' && $read[$i][0] != '*' &&
+ $read[$i][0] != "\n") && (! $IsSpam))
+ {
+ // Check to see if this line is the right "Received from" line
+ // to check
+ if (is_int(strpos($read[$i], $SpamFilters_YourHop))) {
+
+ // short-circuit and skip work if we don't scan this one
+ if ($Scan) {
+ $read[$i] = ereg_replace('[^0-9\.]', ' ', $read[$i]);
+ $elements = explode(' ', $read[$i]);
+ foreach ($elements as $value) {
+ if ($value != '' &&
+ ereg('[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}',
+ $value, $regs)) {
+ $Chunks = explode('.', $value);
+ if ("$SpamFilters_DNScache[$value]" == "") {
+ $SpamFilters_DNScache[$value] =
+ filters_spam_check_site($Chunks[0], $Chunks[1],
+ $Chunks[2], $Chunks[3], $filters);
+ }
+ if ($SpamFilters_DNScache[$value]) {
+ $IsSpam ++;
+ break; // no sense in checking more IPs
+ }
+ }
+ }
+ }
+ }
+ $i ++;
+ }
+
+ // Lookie! It's spam! Yum!
+ if ($IsSpam) {
+ if (sqimap_mailbox_exists ($imap_stream, $filters_spam_folder)) {
+ sqimap_messages_copy ($imap_stream, $MsgNum, $MsgNum,
+ $filters_spam_folder);
+ sqimap_messages_flag ($imap_stream, $MsgNum, $MsgNum,
+ 'Deleted');
+ }
+ }
+ }
+
+ sqimap_mailbox_expunge($imap_stream, 'INBOX');
+ }
+
+
+ // Does the loop through each enabled filter for the specified IP address.
+ // IP format: $a.$b.$c.$d
+ function filters_spam_check_site($a, $b, $c, $d, &$filters) {
+ foreach ($filters as $key => $value) {
+ if ($filters[$key]['enabled']) {
+ if ($filters[$key]['dns']) {
+ if (checkdnsrr("$d.$c.$b.$a." . $filters[$key]['dns'],
+ 'ANY')) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ function load_filters() {
+ global $data_dir, $username;
+ $filters = array();
+ for ($i=0; $fltr = getPref($data_dir, $username, 'filter' . $i); $i++) {
+ $ary = explode(',', $fltr);
+ $filters[$i]['where'] = $ary[0];
+ $filters[$i]['what'] = $ary[1];
+ $filters[$i]['folder'] = $ary[2];
+ }
+ return $filters;
+ }
+
+ function load_spam_filters() {
+ global $data_dir, $username;
+
+ $filters['MAPS RBL']['prefname'] = 'filters_spam_maps_rbl';
+ $filters['MAPS RBL']['name'] = 'MAPS Realtime Blackhole List';
+ $filters['MAPS RBL']['link'] = 'http://www.mail-abuse.org/rbl/';
+ $filters['MAPS RBL']['dns'] = 'blackholes.mail-abuse.org';
+ $filters['MAPS RBL']['comment'] =
+'COMMERCIAL - This list contains servers that are verified spam senders.
+It is a pretty reliable list to scan spam from.';
+
+ $filters['MAPS RSS']['prefname'] = 'filters_spam_maps_rss';
+ $filters['MAPS RSS']['name'] = 'MAPS Relay Spam Stopper';
+ $filters['MAPS RSS']['link'] = 'http://www.mail-abuse.org/rss/';
+ $filters['MAPS RSS']['dns'] = 'relays.mail-abuse.org';
+ $filters['MAPS RSS']['comment'] =
+'COMMERCIAL - Servers that are configured (or misconfigured) to allow spam to
+be relayed through their system will be banned with this. Another good one to
+use.';
+
+ $filters['MAPS DUL']['prefname'] = 'filters_spam_maps_dul';
+ $filters['MAPS DUL']['name'] = 'MAPS Dial-Up List';
+ $filters['MAPS DUL']['link'] = 'http://www.mail-abuse.org/dul/';
+ $filters['MAPS DUL']['dns'] = 'dialups.mail-abuse.org';
+ $filters['MAPS DUL']['comment'] =
+'COMMERCIAL - Dial-up users are often filtered out since they should use their
+ISP\'s mail servers to send mail. Spammers typically get a dial-up account
+and send spam directly from there.';
+
+ $filters['MAPS RBLplus']['prefname'] = 'filters_spam_maps_rblplus';
+ $filters['MAPS RBLplus']['name'] = 'MAPS RBL+ List';
+ $filters['MAPS RBLplus']['link'] = 'http://www.mail-abuse.org/';
+ $filters['MAPS RBLplus']['dns'] = 'rbl-plus.mail-abuse.org';
+ $filters['MAPS RBLplus']['comment'] =
+'COMMERCIAL - RBL+ is a combination of RSS, DUL, and RBL.';
+
+ $filters['Osirusoft']['prefname'] = 'filters_spam_maps_osirusoft';
+ $filters['Osirusoft']['name'] = 'Osirusoft List';
+ $filters['Osirusoft']['link'] = 'http://relays.osirusoft.com/';
+ $filters['Osirusoft']['dns'] = 'relays.osirusoft.com';
+ $filters['Osirusoft']['comment'] =
+'FREE - Osirusoft - Very thorough, but also rejects replies from many
+ISP\'s abuse@domain.name email messages for some reason.';
+
+ $filters['ORDB']['prefname'] = 'filters_spam_ordb';
+ $filters['ORDB']['name'] = 'Open Relay Database List';
+ $filters['ORDB']['link'] = 'http://www.ordb.org/';
+ $filters['ORDB']['dns'] = 'relays.ordb.org';
+ $filters['ORDB']['comment'] =
+'FREE - ORDB was born when ORBS went off the air. It seems to have fewer false
+positives than ORBS did though.';
+
+ $filters['ORBZ']['prefname'] = 'filters_spam_orbz';
+ $filters['ORBZ']['name'] = 'ORBZ List';
+ $filters['ORBZ']['link'] = 'http://www.orbz.org/';
+ $filters['ORBZ']['dns'] = 'inputs.orbz.org';
+ $filters['ORBZ']['comment'] =
+'FREE - Another ORBS replacement (just the INPUTS database used here).';
+
+ $filters['Five-Ten']['prefname'] = 'filters_spam_fiveten';
+ $filters['Five-Ten']['name'] = 'Five-Ten-sg.com Lists';
+ $filters['Five-Ten']['link'] = 'http://www.five-ten-sg.com/blackhole.php';
+ $filters['Five-Ten']['dns'] = 'blackholes.five-ten-sg.com';
+ $filters['Five-Ten']['comment'] =
+'FREE - Five-Ten-sg.com has SPAM source, OpenRelay, and and Dialup IPs.';
+
+ $filters['Dorkslayers']['prefname'] = 'filters_spam_dorks';
+ $filters['Dorkslayers']['name'] = 'Dorkslayers Lists';
+ $filters['Dorkslayers']['link'] = 'http://www.dorkslayers.com';
+ $filters['Dorkslayers']['dns'] = 'orbs.dorkslayers.com';
+ $filters['Dorkslayers']['comment'] =
+'FREE - Dorkslayers appears to include only really bad open relays outside
+the US to avoid being sued. Interestingly enough, their website recommends
+you NOT use their service.';
+
+ $filters['ORBL']['prefname'] = 'filters_spam_orbl';
+ $filters['ORBL']['name'] = 'ORBL Lists';
+ $filters['ORBL']['link'] = 'http://www.orbl.org';
+ $filters['ORBL']['dns'] = 'or.orbl.org';
+ $filters['ORBL']['comment'] =
+'FREE - ORBL is another ORBS spinoff formed after ORBS shut down. May be
+SLOOOOOOW!';
+
+ $filters['ORBZ-UK']['prefname'] = 'filters_spam_orbzuk';
+ $filters['ORBZ-UK']['name'] = 'ORBZ-UK Lists';
+ $filters['ORBZ-UK']['link'] = 'http://orbz.gst-group.co.uk';
+ $filters['ORBZ-UK']['dns'] = 'orbz.gst-group.co.uk';
+ $filters['ORBZ-UK']['comment'] =
+'FREE - orbz.gst-group.co.uk lists not only open relays, but also mailservers
+that refuse or bounce email addressed to postmaster@<theirdomain>.';
+
+ foreach ($filters as $Key => $Value) {
+ $filters[$Key]['enabled'] = getPref($data_dir, $username,
+ $filters[$Key]['prefname']);
+ }
+
+ return $filters;
+ }
+
+ function remove_filter ($id) {
+ global $data_dir, $username;
+
+ while ($nextFilter = getPref($data_dir, $username, 'filter' .
+ ($id + 1))) {
+ setPref($data_dir, $username, 'filter' . $id, $nextFilter);
+ $id ++;
+ }
+
+ removePref($data_dir, $username, 'filter' . $id);
+ }
+
+ function filter_swap($id1, $id2) {
+ global $data_dir, $username;
+
+ $FirstFilter = getPref($data_dir, $username, 'filter' . $id1);
+ $SecondFilter = getPref($data_dir, $username, 'filter' . $id2);
+
+ if ($FirstFilter && $SecondFilter) {
+ setPref($data_dir, $username, 'filter' . $id2, $FirstFilter);
+ setPref($data_dir, $username, 'filter' . $id1, $SecondFilter);
+ }
+ }
+?>
--- /dev/null
+<?php
+ /*
+ * Message and Spam Filter Plugin
+ * By Luke Ehresman <luke@squirrelmail.org>
+ * Tyler Akins
+ * Brent Bice
+ * (c) 2000 (GNU GPL - see ../../COPYING)
+ *
+ * This plugin filters your inbox into different folders based upon given
+ * criteria. It is most useful for people who are subscibed to mailing lists
+ * to help organize their messages. The argument stands that filtering is
+ * not the place of the client, which is why this has been made a plugin for
+ * SquirrelMail. You may be better off using products such as Sieve or
+ * Procmail to do your filtering so it happens even when SquirrelMail isn't
+ * running.
+ *
+ * If you need help with this, or see improvements that can be made, please
+ * email me directly at the address above. I definately welcome suggestions
+ * and comments. This plugin, as is the case with all SquirrelMail plugins,
+ * is not directly supported by the developers. Please come to me off the
+ * mailing list if you have trouble with it.
+ *
+ * Also view plugins/README.plugins for more information.
+ *
+ */
+ chdir ("..");
+ require_once('../src/validate.php');
+ require_once ("../functions/page_header.php");
+ require_once ("../functions/imap.php");
+ require_once ("../src/load_prefs.php");
+
+ global $AllowSpamFilters;
+
+ displayPageHeader($color, "None");
+
+ if (isset($filter_submit)) {
+ if (!isset($theid)) $theid = 0;
+ $filter_what = ereg_replace(",", " ", $filter_what);
+ $filter_what = str_replace("\\\\", "\\", $filter_what);
+ $filter_what = str_replace("\\\"", "\"", $filter_what);
+ $filter_what = str_replace("\"", """, $filter_what);
+
+ setPref($data_dir, $username, "filter".$theid, $filter_where.",".$filter_what.",".$filter_folder);
+ $filters[$theid]["where"] = $filter_where;
+ $filters[$theid]["what"] = $filter_what;
+ $filters[$theid]["folder"] = $filter_folder;
+ } elseif (isset($spam_submit) && $AllowSpamFilters) {
+ $spam_filters = load_spam_filters();
+ setPref($data_dir, $username, 'filters_spam_folder', $filters_spam_folder_set);
+ setPref($data_dir, $username, 'filters_spam_scan', $filters_spam_scan_set);
+ foreach ($spam_filters as $Key => $Value)
+ {
+ $input = $spam_filters[$Key]['prefname'] . '_set';
+ setPref($data_dir, $username, $spam_filters[$Key]['prefname'],
+ $$input);
+ }
+ } elseif (isset($action) && $action == "delete") {
+ remove_filter($theid);
+ } elseif (isset($action) && $action == "move_up") {
+ filter_swap($theid, $theid - 1);
+ } elseif (isset($action) && $action == "move_down") {
+ filter_swap($theid, $theid + 1);
+ }
+
+ if ($AllowSpamFilters) {
+ $filters_spam_folder = getPref($data_dir, $username, 'filters_spam_folder');
+ $filters_spam_scan = getPref($data_dir, $username, 'filters_spam_scan');
+ }
+ $filters = load_filters();
+
+ ?>
+ <br>
+ <table width=95% align=center border=0 cellpadding=2 cellspacing=0><tr><td bgcolor="<?php echo $color[0] ?>">
+ <center><b><?php echo _("Options") ?> - Message Filtering</b></center>
+ </td></tr></table>
+ <br><center>[<a href="options.php?action=add">New</a>] - [<a href="../../src/options.php">Done</a>]</center><br>
+ <table border=0 cellpadding=3 cellspacing=0 align=center>
+ <?php
+ for ($i=0; $i < count($filters); $i++) {
+ if ($i % 2 == 0) $clr = $color[0];
+ else $clr = $color[9];
+
+ $fdr = ($folder_prefix)?str_replace($folder_prefix, "", $filters[$i]["folder"]):$filters[$i]["folder"];
+
+?>
+<tr bgcolor="<?PHP echo $clr ?>"><td><small>
+[<a href="options.php?theid=<?PHP echo $i ?>&action=edit">Edit</a>]
+</small></td><td><small>
+[<a href="options.php?theid=<?PHP echo $i ?>&action=delete">Delete</a>]
+</small></td><td align=center><small>
+[<?PHP if (isset($filters[$i + 1])) {
+?><a href="options.php?theid=<?PHP echo $i ?>&action=move_down">Down</a><?PHP
+if ($i > 0) echo ' | ';
+}
+if ($i > 0) {
+?><a href="options.php?theid=<?PHP echo $i ?>&action=move_up">Up</a><?PHP
+} ?>]</small></td><td>
+- If <b><?PHP echo $filters[$i]['where'] ?></b> contains <b><?PHP
+echo $filters[$i]['what'] ?></b> then move to <b><?PHP echo $fdr ?></b>
+</td></tr>
+<?PHP
+
+ }
+ ?>
+ </table>
+
+ <table width=80% align=center border=0 cellpadding=2 cellspacing=0">
+ <tr><td> </td></tr>
+ </table>
+
+ <?PHP if ($AllowSpamFilters) { ?>
+
+ <table width=95% align=center border=0 cellpadding=2 cellspacing=0 bgcolor="<?php echo $color[0] ?>">
+ <tr><th align=center>Spam Filtering</th></tr>
+ </table>
+ <?PHP if (! isset($action) || $action != 'spam') { ?>
+ <p align=center>[<a href="options.php?action=spam">Edit</a>]<br>
+ Spam is sent to <b><?PHP
+ if ($filters_spam_folder)
+ {
+ echo $filters_spam_folder;
+ }
+ else
+ {
+ echo '[<i>not set yet</i>]';
+ }
+ ?></b><br>Spam scan is limited to <b><?PHP
+ if ($filters_spam_scan == 'new')
+ {
+ echo 'New Messages Only';
+ }
+ else
+ {
+ echo 'All Messages';
+ }
+ ?></b></p>
+
+ <table border=0 cellpadding=3 cellspacing=0 align=center bgcolor="<?PHP echo $color[0] ?>">
+ <?PHP
+
+ $spam_filters = load_spam_filters();
+
+ foreach ($spam_filters as $Key => $Value)
+ {
+ echo '<tr><th align=center>';
+
+ if ($spam_filters[$Key]['enabled'])
+ {
+ echo 'ON';
+ }
+ else
+ {
+ echo 'OFF';
+ }
+
+ echo '</th><td> - </td><td>';
+
+ if ($spam_filters[$Key]['link'])
+ {
+ echo '<a href="';
+ echo $spam_filters[$Key]['link'];
+ echo '" target="_blank">';
+ }
+
+ echo $spam_filters[$Key]['name'];
+ if ($spam_filters[$Key]['link'])
+ {
+ echo '</a>';
+ }
+ echo "</td></tr>\n";
+ }
+
+ ?>
+ </table>
+ <?php
+ }
+ }
+
+ if (isset($action) && ($action == "add" || $action == "edit")) {
+ $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
+ $boxes = sqimap_mailbox_list($imapConnection);
+ sqimap_logout($imapConnection);
+ if (!isset($theid))
+ $theid = count($filters);
+
+ ?>
+ <center>
+ <form action="options.php" method=post>
+ <br><table cellpadding=2 cellspacing=0 border=0>
+ <tr>
+ <td>
+
+ </td>
+ <td>
+ <select name=filter_where>
+ <?php
+ if (! isset($filters[$theid]['where'])) $L = false;
+ else $L = true;
+ if ($L && $filters[$theid]["where"] == "From") echo "<option value=\"From\" selected> From\n";
+ else echo "<option value=\"From\"> From\n";
+
+ if ($L && $filters[$theid]["where"] == "To") echo "<option value=\"To\" selected> To\n";
+ else echo "<option value=\"To\"> To\n";
+
+ if ($L && $filters[$theid]["where"] == "Cc") echo "<option value=\"Cc\" selected> Cc\n";
+ else echo "<option value=\"Cc\"> Cc\n";
+
+ if ($L && $filters[$theid]["where"] == "To or Cc") echo "<option value=\"To or Cc\" selected> To or Cc\n";
+ else echo "<option value=\"To or Cc\"> To or Cc\n";
+
+ if ($L && $filters[$theid]["where"] == "Subject") echo "<option value=\"Subject\" selected> Subject\n";
+ else echo "<option value=\"Subject\"> Subject\n";
+ ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td align=right>
+ Contains:
+ </td>
+ <td>
+ <input type=text size=32 name=filter_what value="<?php
+if (isset($filters[$theid]['what'])) echo $filters[$theid]["what"]; ?>">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Move to:
+ </td>
+ <td>
+ <tt>
+ <select name=filter_folder>
+ <?php
+ for ($i = 0; $i < count($boxes); $i++) {
+ if (! in_array('noselect', $boxes[$i]['flags'])) {
+ $box = $boxes[$i]["unformatted"];
+ $box2 = str_replace(' ', ' ', $boxes[$i]["formatted"]);
+ if (isset($filters[$theid]['folder']) &&
+ $filters[$theid]["folder"] == $box)
+ echo " <OPTION VALUE=\"$box\" SELECTED>$box2\n";
+ else
+ echo " <OPTION VALUE=\"$box\">$box2\n";
+ }
+ }
+ ?>
+ </tt>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <input type=submit name=filter_submit value=Submit>
+ <input type=hidden name=theid value=<?php echo $theid ?>>
+ </form>
+ </center>
+ <?php
+ }
+ else if (isset($action) && $action == 'spam' && $AllowSpamFilters)
+ {
+ $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
+ $boxes = sqimap_mailbox_list($imapConnection);
+ sqimap_logout($imapConnection);
+ for ($i = 0; $i < count($boxes) && $filters_spam_folder == ''; $i++) {
+ if ($boxes[$i]["flags"][0] != "noselect" && $boxes[$i]["flags"][1] != "noselect" && $boxes[$i]["flags"][2] != "noselect") {
+ $filters_spam_folder = $boxes[$i]['unformatted'];
+ }
+ }
+
+ ?><form method=post action="options.php">
+ <center>
+ <table width=85% cellpadding=2 cellspacing=0 border=0>
+ <tr>
+ <th align=right nowrap>Move spam to:</th>
+ <td><select name="filters_spam_folder_set">
+ <?PHP
+ for ($i = 0; $i < count($boxes); $i++) {
+ if (! in_array('noselect', $boxes[$i]['flags'])) {
+ $box = $boxes[$i]["unformatted"];
+ $box2 = str_replace(' ', ' ', $boxes[$i]["formatted"]);
+ if ($filters_spam_folder == $box)
+ echo "<OPTION VALUE=\"$box\" SELECTED>$box2</OPTION>\n";
+ else
+ echo "<OPTION VALUE=\"$box\">$box2</OPTION>\n";
+ }
+ }
+ ?>
+ </select>
+ </td>
+ </tr>
+ <tr><td></td><td>Moving spam directly to the trash may not be a good idea at first,
+ since messages from friends and mailing lists might accidentally be marked as spam.
+ Whatever folder you set this to, make sure that it gets cleaned out periodically,
+ so that you don't have an excessively large mailbox hanging around.
+ </td></tr>
+ <tr>
+ <th align=right nowrap>What to Scan:</th>
+ <td><select name="filters_spam_scan_set">
+ <option value=''<?PHP
+ if ($filters_spam_scan == '') echo ' SELECTED';
+ ?>>All messages</option>
+ <option value='new'<?PHP
+ if ($filters_spam_scan == 'new') echo ' SELECTED';
+ ?>>Only unread messages</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td></td><td>The more messages you scan, the longer it takes. I would suggest
+ that you scan only new messages. If you make a change to your filters, I
+ would set it to scan all messages, then go view my INBOX, then come back and
+ set it to scan only new messages. That way, your new spam filters will be
+ applied and you'll scan even the spam you read with the new filters.</td>
+ </tr>
+ <?PHP
+ $spam_filters = load_spam_filters();
+
+ foreach ($spam_filters as $Key => $Value)
+ {
+ echo "<tr><th align=right nowrap>$Key</th>\n";
+ echo '<td><input type=checkbox name="';
+ echo $spam_filters[$Key]['prefname'];
+ echo '_set"';
+ if ($spam_filters[$Key]['enabled'])
+ echo ' CHECKED';
+ echo '> - ';
+ if ($spam_filters[$Key]['link'])
+ {
+ echo '<a href="';
+ echo $spam_filters[$Key]['link'];
+ echo '" target="_blank">';
+ }
+ echo $spam_filters[$Key]['name'];
+ if ($spam_filters[$Key]['link'])
+ {
+ echo '</a>';
+ }
+ echo '</td></tr><tr><td></td><td>';
+ echo $spam_filters[$Key]['comment'];
+ echo "</td></tr>\n";
+ }
+ ?>
+ <tr><td colspan=2 align=center><input type=submit name="spam_submit" value="Save"></td></tr>
+ </table>
+ </center>
+ </form>
+ <?PHP
+
+ sqimap_logout($imapConnection);
+ }
+?>
--- /dev/null
+<?php
+ /*
+ * Message and Spam Filter Plugin
+ * By Luke Ehresman <luke@squirrelmail.org>
+ * Tyler Akins
+ * Brent Bice
+ * (c) 2000 (GNU GPL - see ../../COPYING)
+ *
+ * This plugin filters your inbox into different folders based upon given
+ * criteria. It is most useful for people who are subscibed to mailing lists
+ * to help organize their messages. The argument stands that filtering is
+ * not the place of the client, which is why this has been made a plugin for
+ * SquirrelMail. You may be better off using products such as Sieve or
+ * Procmail to do your filtering so it happens even when SquirrelMail isn't
+ * running.
+ *
+ * If you need help with this, or see improvements that can be made, please
+ * email me directly at the address above. I definately welcome suggestions
+ * and comments. This plugin, as is the case with all SquirrelMail plugins,
+ * is not directly supported by the developers. Please come to me off the
+ * mailing list if you have trouble with it.
+ *
+ * Also view plugins/README.plugins for more information.
+ *
+ */
+
+ // Set this to true if you have problems -- check the README file
+ // Note: This doesn't work all of the time (No idea why)
+ // Seems to be related to UW
+ global $UseSeparateImapConnection;
+ $UseSeparateImapConnection = false;
+
+ // Set this to false if you do not want the user to be able to enable
+ // spam filters
+ global $AllowSpamFilters;
+ $AllowSpamFilters = true;
+
+ // Set this to a string containing something unique to the line in the
+ // header you want me to find IPs to scan the databases with. For example,
+ // All the email coming IN from the internet to my site has a line in
+ // the header that looks like (all on one line):
+ // Received: [from usw-sf-list1.sourceforge.net (usw-sf-fw2.sourceforge.net
+ // [216.136.171.252]) by firewall.persistence.com (SYSADMIN-antispam
+ // 0.2) with
+ // Since this line indicates the FIRST hop the email takes into my network,
+ // I set my SpamFilters_YourHop to 'by firewall.persistence.com' but any
+ // case-sensitive string will do. You can set it to something found on
+ // every line in the header (like ' ') if you want to scan all IPs in
+ // the header (lots of false alarms here tho).
+
+ global $SpamFilters_YourHop;
+ $SpamFilters_YourHop = 'by firewall.persistence.com';
+
+ // A cache of IPs we've already checked or are known bad boys or good boys
+ // ie. $SpamFilters_DNScache["210.54.220.18"] = true;
+ // would tell filters to not even bother doing the DNS queries for that
+ // IP and any email coming from it are SPAM - false would mean that any
+ // email coming from it would NOT be SPAM
+ global $SpamFilters_DNScache;
+
+ require_once ("../plugins/filters/filters.php");
+
+ function squirrelmail_plugin_init_filters() {
+ global $squirrelmail_plugin_hooks;
+ global $mailbox, $imap_stream, $imapConnection;
+
+ $squirrelmail_plugin_hooks["left_main_before"]["filters"] = "start_filters";
+ if ($mailbox == "INBOX")
+ $squirrelmail_plugin_hooks["right_main_after_header"]["filters"] = "start_filters";
+ $squirrelmail_plugin_hooks["options_register"]["filters"] = "squirrelmail_plugin_register";
+ }
+
+ function squirrelmail_plugin_register() {
+ global $optionpages;
+
+ $optionpages[] = array(
+ 'name' => 'Message Filters',
+ 'url' => '../plugins/filters/options.php',
+ 'desc' => 'Filtering enables messages with different criteria to
+ be automatically filtered into different folders for
+ easier organization.',
+ 'js' => false
+ );
+ }
+?>
--- /dev/null
+ /******************************************************************************
+ ** Reads the output from the IMAP stream. If handle_errors is set to true,
+ ** this will also handle all errors that are received. If it is not set,
+ ** the errors will be sent back through $response and $message
+ ******************************************************************************/
+ function sqimap_read_data ($imap_stream, $pre, $handle_errors, &$response, &$message) {
+ global $color, $squirrelmail_language, $imap_general_debug;
+
+ $data = array();
+ $size = 0;
+
+ do {
+ $read = fgets($imap_stream, 9096);
+ if (ereg("^$pre (OK|BAD|NO)(.*)$", $read, $regs)) {
+ break; // found end of reply
+ }
+
+ // Continue if needed for this single line
+ while (strpos($read, "\n") === false) {
+ $read .= fgets($imap_stream, 9096);
+ }
+
+ $data[] = $read;
+
+ if (ereg("^\\* [0-9]+ FETCH.*\\{([0-9]+)\\}", $read, $regs)) {
+ $size = $regs[1];
+ if ($imap_general_debug) {
+ echo "<small><tt><font color=\"#CC0000\">Size is $size</font></tt></small><br>\n";
+ }
+
+ $total_size = 0;
+ do {
+ $read = fgets($imap_stream, 9096);
+ if ($imap_general_debug) {
+ echo "<small><tt><font color=\"#CC0000\">$read</font></tt></small><br>\n";
+ flush();
+ }
+ $data[] = $read;
+ $total_size += strlen($read);
+ } while ($total_size < $size);
+
+ $size = 0;
+ }
+ // For debugging purposes
+ if ($imap_general_debug) {
+ echo "<small><tt><font color=\"#CC0000\">$read</font></tt></small><br>\n";
+ flush();
+ }
+ } while (true);
+
+ $response = $regs[1];
+ $message = trim($regs[2]);
+
+ if ($imap_general_debug) echo '--<br>';
+
+ if ($handle_errors == false)
+ return $data;
+
+ if ($response == 'NO') {
+ // ignore this error from m$ exchange, it is not fatal (aka bug)
+ if (strstr($message, 'command resulted in') === false) {
+ set_up_language($squirrelmail_language);
+ echo "<br><b><font color=$color[2]>\n";
+ echo _("ERROR : Could not complete request.");
+ echo "</b><br>\n";
+ echo _("Reason Given: ");
+ echo $message . "</font><br>\n";
+ exit;
+ }
+ } else if ($response == 'BAD') {
+ set_up_language($squirrelmail_language);
+ echo "<br><b><font color=$color[2]>\n";
+ echo _("ERROR : Bad or malformed request.");
+ echo "</b><br>\n";
+ echo _("Server responded: ");
+ echo $message . "</font><br>\n";
+ exit;
+ }
+
+ return $data;
+ }
+
+
+
+
--- /dev/null
+SquirrelSpell-v0.3.1
+---------------------
+
+Untar SquirrelSpell into your squirrelmail/plugins directory. Move
+sqspell_config.dist to sqspell_config.php if this is a fresh install. If
+upgrading, just untar over your old installation.
+
+Modify the sqspell_config.php file making sure you have ispell or aspell
+available on your system and located in PHP's path. The squirrelspell
+doesn't check for that and if it is not available, you're just going to
+get a "No errors found" message every time. :) Quite pleasing, but not
+very useful.
+
+Read files in "doc" directory -- they explain some features.
+
+Enable the plugin either by hand or by running the configure script from
+your squirrelmail install directory.
+
+Enjoy and report bugs. ;)
--- /dev/null
+CRYPTOGRAPHY SUPPORT IN SQUIRRELSPELL
+--------------------------------------
+
+Starting with version v0.3 SquirrelSpell is capable of working with encrypted
+user dictionaries. However, this option is only available when PHP
+is compiled with support for MCRYPT. This is relatively easy -- to enable
+MCRYPT support, follow instructions at:
+
+http://www.php.net/manual/en/ref.mcrypt.php
+
+NOTE: You will need libmcrypt version 2.4.x or above for SquirrelSpell
+to work.
+
+HOW IT'S DONE
+--------------
+SquirrelSpell encrypts the dictionary with the user's mailbox password,
+thus making the encryption/decryption process transparent to the user.
+The algorythm used for encryption is Blowfish, but you may manually override
+it in the code if you so wish.
+
+The only shortcoming this approach has -- when mailbox password is changed,
+SquirrelSpell asks the user to enter the old password in order to re-encrypt
+the file with the new key. If the user doesn't remember the password, then
+the file is lost, unless you want to brute-force it open.
+
+The encryption is off by default and users are warned about remembering
+their passwords before they enable encryption of their personal dictionary.
+
+I haven't tested the overhead. If anyone has any benchmarks -- you are
+welcome to share them.
--- /dev/null
+SQUIRRELSPELL
+
+v0.3.5
+-------
+- Making it work with 1.1.1 broke it under 1.0.6. Decided not to support
+ developmental versions after this release.
+
+v0.3.4
+-------
+- Changes to unbreak it in 1.1.1. :)
+
+v0.3.3
+-------
+- Apparently, magic quotes wasn't a bug, but something introduced in 1.0.6,
+ so I took out all magic-quotes escaping routines, since it's done
+ automatically now by validate.php.
+
+v0.3.2
+-------
+- Rolled back changes in v0.3.1
+- Workaround for an odd bug with PHP's magic_quotes_gpc
+- Changed trim to chop so the newline-trimming function doesn't trim
+ leading spaces.
+- Changed SOUP_NAZI to only deny Opera-4 versions
+- Moved SQSPELL_VERSION to sqspell_functions.php for easier
+ upgrades.
+
+v0.3.1
+-------
+Changes to make it work with 1.0.5.
+
+v0.3
+-----
+Added vlink and alink settings, plus fixed some colors.
+
+v0.3b
+------
+- Major code re-organization.
+- Moved modules into separate directory.
+- Moved most JavaScript out of the main code into separate .js files
+- Created generic GUI-wrappers for most interface screens.
+- Added support for multiple international dictionaries.
+- Added MCRYPT support for encrypting the user dictionaries.
+- No longer checks lines starting with ">" (reply).
+- No longer checks anything past the "--" on a single line (signature).
+- SquirrelSpell options are now on the main OPTIONS page, not on the
+ personal options page.
+
+v0.2.1
+------
+Added a SoupNazi function. :)) Checks for bad browsers which are known not to
+work with SquirrelSpell due to their odd JavaScript.
+
+v0.2pl1
+-------
+Fixed the Magic Quotes problems.
+
+v0.2
+-----
+Added user dictionaries.
+
+v0.1.1
+-------
+Added support for aspell
+
+v0.1pl1
+--------
+Fixed Magic Quotes errors.
+
+version v0.1
+-------------
+Initial release.
--- /dev/null
+PRIVACY CONCERNS WHEN USING SQUIRRELSPELL:
+-------------------------------------------
+
+Beginning with version v0.2 SquirrelSpell saves personal dictionary on the
+server. This has a potential of a serious privacy issue, therefore you
+should configure your system to disallow web access to the directory where
+your user dictionaries are stored. By default they are stored in your
+$data_dir which you provided in your Squirrelmail config. This is the best
+option, but you should read the SquirrelMail FAQ's and Readme's on how to
+secure that directory.
+
+Also, see the CRYPTO file for instructions on how to enable encryption
+of user dictionaries. This is done in order to further enhance the
+privacy of your users.
--- /dev/null
+SquirrelSpell
+--------------
+
+SquirrelSpell is a JavaScript-powered spellchecker written to work with
+SquirrelMail versions 0.5 and higher.
+
+LICENSE:
+---------
+This is free software released under GNU GPL license and comes with no
+warranty of any kind. You may modify, borrow, or redistribute code as long
+as it doesn't violate the GNU GPL license. You can read more about this
+license at http://www.gnu.org/
+
+FEATURES:
+----------
+SquirrelSpell works with UN*X's ISPELL or ASPELL libraries and
+SquirrelMail version 0.5 and higher. No PHP recompilation required,
+unless you wish to enable MCRYPT support.
+
+* SpellChecker:
+ISPELL or ASPELL. It all depends on them. Read configuration parameters in
+sqspell_config.php. Starting with version v0.3 supports multiple international
+dictionaries.
+
+* User Dictionary:
+SquirrelSpell adds words to the user dictionary. You may edit your
+dictionary under options->personal options->Edit my dictionary.
+
+* Encryption:
+Starting with version v0.3 SquirrelSpell is capable of working with
+encrypted user dictionaries. See doc/CRYPTO for information on how to
+enable this feature.
+
+* i18n and l10n:
+SquirrelSpell supports any international dictionaries provided by ispell
+or aspell. However, since there isn't a translation interface available
+for SquirrelMail plugins, all messages produced by SquirrelSpell will be
+in English.
+
+AUTHOR:
+--------
+Konstantin Riabitsev, http://www.mricon.com/
+
+SUPPORT:
+---------
+Send suppot questions and bug reports to the plugins mailing list:
+squirrelmail-plugins@lists.sourceforge.net. When reporting a bug
+don't forget to mention your browser version, SquirrelMail and
+SquirrelSpell versions, as well as any other useful info.
+
+ENJOY. :)
+---------
--- /dev/null
+From version v0.2 to version v0.3
+----------------------------------
+
+The user dictionaries will be converted to v0.3 format. Once they are
+converted, you can't downgrade back to v0.2. If this scares you, backup all
+*.words files in your $data_dir somewhere safe.
+
+Files are renamed around. config.php is now sqspell_config.php.
+
+When you are setting up SQSPELL_DEFAULT_APP in the sqspell_config, keep in
+mind that this has to reflect whichever dictionary you used in version 0.2.
+Say, if you used "ispell -d german", you will need to specify German as
+your SQSPELL_DEFAULT_APP so user dictionaries can be upgraded successfully.
+Otherwise wrong words will end up in a wrong dictionary.
+
--- /dev/null
+<?php
+header("Location: http://www.mricon.com/");
+?>
--- /dev/null
+<?php
+header("Location: http://www.mricon.com/");
+?>
--- /dev/null
+squirrelspell/js
+
+These are javascript files used by SquirrelSpell.
--- /dev/null
+/**
+ CHECK_ME.JS
+ ------------
+ This JavaScript app is the driving power of the SquirrelSpell's
+ main spellchecker window. Hope you have as much pain figuring
+ it out as it took to write. ;))
+ **/
+
+var CurrentError=0;
+var CurrentLocation=0;
+
+var CurrentLine;
+var CurrentSymbol;
+var ChangesMade=false;
+
+function populateSqspellForm(){
+ // this function loads error data into the form.
+ CurrentWord=Word=misses[CurrentError];
+ WordLocations = locations[CurrentError].split(", ");
+ CurrentLoc = WordLocations[CurrentLocation];
+ if(CurrentLocation==WordLocations.length-1) {
+ CurrentLocation=0;
+ } else {
+ CurrentLocation++;
+ }
+
+ tmp = CurrentLoc.split(":");
+ CurrentLine=parseInt(tmp[0]);
+ CurrentSymbol=parseInt(tmp[1]);
+ document.forms[0].sqspell_error.value=Word;
+ LineValue=sqspell_lines[CurrentLine];
+ StartWith=0;
+ NewLineValue="";
+ if (CurrentSymbol > 40){
+ StartWith=CurrentSymbol-40;
+ NewLineValue = "...";
+ }
+ EndWith=LineValue.length;
+ EndLine="";
+ if (EndWith > CurrentSymbol + 40){
+ EndWith=CurrentSymbol+40;
+ EndLine="...";
+ }
+ NewLineValue+=LineValue.substring(StartWith, CurrentSymbol) + "*" + Word + "*" + LineValue.substring(CurrentSymbol + Word.length, EndWith) + EndLine;
+ document.forms[0].sqspell_line_area.value=NewLineValue;
+
+ if (suggestions[CurrentError]){
+ WordSuggestions = suggestions[CurrentError].split(", ");
+ for (i=0; i<WordSuggestions.length; i++){
+ document.forms[0].sqspell_suggestion.options[i] = new Option(WordSuggestions[i], WordSuggestions[i]);
+ }
+ } else {
+ document.forms[0].sqspell_suggestion.options[0] = new Option("No Suggestions", "_NONE");
+ document.forms[0].sqspell_oruse.value=Word;
+ document.forms[0].sqspell_oruse.focus();
+ document.forms[0].sqspell_oruse.select();
+ }
+
+ document.forms[0].sqspell_suggestion.selectedIndex=0;
+ if (!document.forms[0].sqspell_oruse.value)
+ document.forms[0].sqspell_oruse.value=document.forms[0].sqspell_suggestion.options[document.forms[0].sqspell_suggestion.selectedIndex].value;
+ occursTimes = WordLocations.length;
+ if (CurrentLocation) occursTimes += CurrentLocation-1;
+ document.forms[0].sqspell_likethis.value=occursTimes;
+}
+
+function updateLine(lLine, lSymbol, lWord, lNewWord){
+ // This function updates the line with new word value
+ sqspell_lines[lLine] = sqspell_lines[lLine].substring(0, lSymbol) + lNewWord + sqspell_lines[lLine].substring(lSymbol+lWord.length, sqspell_lines[lLine].length);
+ if (lWord.length != lNewWord.length)
+ updateSymbol(lLine, lSymbol, lNewWord.length-lWord.length);
+ if (!ChangesMade) ChangesMade=true;
+}
+
+function sqspellRemember(){
+ // This function adds the word to the field in the form to be later
+ // submitted and added to the user dictionary.
+ CurrentWord = misses[CurrentError] + "%";
+ document.forms[0].words.value += CurrentWord;
+ sqspellIgnoreAll();
+}
+
+
+function sqspellChange(){
+ // Called when pressed the "Change" button
+ CurrentWord = misses[CurrentError];
+ NewWord=document.forms[0].sqspell_oruse.value;
+ updateLine(CurrentLine, CurrentSymbol, CurrentWord, NewWord);
+ proceed();
+}
+
+function sqspellChangeAll(){
+ // Called when pressed the "Change All" button
+ allLoc = locations[CurrentError].split(", ");
+ if (allLoc.length==1) {
+ // There's no need to "change all", only one occurance.
+ sqspellChange();
+ return;
+ }
+
+ NewWord=document.forms[0].sqspell_oruse.value;
+ CurrentWord = misses[CurrentError];
+ for (z=CurrentLocation-1; z<allLoc.length; z++){
+ tmp = allLoc[z].split(":");
+ lLine = parseInt(tmp[0]); lSymbol = parseInt(tmp[1]);
+ updateLine(lLine, lSymbol, CurrentWord, NewWord);
+ // Load it again to reflect the changes in symbol data
+ allLoc = locations[CurrentError].split(", ");
+ }
+
+ CurrentLocation=0;
+ proceed();
+}
+
+function sqspellIgnore(){
+ // Only here for consistency. Called when pressed the "Ignore" button
+ proceed();
+}
+
+function sqspellIgnoreAll(){
+ // Called when pressed the "Ignore All" button
+ CurrentLocation=0;
+ proceed();
+}
+
+function clearSqspellForm(){
+ // Clears the options in selectbox "sqspell_suggestions"
+ for (i=0; i<document.forms[0].sqspell_suggestion.length; i++){
+ document.forms[0].sqspell_suggestion.options[i]=null;
+ }
+
+ // Now, I've been instructed by the Netscape Developer docs to call
+ // history.go(0) to refresh the page after I've changed the options.
+ // However, that brings so many pains with it that I just decided not
+ // to do it. It works like it is in Netscape 4.x. If there are problems
+ // in earlier versions of Netscape, then oh well. I'm not THAT anxious
+ // to have it working on all browsers... ;)
+
+ document.forms[0].sqspell_oruse.value="";
+}
+
+function proceed(){
+ // Goes on to the next error if any, or finishes.
+ if (!CurrentLocation) CurrentError++;
+ if (misses[CurrentError]){
+ clearSqspellForm();
+ populateSqspellForm();
+ } else {
+ if (ChangesMade || document.forms[0].words.value){
+ if (confirm("SpellCheck complete. Commit Changes?"))
+ sqspellCommitChanges();
+ else self.close();
+ } else {
+ confirm ("No changes were made.");
+ self.close();
+ }
+ }
+}
+
+function updateSymbol(lLine, lSymbol, difference){
+ // Now, I will admit that this is not the best way to do stuff,
+ // However that's the solution I've come up with.
+ // This function updates the symbol locations after there have been
+ // word length changes in the lines. Otherwise SquirrelSpell barfs all
+ // over your message... ;)
+ //
+ // If you are wondering why I didn't use two-dimensional arrays instead,
+ // well, sometimes there will be a long line with an error close to the
+ // end of it, so the coordinates would be something like 2,98 and
+ // some Javascript implementations will create 98 empty members of an
+ // array just to have a filled number 98. This is too resource-wasteful
+ // and I have decided to go with the below solution instead. It takes
+ // a little more processing, but it saves a lot on memory.
+
+ for (i=0; i<misses.length; i++){
+ if(locations[i].indexOf(lLine + ":") >= 0){
+ allLoc = locations[i].split(", ");
+ for (j=0; j<allLoc.length; j++){
+ if (allLoc[j].indexOf(lLine+":")==0){
+ tmp = allLoc[j].split(":");
+ tmp[0] = parseInt(tmp[0]); tmp[1] = parseInt(tmp[1]);
+ if (tmp[1] > lSymbol){
+ tmp[1] = tmp[1] + difference;
+ allLoc[j] = tmp.join(":");
+ }
+ }
+ }
+ locations[i] = allLoc.join(", ");
+ }
+ }
+}
+
+function sqspellCommitChanges(){
+ // Write the changes back into the compose form
+ if (navigator.appName.indexOf("Microsoft")==0){
+ // MSIE doesn't have array.shift()
+ newSubject = sqspell_lines[0];
+ newBody = "";
+ for (i=1; i<sqspell_lines.length; i++){
+ if (i!=1) newBody+="\r\n";
+ newBody += sqspell_lines[i];
+ }
+ } else {
+ newSubject = sqspell_lines.shift();
+ newBody = sqspell_lines.join("\n");
+ }
+
+ opener.document.forms[0].subject.value=newSubject;
+ opener.document.forms[0].body.value=newBody;
+
+ // See if any words were added to the dictionary.
+ if (document.forms[0].words.value){
+ // yeppers
+ document.forms[0].sqspell_line_area.value="Now saving your personal dictionary... Please wait.";
+ // pass focus to the parent so we can do background save.
+ window.opener.focus();
+ document.forms[0].submit();
+ } else {
+ self.close();
+ }
+}
--- /dev/null
+/**
+ CRYPTO_SETTINGS.JS
+ -------------------
+ Some client-side checks. Nothing fancy.
+ **/
+
+function checkMe(){
+ if (!document.forms[0].action.checked){
+ alert ("Please make a selection first.");
+ return false;
+ }
+ if (document.forms[0].action.value=="encrypt")
+ cmsg="This will encrypt your personal dictionary and store it in an encrypted format. Proceed?";
+ if (document.forms[0].action.value=="decrypt")
+ cmsg="This will decrypt your personal dictionary and store it in a clear-text format. Proceed?";
+ return confirm(cmsg);
+}
--- /dev/null
+/**
+ DECRYPT_ERROR.JS
+ -----------------
+ Some client-side form-checks. Trivial stuff.
+ **/
+
+function AYS(){
+ if (document.forms[0].delete_words.checked && document.forms[0].old_key.value){
+ alert ("You can either delete your dictionary or type in the old password. Not both.");
+ return false;
+ }
+
+ if (!document.forms[0].delete_words.checked && !document.forms[0].old_key.value){
+ alert("First make a choice.");
+ return false;
+ }
+ if (document.forms[0].delete_words.checked)
+ return confirm("This will delete your personal dictionary file. Proceed?");
+ return true;
+}
+
--- /dev/null
+<?php
+header("Location: http://www.mricon.com/");
+?>
--- /dev/null
+/**
+ INIT.JS
+ -------
+ Grabs the text from the SquirrelMail field and submits it to
+ the squirrelspell.
+ **/
+function sqspell_init(flag){
+ // flag tells the function whether to automatically submit the form, or
+ // wait for user input. True submits the form, while False doesn't.
+ textToSpell = opener.document.forms[0].subject.value + "\n" + opener.document.forms[0].body.value;
+ document.forms[0].sqspell_text.value = textToSpell;
+ if (flag) document.forms[0].submit();
+}
--- /dev/null
+squirrelspell/modules
+
+This is where the loadable modules for SquirrelSpell are.
--- /dev/null
+<?php
+
+ /**
+ CHECK_ME.MOD.PHP
+ -----------------
+ This module is the main workhorse of SquirrelSpell. It submits
+ the message to the spell-checker, parses the output, and loads
+ the interface window.
+ **/
+// Declaring globals for E_ALL.
+global $sqspell_text, $SQSPELL_APP, $sqspell_use_app, $attachment_dir,
+ $username, $SQSPELL_EREG, $color;
+
+ // Now we explode the lines for three reasons:
+ // 1) So we can ignore lines starting with ">" (reply's)
+ // 2) So we can stop processing when we get to "--" on a single line,
+ // which means that the signature is starting
+ // 3) So we can add an extra space at the beginning of each line. This way
+ // ispell/aspell don't treat these as command characters.
+ $sqspell_raw_lines = explode("\n", $sqspell_text);
+ for ($i=0; $i<sizeof($sqspell_raw_lines); $i++){
+ if (trim($sqspell_raw_lines[$i]) == "--") break;
+ if(substr($sqspell_raw_lines[$i], 0, 1) != ">")
+ $sqspell_new_lines[$i] = " " . $sqspell_raw_lines[$i];
+ else $sqspell_new_lines[$i] = "";
+ }
+ $sqspell_new_text=implode("\n", $sqspell_new_lines);
+
+ // Define the command used to spellcheck the document.
+ $sqspell_command=$SQSPELL_APP[$sqspell_use_app];
+ // For the simplicity's sake we'll put all text into a file
+ // in attachment_dir directory, then cat it and pipe it to sqspell_command.
+ // There are other ways to do it, including popen(), but it's unidirectional
+ // and no fun at all.
+ // NOTE: This will probably change in future releases of squirrelspell
+ // for privacy reasons.
+ //
+ $floc = "$attachment_dir/$username" . "_sqspell_data.txt";
+ $fp=fopen($floc, "w");
+ fwrite($fp, $sqspell_new_text);
+ fclose($fp);
+ exec("cat $floc | $sqspell_command", $sqspell_output);
+ unlink($floc);
+
+ // Load the user dictionary.
+ $words=sqspell_getLang(sqspell_getWords(), $sqspell_use_app);
+ // define some variables.
+ $current_line=0;
+ $missed_words=Array();
+ $misses = Array();
+ $locations = Array();
+ $errors=0;
+ // Now we process the output of sqspell_command (ispell or aspell
+ // in ispell compatibility mode, whichever).
+ for ($i=0; $i<sizeof($sqspell_output); $i++){
+ switch (substr($sqspell_output[$i], 0, 1)){
+ case "":
+ // Ispell adds empty lines when an end of line is reached
+ $current_line++;
+ break;
+
+ case "&":
+ // This means there's a misspelled word and a few suggestions.
+ list($left, $right) = explode(": ", $sqspell_output[$i]);
+ $tmparray = explode(" ", $left);
+ $sqspell_word=$tmparray[1];
+ // Check if the word is in user dictionary.
+ if (!$SQSPELL_EREG("\n$sqspell_word\n", $words)){
+ $sqspell_symb=intval($tmparray[3])-1;
+ if (!$misses[$sqspell_word]) {
+ $misses[$sqspell_word] = $right;
+ $missed_words[$errors] = $sqspell_word;
+ $errors++;
+ }
+ if ($locations[$sqspell_word]) $locations[$sqspell_word] .= ", ";
+ $locations[$sqspell_word] .= "$current_line:$sqspell_symb";
+ }
+ break;
+
+ case "#":
+ // This means a misspelled word and no suggestions.
+ $tmparray = explode(" ", $sqspell_output[$i]);
+ $sqspell_word=$tmparray[1];
+ // Check if the word is in user dictionary.
+ if (!$SQSPELL_EREG("\n$sqspell_word\n", $words)){
+ $sqspell_symb=intval($tmparray[2])-1;
+ if (!$misses[$sqspell_word]) {
+ $misses[$sqspell_word] = "_NONE";
+ $missed_words[$errors] = $sqspell_word;
+ $errors++;
+ }
+ if ($locations[$sqspell_word]) $locations[$sqspell_word] .= ", ";
+ $locations[$sqspell_word] .= "$current_line:$sqspell_symb";
+ }
+ break;
+ }
+ }
+
+ if ($errors){
+ // So, there are errors
+ // This is the only place where the generic GUI-wrapper is not
+ // called, but generated right here. This is due to the complexity
+ // of the output.
+ ?>
+ <html>
+ <head>
+ <title>SquirrelSpell Results</title>
+ <script type="text/javascript">
+ // Load the spelling errors into JavaScript arrays
+ <!--
+ <?php
+ $sqspell_lines = explode("\n", $sqspell_text);
+ echo "// All lines of the message
+ var sqspell_lines=new Array();\n";
+ for ($i=0; $i<sizeof($sqspell_lines); $i++){
+ echo "sqspell_lines[$i] = \"" . chop(addslashes($sqspell_lines[$i])) . "\";\n";
+ }
+
+ echo "\n\n";
+ echo "// Misses are all misspelled words
+ var misses=new Array();\n";
+ for ($i=0; $i<sizeof($missed_words); $i++){
+ echo "misses[$i] = \"" . $missed_words[$i] . "\";\n";
+ }
+
+ echo "\n\n";
+ echo "// Suggestions are (guess what!) suggestions for misspellings
+ var suggestions = new Array();\n";
+ $i=0;
+ while (list($word, $value) = each($misses)){
+ if ($value=="_NONE") $value="";
+ echo "suggestions[$i] = \"$value\";\n";
+ $i++;
+ }
+
+ echo "\n\n";
+ echo "// Locations are where those misspellings are located, line:symbol
+ var locations= new Array();\n";
+ $i=0;
+ while (list($word, $value) = each($locations)){
+ echo "locations[$i] = \"$value\";\n";
+ $i++;
+ }
+ ?>
+ // Why isn't there a booger fairy?
+ //-->
+ </script>
+ <script src="js/check_me.js" type="text/javascript"></script>
+ </head>
+ <?php
+ printf('<body bgcolor="%s" text="%s" link="%s" alink="%s" vlink="%s" onload="populateSqspellForm()">', $color[4], $color[8], $color[7], $color[7], $color[7]);
+ ?>
+ <table width="100%" border="0" cellpadding="2">
+ <tr><td bgcolor="<?php echo $color[9] ?>" align="center"><b>Found <?php
+ echo $errors ?> errors</b></td></tr>
+ <tr><td><hr></td></tr>
+ <tr><td>
+ <form method="post">
+ <input type="hidden" name="MOD" value="forget_me_not">
+ <input type="hidden" name="words" value="">
+ <input type="hidden" name="sqspell_use_app" value="<?php echo $sqspell_use_app ?>">
+ <table border="0" width="100%">
+ <tr align="center">
+ <td colspan="4">
+ <span style="background-color:<?php echo $color[9] ?>">Line with an error:</span><br>
+ <textarea name="sqspell_line_area" cols="50" rows="3" wrap="hard" onfocus="this.blur()"></textarea>
+ </td>
+ </tr>
+ <tr valign="middle">
+ <td align="right" width="25%">
+ <span style="background-color: <?php echo $color[9] ?>">Error:</span>
+ </td>
+ <td align="left" width="25%">
+ <input name="sqspell_error" size="10" value="" onfocus="this.blur()">
+ </td>
+ <td align="right" width="25%">
+ <span style="background-color: <?php echo $color[9] ?>">Suggestions:</span>
+ </td>
+ <td align="left" width="25%">
+ <select name="sqspell_suggestion" onchange="if (this.options[this.selectedIndex].value != '_NONE') document.forms[0].sqspell_oruse.value=this.options[this.selectedIndex].value">
+ <option>Suggestions</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td align="right">
+ <span style="background-color: <?php echo $color[9] ?>">Change to:</span>
+ </td>
+ <td align="left">
+ <input name="sqspell_oruse" size="15" value=""
+ onfocus="if(!this.value) this.value=document.forms[0].sqspell_error.value">
+ </td>
+ <td align="right">
+ <span style="background-color: <?php echo $color[9] ?>">Occurs times:</span>
+ </td>
+ <td align="left">
+ <input name="sqspell_likethis" size=3 value=""
+ onfocus="this.blur()">
+ </td>
+ </tr>
+ </td></tr>
+ <tr><td colspan="4"><hr></td></tr>
+ <tr>
+ <td colspan="4">
+ <table border="0" cellpadding="0" cellspacing="3" width="100%">
+ <tr align="center" bgcolor="<?php echo $color[9] ?>">
+ <td>
+ <a href="javascript:sqspellChange()"
+ title="Change this word">Change</a>
+ </td>
+ <td>
+ <a href="javascript:sqspellChangeAll()"
+ title="Change ALL occurances of this word">Change All</a>
+ </td>
+ <td>
+ <a href="javascript:sqspellIgnore()"
+ title="Ignore this word">Ignore</a>
+ </td>
+ <td>
+ <a href="javascript:sqspellIgnoreAll()"
+ title="Ignore ALL occurances of this word">Ignore All</a>
+ </td>
+ <td>
+ <a href="javascript:sqspellRemember()"
+ title="Add this word to your personal dictionary">Add to Dic</a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr><td colspan="4"><hr></td></tr>
+ <tr>
+ <td colspan="4" align="center" bgcolor="<?php echo $color[9] ?>">
+ <input type="button" value=" Close and Commit " onclick="if (confirm('The spellcheck is not finished. Really close and commit changes?')) sqspellCommitChanges()">
+ <input type="button" value=" Close and Cancel " onclick="if (confirm('The spellcheck is not finished. Really close and discard changes?')) self.close()">
+ </td>
+ </tr>
+ </table>
+ </form>
+ </td></tr>
+ </table>
+ </body>
+ </html>
+ <?php
+ } else {
+ // AREN'T YOU SUCH A KNOW-IT-ALL!
+ $msg="<form onsubmit=\"return false\"><div align=\"center\"><input type=\"submit\" value=\" Close \" onclick=\"self.close()\"></div></form>";
+ sqspell_makeWindow(null, "No errors found", null, $msg);
+ }
+?>
--- /dev/null
+<?php
+
+/**
+ CRYPTO.MOD.PHP
+ --------------
+ This module handles the encryption/decryption of the user dictionary
+ if the user so chooses from the options page.
+ **/
+// Declaring globals for E_ALL
+global $action, $SQSPELL_CRYPTO;
+switch ($action){
+ case "encrypt":
+ // Let's encrypt the file.
+ $words=sqspell_getWords();
+ // flip the flag.
+ $SQSPELL_CRYPTO=true;
+ sqspell_writeWords($words);
+ $msg="<p>Your personal dictionary has been <strong>encrypted</strong> and is now stored in an <strong>encrypted format</strong>.</p>";
+ break;
+
+ case "decrypt":
+ // Decrypt the file and save plain text.
+ $words=sqspell_getWords();
+ // flip the flag.
+ $SQSPELL_CRYPTO=false;
+ sqspell_writeWords($words);
+ $msg="<p>Your personal dictionary has been <strong>decrypted</strong> and is now stored as <strong>clear text</strong>.</p>";
+ break;
+
+ case "":
+ // Wait, this shouldn't happen! :)
+ $msg = "<p>No action requested.</p>";
+ break;
+}
+ sqspell_makePage("Personal Dictionary Crypto Settings", null, $msg);
+?>
--- /dev/null
+<?php
+/**
+ CRYPTO_BADKEY.MOD.PHP
+ ---------------------
+ This module tries to decrypt the user dictionary with a newly provided
+ old password, or erases the file if everything else fails. :(
+ **/
+ // Just for fidian! :)
+ global $delete_words, $SCRIPT_NAME, $old_key;
+ if ($delete_words=="ON"){
+ // All attemts to decrypt the file were futile. Erase the bastard and
+ // hope this never happens again.
+ sqspell_deleteWords();
+ // See where we were called from -- pop-up window or options page
+ // and call whichever wrapper is appropriate.
+ if (strstr($SCRIPT_NAME, "sqspell_options")){
+ $msg="<p>Your personal dictionary was erased.</p>";
+ sqspell_makePage("Dictionary Erased", null, $msg);
+ } else {
+ $msg = "<p>Your personal dictionary was erased. Please close this window and
+ click \"Check Spelling\" button again to start your spellcheck over.</p>
+ <p align=\"center\"><form>
+ <input type=\"button\" value=\" Close this Window \" onclick=\"self.close()\">
+ </form></p>";
+ sqspell_makeWindow(null, "Dictionary Erased", null, $msg);
+ }
+ exit;
+ }
+
+ if ($old_key){
+ // User provided another key to try and decrypt the dictionary.
+ // call sqspell_getWords. If this key fails, the function will
+ // handle it.
+ $words=sqspell_getWords();
+ // It worked! Pinky, you're a genius!
+ // Write it back this time encrypted with a new key.
+ sqspell_writeWords($words);
+ // See where we are and call a necessary GUI-wrapper.
+ if (strstr($SCRIPT_NAME, "sqspell_options")){
+ $msg="<p>Your personal dictionary was re-encrypted successfully. Now
+ return to the "SpellChecker options" menu and make your selection
+ again.</p>";
+ sqspell_makePage("Successful Re-encryption", null, $msg);
+ } else {
+ $msg = "<p>Your personal dictionary was re-encrypted successfully. Please
+ close this window and click \"Check Spelling\" button again to start your
+ spellcheck over.</p>
+ <form><p align=\"center\"><input type=\"button\" value=\" Close this Window \"
+ onclick=\"self.close()\"></p></form>";
+ sqspell_makeWindow(null, "Dictionary re-encrypted", null, $msg);
+ }
+ exit;
+ }
+?>
--- /dev/null
+<?php
+/**
+ EDIT_DIC.MOD.PHP
+ ----------------
+ This module displays the words in your dictionary for editing.
+ **/
+ // fidian, you owe me a pack of Guinness! :)
+ global $color;
+ $words=sqspell_getWords();
+ if (!$words){
+ // Agt. Smith: "You're empty."
+ // Neo: "So are you."
+ sqspell_makePage("Personal Dictionary", null, "<p>No words in your personal dictionary.</p>");
+ } else {
+ // We're loaded with booty.
+ $pre_msg = "<p>Please check any words you wish to delete from your dictionary.</p>\n";
+ $pre_msg .= "<table border=\"0\" width=\"95%\" align=\"center\">\n";
+ $langs=sqspell_getSettings($words);
+ for ($i=0; $i<sizeof($langs); $i++){
+ $lang_words = sqspell_getLang($words, $langs[$i]);
+ if ($lang_words){
+ // No words in this dictionary.
+ if (!$msg) $msg = $pre_msg;
+ $msg .= "<tr bgcolor=\"$color[0]\" align=\"center\"><th>$langs[$i] dictionary</th></tr>
+ <tr><td align=\"center\">
+ <form method=\"post\">
+ <input type=\"hidden\" name=\"MOD\" value=\"forget_me\">
+ <input type=\"hidden\" name=\"sqspell_use_app\" value=\"$langs[$i]\">
+ <table border=\"0\" width=\"95%\" align=\"center\">
+ <tr>
+ <td valign=\"top\">\n";
+ $words_ary=explode("\n", $lang_words);
+ array_pop($words_ary);
+ array_shift($words_ary);
+ // Do some fancy stuff to separate the words into three columns.
+ for ($j=0; $j<sizeof($words_ary); $j++){
+ if ($j==intval(sizeof($words_ary)/3) || $j==intval(sizeof($words_ary)/3*2))
+ $msg .= "</td><td valign=\"top\">\n";
+ $msg .= "<input type=\"checkbox\" name=\"words_ary[]\" value=\"$words_ary[$j]\"> $words_ary[$j]<br>";
+ }
+ $msg .= "</td>
+ </tr>
+ </table>
+ </td></tr>
+ <tr bgcolor=\"$color[0]\" align=\"center\"><td>
+ <input type=\"submit\" value=\"Delete checked words\"></form>
+ </td></tr><tr><td><hr>
+ </td></tr>\n";
+ }
+ }
+ // Check if all dictionaries were empty.
+ if (!$msg)
+ $msg = "<p>No words in your dictionary.</p>";
+ else $msg .= "</table>";
+ sqspell_makePage("Edit your Personal Dictionary", null, $msg);
+ }
+?>
--- /dev/null
+<?php
+/**
+ ENC_SETUP.MOD.PHP
+ -----------------
+ This module shows the user a nice invitation to encrypt or decypt
+ his/her personal dictionary and explains the caveats of such a decision.
+ **/
+// Something for our friends with E_ALL for error_reporting:
+global $SQSPELL_CRYPTO;
+
+$words=sqspell_getWords();
+if ($SQSPELL_CRYPTO){
+ // Current format is encrypted.
+ $msg = "<p>Your personal dictionary is <strong>currently encrypted</strong>. This
+ helps protect your privacy in case the web-mail system gets compromized and your
+ personal dictionary ends up stolen. It is currently encrypted with the password
+ you use to access your mailbox, making it hard for anyone to see what is stored
+ in your personal dictionary.</p>
+ <p><strong>ATTENTION:</strong> If you forget your password, your personal dictionary
+ will become unaccessible, since it can no longer be decrypted.
+ If you change your mailbox password, SquirrelSpell will recognize it and prompt you for
+ your old password in order to re-encrypt the dictionary with a new key.</p>
+ <form method=\"post\" onsubmit=\"return checkMe()\">
+ <input type=\"hidden\" name=\"MOD\" value=\"crypto\">
+ <p align=\"center\"><input type=\"checkbox\" name=\"action\" value=\"decrypt\"> Please decrypt my personal
+ dictionary and store it in a clear-text format.</p>
+ <p align=\"center\"><input type=\"submit\" value=\" Change crypto settings \"></p>
+ </form>
+ ";
+} else {
+ // current format is clear text.
+ $msg = "<p>Your personal dictionary is <strong>currently not encrypted</strong>.
+ You may wish to encrypt your personal dictionary to protect your privacy in case
+ the webmail system gets compromized and your personal dictionary file gets stolen.
+ When encrypted, the file's contents look garbled and are hard to decrypt without
+ knowing the correct key (which is your mailbox password).</p>
+ <strong>ATTENTION:</strong> If you decide to encrypt your personal dictionary,
+ you must remember that it gets "hashed" with your mailbox password. If
+ you forget your mailbox password and the administrator changes it to a new value,
+ your personal dictionary will become useless and will have to be created anew.
+ However, if you or your system administrator change your mailbox password but you
+ still have the old password at hand, you will be able to enter the old key to
+ re-encrypt the dictionary with the new value.</p>
+ <form method=\"post\" onsubmit=\"return checkMe()\">
+ <input type=\"hidden\" name=\"MOD\" value=\"crypto\">
+ <p align=\"center\"><input type=\"checkbox\" name=\"action\" value=\"encrypt\"> Please encrypt my personal
+ dictionary and store it in an encrypted format.</p>
+ <p align=\"center\"><input type=\"submit\" value=\" Change crypto settings \"></p>
+ </form>
+ ";
+}
+ sqspell_makePage("Personal Dictionary Crypto Settings", "crypto_settings.js", $msg);
+?>
--- /dev/null
+<?php
+/**
+ FORGET_ME.MOD.PHP
+ ------------------
+ This module deletes the words from the user dictionary. Called
+ after EDIT_DIC module.
+ **/
+ // Make it two packs of Guinness and a bag of pistachios, fidian. :)
+ global $words_ary, $sqspell_use_app, $SQSPELL_VERSION;
+ if (sizeof($words_ary)){
+ // something needs to be deleted.
+ $words=sqspell_getWords();
+ $lang_words = sqspell_getLang($words, $sqspell_use_app);
+ $msg = "<p>Deleting the following entries from <strong>$sqspell_use_app</strong> dictionary:</p>
+ <ul>\n";
+ for ($i=0; $i<sizeof($words_ary); $i++){
+ // remove word by word...
+ $lang_words=str_replace("$words_ary[$i]\n", "", $lang_words);
+ $msg .= "<li>$words_ary[$i]</li>\n";
+ }
+ $new_words_ary=split("\n", $lang_words);
+ // Wipe this lang, if only 2 members in array (no words left).
+ if (sizeof($new_words_ary)<=2) $lang_words="";
+ $new_lang_words = $lang_words;
+ // process the stuff and write the dic back.
+ $langs=sqspell_getSettings($words);
+ $words_dic = "# SquirrelSpell User Dictionary $SQSPELL_VERSION\n# Last Revision: " . date("Y-m-d") . "\n# LANG: " . join(", ", $langs) . "\n";
+ for ($i=0; $i<sizeof($langs); $i++){
+ if ($langs[$i]==$sqspell_use_app)
+ $lang_words = $new_lang_words;
+ else $lang_words = sqspell_getLang($words, $langs[$i]);
+ if ($lang_words) $words_dic .= $lang_words;
+ }
+ $words_dic .= "# End\n";
+ sqspell_writeWords($words_dic);
+ $msg .= "</ul>
+ <p>All done!</p>\n";
+ sqspell_makePage("Personal Dictionary Updated", null, $msg);
+ } else {
+ // Click on some words first, Einstein!
+ sqspell_makePage("Personal Dictionary", null, "<p>No changes requested.</p>");
+ }
+?>
+
--- /dev/null
+<?php
+/**
+ FORGET_ME_NOT.MOD.PHP
+ ----------------------
+ This module saves the added words into the user dictionary. Called
+ after CHECK_ME module.
+ **/
+ // For our friends with E_ALL.
+ global $words, $SQSPELL_VERSION, $SQSPELL_APP_DEFFAULT, $sqspell_use_app;
+
+ $new_words = ereg_replace("%", "\n", $words);
+
+ // Load the user dictionary.
+ $words=sqspell_getWords();
+
+ if (!$words){
+ // First time.
+ $words_dic="# SquirrelSpell User Dictionary $SQSPELL_VERSION\n# Last Revision: " . date("Y-m-d") . "\n# LANG: $SQSPELL_APP_DEFAULT\n# $SQSPELL_APP_DEFAULT\n";
+ $words_dic .= $new_words . "# End\n";
+ } else {
+ // Do some fancy stuff in order to save the dictionary and not mangle the
+ // rest.
+ $langs=sqspell_getSettings($words);
+ $words_dic = "# SquirrelSpell User Dictionary $SQSPELL_VERSION\n# Last Revision: " . date("Y-m-d") . "\n# LANG: " . join(", ", $langs) . "\n";
+ for ($i=0; $i<sizeof($langs); $i++){
+ $lang_words=sqspell_getLang($words, $langs[$i]);
+ if ($langs[$i]==$sqspell_use_app){
+ if (!$lang_words) $lang_words="# $langs[$i]\n";
+ $lang_words .= $new_words;
+ }
+ $words_dic .= $lang_words;
+ }
+ $words_dic .= "# End\n";
+ }
+
+ // Write out the file
+ sqspell_writeWords($words_dic);
+ // display the splash screen, then close it automatically after 2 sec.
+ $onload="setTimeout('self.close()', 2000)";
+ $msg="<form onsubmit=\"return false\"><div align=\"center\"><input type=\"submit\" value=\" Close \" onclick=\"self.close()\"></div></form>";
+ sqspell_makeWindow($onload, "Personal Dictionary Updated", null, $msg);
+?>
+
--- /dev/null
+<?php
+header("Location: http://www.mricon.com/");
+?>
--- /dev/null
+<?php
+/**
+ INIT.MOD.PHP
+ -------------
+ Initial loading of the popup window interface.
+ **/
+
+ // See if we need to give user the option of choosing which dictionary
+ // he wants to use to spellcheck his message.
+ $langs=sqspell_getSettings(null);
+ $msg="<form method=\"post\">
+ <input type=\"hidden\" name=\"MOD\" value=\"check_me\">
+ <input type=\"hidden\" name=\"sqspell_text\">
+ <p align=\"center\">";
+ if (sizeof($langs)==1){
+ // only one dictionary defined by the users. Submit the form
+ // automatically.
+ $onload="sqspell_init(true)";
+ $msg .= "Please wait, communicating with the server...</p>
+ <input type=\"hidden\" name=\"sqspell_use_app\" value=\"$langs[0]\">
+ ";
+ } else {
+ // more than one dictionary. Let the user choose the dictionary first
+ // then manually submit the form.
+ $onload="sqspell_init(false)";
+ $msg .= "Please choose which dictionary you would like to use to spellcheck this
+ message:</p>
+ <p align=\"center\">
+ <select name=\"sqspell_use_app\">
+ ";
+ for ($i=0; $i<sizeof($langs); $i++){
+ $msg .= "<option";
+ if (!$i) $msg .= " selected";
+ $msg .= ">$langs[$i]</option>\n";
+ }
+
+ $msg .= " </select>
+ <input type=\"submit\" value=\"Go\">
+ </p>
+ ";
+ }
+ $msg .="</form>\n";
+ sqspell_makeWindow($onload, "SquirrelSpell Initiating", "init.js", $msg);
+?>
--- /dev/null
+<?php
+/**
+ LANG_CHANGE.MOD.PHP
+ --------------------
+ This module changes the international dictionaries selection
+ for the user. Called after LANG_SETUP module.
+ **/
+ // For poor wretched souls with E_ALL.
+ global $use_langs, $lang_default, $SQSPELL_APP_DEFAULT;
+
+ $words = sqspell_getWords();
+ if (!$words) $words = sqspell_makeDummy();
+ $langs = sqspell_getSettings($words);
+ if (sizeof($use_langs)){
+ // See if the user clicked any options on the previous page.
+ if (sizeof($use_langs)>1){
+ // See if s/he wants more than one dictionary.
+ if ($use_langs[0]!=$lang_default){
+ // See if we need to juggle the order of the dictionaries
+ // to make the default dictionary first in line.
+ if (in_array($lang_default, $use_langs)){
+ // see if the user was dumb and chose a default dictionary
+ // to be something other than the ones he selected.
+ $hold = array_shift($use_langs);
+ $lang_string = join(", ", $use_langs);
+ $lang_string = str_replace("$lang_default", "$hold", $lang_string);
+ $lang_string = $lang_default . ", " . $lang_string;
+ } else {
+ // Yes, he is dumb.
+ $lang_string = join(", ", $use_langs);
+ }
+ } else {
+ // No need to juggle the order -- preferred is already first.
+ $lang_string = join(", ", $use_langs);
+ }
+ } else {
+ // Just one dictionary, please.
+ $lang_string = $use_langs[0];
+ }
+ $msg = "<p>Settings adjusted to: <strong>$lang_string</strong> with
+ <strong>$lang_default</strong> as default dictionary.</p>";
+ } else {
+ // No dictionaries selected. Use system default.
+ $msg = "<p>Using <strong>$SQSPELL_APP_DEFAULT</strong> dictionary (system default)
+ for spellcheck.</p>";
+ $lang_string = $SQSPELL_APP_DEFAULT;
+ }
+ $old_lang_string = join(", ", $langs);
+ $words = str_replace("# LANG: $old_lang_string", "# LANG: $lang_string", $words);
+ // write it down where the sun don't shine.
+ sqspell_writeWords($words);
+ sqspell_makePage("International Dictionaries Preferences Updated", null, $msg);
+?>
--- /dev/null
+<?php
+/**
+ LANG_SETUP.MOD.PHP
+ ------------------
+ This module displays available dictionaries to the user and lets
+ him/her choose which ones s/he wants to check messages with.
+ **/
+ // Making sure Sqspell doesn't barf when working with E_ALL
+ global $SQSPELL_APP;
+
+ $msg = "<p>Please check any available international dictionaries which you would like
+ to use when spellchecking:</p>
+ <form method=\"post\">
+ <input type=\"hidden\" name=\"MOD\" value=\"lang_change\">
+ <blockquote><p>
+ ";
+ $langs = sqspell_getSettings(null);
+ $add = "<p>Make this dictionary my default selection: <select name=\"lang_default\">\n";
+ while (list($avail_lang, $junk) = each($SQSPELL_APP)){
+ $msg .= "<input type=\"checkbox\" name=\"use_langs[]\" value=\"$avail_lang\"";
+ if (in_array($avail_lang, $langs)) $msg .= " checked";
+ $msg .= ">$avail_lang<br>\n";
+ $add .= "<option";
+ if ($avail_lang==$langs[0]) $add .= " selected";
+ $add .= ">$avail_lang</option>\n";
+ }
+ $msg .= "</p>\n" . $add . "</select>\n";
+ $msg .= "</p></blockquote><p><input type=\"submit\" value=\" Make these changes \"></p>";
+ sqspell_makePage("Add International Dictionaries", null, $msg);
+?>
--- /dev/null
+<?php
+/**
+ OPTIONS_MAIN.MOD.PHP
+ ---------------------
+ Default page called when accessing SquirrelSpell's options.
+ **/
+ // E_ALL: protection behind 3000 miles.
+ global $SQSPELL_APP;
+
+ $msg = "<p>Please choose which options you wish to set up:</p>
+ <ul>
+ <li><a href=\"sqspell_options.php?MOD=edit_dic\">Edit your personal dictionary</a></li>
+ ";
+ // See if more than one dictionary is defined system-wide.
+ // If so, let the user choose his preferred ones.
+ if (sizeof($SQSPELL_APP)>1)
+ $msg .= "<li><a href=\"sqspell_options.php?MOD=lang_setup\">Set up international dictionaries</a></li>\n";
+ // See if MCRYPT is available.
+ // If so, let the user choose whether s/he wants to encrypt the
+ // personal dictionary file.
+ if (function_exists("mcrypt_generic"))
+ $msg .= "<li><a href=\"sqspell_options.php?MOD=enc_setup\">Encrypt or decrypt your personal dictionary</a></li>\n";
+ else $msg .= "<li>Encrypt or decrypt your personal dictionary <em>(not available)</em></li>\n";
+ $msg .= "</ul>\n";
+ sqspell_makePage("SquirrelSpell Options Menu", null, $msg);
+
+?>
--- /dev/null
+<?php
+
+/**
+ * SETUP.PHP
+ * ---------
+ * This is a standard Squirrelmail-1.2 API for plugins.
+ */
+
+/**
+ * This function checks whether the user's USER_AGENT is known to
+ * be broken. If so, returns true and the plugin is invisible to the
+ * offending browser.
+ */
+function soupNazi(){
+ global $HTTP_USER_AGENT;
+ require ('../plugins/squirrelspell/sqspell_config.php');
+ $soup_nazi = false;
+
+ $soup_menu = explode(',', $SQSPELL_SOUP_NAZI);
+ for ($i = 0; $i < sizeof($soup_menu); $i++) {
+ if (stristr($HTTP_USER_AGENT, trim($soup_menu[$i]))) {
+ $soup_nazi=true;
+ }
+ }
+ return $soup_nazi;
+}
+
+function squirrelmail_plugin_init_squirrelspell() {
+ /* Standard initialization API. */
+ global $squirrelmail_plugin_hooks;
+
+ $squirrelmail_plugin_hooks["compose_button_row"]["squirrelspell"] = "squirrelspell_setup";
+ $squirrelmail_plugin_hooks["options_register"]["squirrelspell"] = "squirrelspell_options";
+ $squirrelmail_plugin_hooks["options_link_and_description"]["squirrelspell"] = "squirrelspell_options";
+}
+
+function squirrelspell_options() {
+ // Gets added to the user's OPTIONS page.
+ global $optionpages;
+
+ if (soupNazi()) {
+ return;
+ }
+
+ /* Register Squirrelspell with the $optionpages array. */
+ $optionpages[] = array(
+ 'name' => 'SpellChecker Options',
+ 'url' => '../plugins/squirrelspell/sqspell_options.php',
+ 'desc' => 'Here you may set up how your personal dictionary is stored,
+ edit it, or choose which languages should be available to
+ you when spell-checking.',
+ 'js' => true
+ );
+}
+
+function squirrelspell_setup() {
+ /* Gets added to the COMPOSE buttons row. */
+ if (soupNazi()) {
+ return;
+ }
+
+?>
+ <script type="text/javascript">
+ <!--
+ // using document.write to hide this functionality from people
+ // with JavaScript turned off.
+ document.write("<input type=\"button\" value=\"Check Spelling\" onclick=\"window.open('../plugins/squirrelspell/sqspell_interface.php', 'sqspell', 'status=yes,width=550,height=370,resizable=yes')\">");
+ //-->
+ </script>
+<?php
+}
+
+?>
--- /dev/null
+<?php
+/** SquirrelSpell Configuration file. **/
+
+// Just for poor wretched souls with E_ALL. :)
+global $username, $data_dir;
+
+/**
+ SPELL-CHECKING APPLICATIONS:
+ ----------------------------
+ This feature was added/changed in 0.3. Use this array to set up
+ which dictionaries are available to users. If you only have
+ English spellchecker on your system, then let this line be:
+
+ $SQSPELL_APP = array("English" => "ispell -a");
+
+ or
+
+ $SQSPELL_APP = array("English" => "/usr/local/bin/aspell -a");
+
+ Sometimes you have to specify full path for PHP to find it.
+ Aspell is a better spell-checker than Ispell, so you're encouraged
+ to use it.
+
+ If you want to have more than one dictionary available to users,
+ configure the array to look something like this:
+
+ $SQSPELL_APP = array(
+ "English" => "aspell -a",
+ "Russian" => "ispell -d russian -a",
+ ...
+ "Swahili" => "ispell -d swahili -a"
+ );
+
+ Watch the commas, making sure there isn't one after your last
+ dictionary declaration. Also, make sure all these dictionaries
+ are available on your system before you specify them here.
+
+ Whatever your setting is, don't omit the "-a" flag.
+
+ **/
+$SQSPELL_APP = array("English" => "ispell -a");
+
+/**
+ DEFAULT DICTIONARY
+ -------------------
+ Even if you're only running one dictionary, still specify which one
+ is the default. Watch the case -- it has to be exactly as in array
+ you declared in $SQSPELL_APP.
+ **/
+$SQSPELL_APP_DEFAULT="English";
+
+/**
+ USER DICTIONARY:
+ -----------------
+ $SQSPELL_WORDS_FILE is a location and mask of a user dictionary file.
+ The default setting should be OK for most everyone. Read PRIVACY and
+ CRYPTO in the "doc" directory.
+ **/
+$SQSPELL_WORDS_FILE = "$data_dir/$username.words";
+
+/**
+ CASE SENSITIVITY:
+ ------------------
+ Use $SQSPELL_EREG="ereg" for case-sensitive matching of user
+ dictionary, or $SQSPELL_EREG="eregi" for case-insensitive
+ matching. It is advised to use case-sensitive matching.
+ **/
+$SQSPELL_EREG="ereg";
+
+/**
+ SOUP NAZI (AVOIDING BAD BROWSERS)
+ -------------------------------------
+ Since some browsers choke on JavaScript, here is an option to disable the
+ browsers with known problems. All you do is add some part of an USER_AGENT
+ string of an offending browser which you want to disable and users will not
+ know about this plugin. E.g. browsers with "Mozilla/4.61 (Macintosh, I, PPC)"
+ USER_AGENT string will get weeded out if you provide "Macintosh" in the
+ config string.
+
+ Mozilla/2 -- You're kidding, right?
+ Mozilla/3 -- known not to work
+ Opera -- known not to work
+ Macintosh -- Netscape 4.x on Macintosh chokes for some reason.
+ Adding until resolved.
+ **/
+$SQSPELL_SOUP_NAZI = "Mozilla/3, Mozilla/2, Opera 4, Opera/4, Macintosh";
+
+?>
--- /dev/null
+<?php
+/** SquirrelSpell Configuration file. **/
+
+// Just for poor wretched souls with E_ALL. :)
+global $username, $data_dir;
+
+/**
+ SPELL-CHECKING APPLICATIONS:
+ ----------------------------
+ This feature was added/changed in 0.3. Use this array to set up
+ which dictionaries are available to users. If you only have
+ English spellchecker on your system, then let this line be:
+
+ $SQSPELL_APP = array("English" => "ispell -a");
+
+ or
+
+ $SQSPELL_APP = array("English" => "/usr/local/bin/aspell -a");
+
+ Sometimes you have to specify full path for PHP to find it.
+ Aspell is a better spell-checker than Ispell, so you're encouraged
+ to use it.
+
+ If you want to have more than one dictionary available to users,
+ configure the array to look something like this:
+
+ $SQSPELL_APP = array(
+ "English" => "aspell -a",
+ "Russian" => "ispell -d russian -a",
+ ...
+ "Swahili" => "ispell -d swahili -a"
+ );
+
+ Watch the commas, making sure there isn't one after your last
+ dictionary declaration. Also, make sure all these dictionaries
+ are available on your system before you specify them here.
+
+ Whatever your setting is, don't omit the "-a" flag.
+
+ **/
+$SQSPELL_APP = array("English" => "ispell -a");
+
+/**
+ DEFAULT DICTIONARY
+ -------------------
+ Even if you're only running one dictionary, still specify which one
+ is the default. Watch the case -- it has to be exactly as in array
+ you declared in $SQSPELL_APP.
+ **/
+$SQSPELL_APP_DEFAULT="English";
+
+/**
+ USER DICTIONARY:
+ -----------------
+ $SQSPELL_WORDS_FILE is a location and mask of a user dictionary file.
+ The default setting should be OK for most everyone. Read PRIVACY and
+ CRYPTO in the "doc" directory.
+ **/
+$SQSPELL_WORDS_FILE = "$data_dir/$username.words";
+
+/**
+ CASE SENSITIVITY:
+ ------------------
+ Use $SQSPELL_EREG="ereg" for case-sensitive matching of user
+ dictionary, or $SQSPELL_EREG="eregi" for case-insensitive
+ matching. It is advised to use case-sensitive matching.
+ **/
+$SQSPELL_EREG="ereg";
+
+/**
+ SOUP NAZI (AVOIDING BAD BROWSERS)
+ -------------------------------------
+ Since some browsers choke on JavaScript, here is an option to disable the
+ browsers with known problems. All you do is add some part of an USER_AGENT
+ string of an offending browser which you want to disable and users will not
+ know about this plugin. E.g. browsers with "Mozilla/4.61 (Macintosh, I, PPC)"
+ USER_AGENT string will get weeded out if you provide "Macintosh" in the
+ config string.
+
+ Mozilla/2 -- You're kidding, right?
+ Mozilla/3 -- known not to work
+ Opera -- known not to work
+ Macintosh -- Netscape 4.x on Macintosh chokes for some reason.
+ Adding until resolved.
+ **/
+$SQSPELL_SOUP_NAZI = "Mozilla/3, Mozilla/2, Opera 4, Opera/4, Macintosh";
+
+?>
--- /dev/null
+<?php
+/**
+ SQSPELL_FUNCTIONS.PHP
+ --------------
+ All SquirrelSpell-wide functions are in this file.
+ **/
+
+function sqspell_makePage($title, $scriptsrc, $body){
+ //
+ // GUI wrap-around for the OPTIONS page.
+ //
+ global $color, $SQSPELL_VERSION, $MOD;
+ displayPageHeader($color, "None");
+ ?>
+ <br>
+ <?php if($scriptsrc) { ?>
+ <script type="text/javascript" src="js/<?php echo $scriptsrc ?>"></script>
+ <?php } ?>
+ <table width="95%" align="center" border="0" cellpadding="2" cellspacing="0">
+ <tr>
+ <td bgcolor="<?php echo $color[9] ?>" align="center">
+ <strong><?php echo $title ?></strong>
+ </td>
+ </tr>
+ <tr><td><hr></td></tr>
+ <tr><td>
+ <?php echo $body ?>
+ </td></tr>
+ <?php if ($MOD!="options_main"){
+ // Generate a nice return-to-main link.
+ ?>
+ <tr><td><hr></td></tr>
+ <tr><td align="center"><a href="sqspell_options.php">Back to "SpellChecker Options" page</a></td></tr>
+ <?php } ?>
+ <tr><td><hr></td></tr>
+ <tr>
+ <td bgcolor="<?php echo $color[9] ?>" align="center">
+ SquirrelSpell <?php echo $SQSPELL_VERSION ?>
+ </td>
+ </tr>
+ </table>
+ <?php
+}
+
+function sqspell_makeWindow($onload, $title, $scriptsrc, $body){
+ //
+ // GUI wrap-around for the pop-up window interface.
+ //
+ global $color, $SQSPELL_VERSION;
+ ?>
+ <html>
+ <head>
+ <title><?php echo $title ?></title>
+ <?php if ($scriptsrc){ ?>
+ <script type="text/javascript" src="js/<?php echo $scriptsrc ?>"></script>
+ <?php } ?>
+ </head>
+ <body text="<?php echo $color[8] ?>"
+ bgcolor="<?php echo $color[4] ?>"
+ link="<?php echo $color[7] ?>"
+ vlink="<?php echo $color[7] ?>"
+ alink="<?php echo $color[7] ?>"<?php
+ if ($onload) echo " onload=\"$onload\""; ?>>
+ <table width="100%" border="0" cellpadding="2">
+ <tr>
+ <td bgcolor="<?php echo $color[9] ?>" align="center">
+ <strong><?php echo $title ?></strong>
+ </td>
+ </tr>
+ <tr>
+ <td><hr></td>
+ </tr>
+ <tr>
+ <td>
+ <?php echo $body ?>
+ </td>
+ </tr>
+ <tr>
+ <td><hr></td>
+ </tr>
+ <tr>
+ <td bgcolor="<?php echo $color[9] ?>" align="center">
+ SquirrelSpell <?php echo $SQSPELL_VERSION ?>
+ </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+ <?php
+}
+
+function sqspell_crypto($mode, $ckey, $input){
+ //
+ // This function does the encryption and decryption of the user
+ // dictionary. It is only available when PHP is compiled
+ // --with-mcrypt. See doc/CRYPTO for more information.
+ //
+ if (!function_exists(mcrypt_generic)) return "PANIC";
+ $td = mcrypt_module_open(MCRYPT_Blowfish, "", MCRYPT_MODE_ECB, "");
+ $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size ($td), MCRYPT_RAND);
+ mcrypt_generic_init($td, $ckey, $iv);
+ switch ($mode){
+ case "encrypt":
+ $crypto = mcrypt_generic($td, $input);
+ break;
+ case "decrypt":
+ $crypto = mdecrypt_generic($td, $input);
+ // See if it decrypted successfully. If so, it should contain
+ // the string "# SquirrelSpell".
+ if (!strstr($crypto, "# SquirrelSpell")) $crypto="PANIC";
+ break;
+ }
+ mcrypt_generic_end ($td);
+ return $crypto;
+}
+
+function sqspell_upgradeWordsFile($words_string){
+ //
+ // This function transparently upgrades the 0.2 dictionary format to
+ // 0.3, since user-defined languages have been added in 0.3 and
+ // the new format keeps user dictionaries selection in the file.
+ //
+ global $SQSPELL_APP_DEFAULT, $SQSPELL_VERSION;
+
+ // Define just one dictionary for this user -- the default.
+ // If the user wants more, s/he can set them up in personal
+ // preferences. See doc/UPGRADING for more info.
+ $new_words_string=substr_replace($words_string, "# SquirrelSpell User Dictionary $SQSPELL_VERSION\n# Last Revision: " . date("Y-m-d") . "\n# LANG: $SQSPELL_APP_DEFAULT\n# $SQSPELL_APP_DEFAULT", 0, strpos($words_string, "\n")) . "# End\n";
+ sqspell_writeWords($new_words_string);
+ return $new_words_string;
+}
+
+function sqspell_getSettings($words){
+ //
+ // Right now it just returns an array with the dictionaries
+ // available to the user for spell-checking. It will probably
+ // do more in the future, as features are added.
+ //
+ global $SQSPELL_APP, $SQSPELL_APP_DEFAULT;
+ if (sizeof($SQSPELL_APP) > 1){
+ // OK, so there are more than one dictionary option.
+ // Now load the user prefs.
+ if(!$words) $words=sqspell_getWords();
+ if ($words){
+ // find which dictionaries user wants to use
+ preg_match("/# LANG: (.*)/i", $words, $matches);
+ $langs=explode(", ", $matches[1]);
+ } else {
+ // User doesn't have a personal dictionary. Set him up with
+ // a default setting.
+ $langs[0]=$SQSPELL_APP_DEFAULT;
+ }
+ } else {
+ // There is only one dictionary defined system-wide.
+ $langs[0]=$SQSPELL_APP_DEFAULT;
+ }
+ return $langs;
+}
+
+function sqspell_getLang($words, $lang){
+ //
+ // Returns words of a specific user dictionary.
+ //
+ $start=strpos($words, "# $lang\n");
+ if (!$start) return "";
+ $end=strpos($words, "#", $start+1);
+ $lang_words = substr($words, $start, $end-$start);
+ return $lang_words;
+}
+
+function sqspell_getWords(){
+ //
+ // This baby operates the user dictionary. If the format is clear-text,
+ // then it just reads the file and returns it. However, if the file is
+ // encrypted, then it decrypts it, checks whether the decryption was
+ // successful, troubleshoots if not, then returns the clear-text dictionary
+ // to the app.
+ //
+ global $SQSPELL_WORDS_FILE, $SQSPELL_CRYPTO;
+ $words="";
+ if (file_exists($SQSPELL_WORDS_FILE)){
+ // Gobble it up.
+ $fp=fopen($SQSPELL_WORDS_FILE, "r");
+ $words=fread($fp, filesize($SQSPELL_WORDS_FILE));
+ fclose($fp);
+ }
+ // Check if this is an encrypted file by looking for
+ // the string "# SquirrelSpell" in it.
+ if ($words && !strstr($words, "# SquirrelSpell")){
+ // This file is encrypted or mangled. Try to decrypt it.
+ // If fails, raise hell.
+ global $key, $onetimepad, $old_key;
+ if ($old_key) {
+ // an override in case user is trying to decrypt a dictionary
+ // with his old password
+ $clear_key=$old_key;
+ } else {
+ // get user's password (the key).
+ $clear_key = OneTimePadDecrypt($key, $onetimepad);
+ }
+ // decrypt
+ $words=sqspell_crypto("decrypt", $clear_key, $words);
+ if ($words=="PANIC"){
+ // AAAAAAAAAAAH!!!!! OK, ok, breathe!
+ // Let's hope the decryption failed because the user changed his
+ // password. Bring up the option to key in the old password
+ // or wipe the file and start over if everything else fails.
+ $msg="<p>
+ <strong>ATTENTION:</strong><br>
+ SquirrelSpell was unable to decrypt your personal dictionary. This is most likely
+ due to the fact that you have changed your mailbox password. In order to proceed,
+ you will have to supply your old password so that SquirrelSpell can decrypt your
+ personal dictionary. It will be re-encrypted with your new password after this.<br>
+ If you haven't encrypted your dictionary, then it got mangled and is no longer
+ valid. You will have to delete it and start anew. This is also true if you don't
+ remember your old password -- without it, the encrypted data is no longer
+ accessible.</p>
+ <blockquote>
+ <form method=\"post\" onsubmit=\"return AYS()\">
+ <input type=\"hidden\" name=\"MOD\" value=\"crypto_badkey\">
+ <p><input type=\"checkbox\" name=\"delete_words\" value=\"ON\"> Delete my dictionary and start a new one<br>
+ Decrypt my dictionary with my old password: <input name=\"old_key\" size=\"10\"></p>
+ </blockquote>
+ <p align=\"center\"><input type=\"submit\" value=\"Proceed >>\"></p>
+ </form>
+ ";
+ // See if this happened in the pop-up window or when accessing
+ // the SpellChecker options page.
+ global $SCRIPT_NAME;
+ if (strstr($SCRIPT_NAME, "sqspell_options"))
+ sqspell_makePage("Error Decrypting Dictionary", "decrypt_error.js", $msg);
+ else sqspell_makeWindow(null, "Error Decrypting Dictionary", "decrypt_error.js", $msg);
+ exit;
+ } else {
+ // OK! Phew. Set the encryption flag to true so we can later on
+ // encrypt it again before saving to HDD.
+ $SQSPELL_CRYPTO=true;
+ }
+ } else {
+ // No encryption is used. Set $SQSPELL_CRYPTO to false, in case we have to
+ // save the dictionary later.
+ $SQSPELL_CRYPTO=false;
+ }
+ // Check if we need to upgrade the dictionary from version 0.2.x
+ if (strstr($words, "Dictionary v0.2")) $words=sqspell_upgradeWordsFile($words);
+ return $words;
+}
+
+function sqspell_writeWords($words){
+ //
+ // Writes user dictionary into the $username.words file, then changes mask
+ // to 0600. If encryption is needed -- does that, too.
+ //
+ global $SQSPELL_WORDS_FILE, $SQSPELL_CRYPTO;
+ // if $words is empty, create a template entry.
+ if (!$words) $words=sqspell_makeDummy();
+ if ($SQSPELL_CRYPTO){
+ // User wants to encrypt the file. So be it.
+ // get his password to use as a key.
+ global $key, $onetimepad;
+ $clear_key=OneTimePadDecrypt($key, $onetimepad);
+ // Try encrypting it. If fails, scream bloody hell.
+ $save_words = sqspell_crypto("encrypt", $clear_key, $words);
+ if ($save_words=="PANIC"){
+ // AAAAAAAAH! I'm not handling this yet, since obviously
+ // the admin of the site forgot to compile the MCRYPT support in.
+ // I will add a handler for this case later, when I can come up
+ // with some work-around... Right now, do nothing. Let the Admin's
+ // head hurt.. ;)))
+ }
+ } else {
+ $save_words = $words;
+ }
+ $fp=fopen($SQSPELL_WORDS_FILE, "w");
+ fwrite($fp, $save_words);
+ fclose($fp);
+ chmod($SQSPELL_WORDS_FILE, 0600);
+}
+
+function sqspell_deleteWords(){
+ //
+ // so I open the door to my enemies,
+ // and I ask can we wipe the slate clean,
+ // but they tell me to please go...
+ // uhm... Well, this just erases the user dictionary file.
+ //
+ global $SQSPELL_WORDS_FILE;
+ if (file_exists($SQSPELL_WORDS_FILE)) unlink($SQSPELL_WORDS_FILE);
+}
+
+function sqspell_makeDummy(){
+ //
+ // Creates an empty user dictionary for the sake of saving prefs or
+ // whatever.
+ //
+ global $SQSPELL_VERSION, $SQSPELL_APP_DEFAULT;
+ $words="# SquirrelSpell User Dictionary $SQSPELL_VERSION\n# Last Revision: " . date("Y-m-d") . "\n# LANG: $SQSPELL_APP_DEFAULT\n# End\n";
+ return $words;
+}
+
+/**
+ VERSION:
+ ---------
+ SquirrelSpell version. Don't modify, since it identifies the format
+ of the user dictionary files and messing with this can do ugly
+ stuff. :)
+ **/
+$SQSPELL_VERSION="v0.3.5";
+
+
+?>
--- /dev/null
+<?php
+
+/**
+ SQSPELL_INTERFACE.PHP
+ ----------------------
+ This is a main wrapper for the pop-up window interface of
+ SquirrelSpell.
+ **/
+
+// Set up a couple of non-negotiable constants. Don't change these,
+// the setuppable stuff is in sqspell_config.php
+$SQSPELL_DIR="squirrelspell";
+$SQSPELL_CRYPTO=false;
+
+// Load the necessary stuff.
+chdir("..");
+include("../src/validate.php");
+include("../src/load_prefs.php");
+include ("$SQSPELL_DIR/sqspell_config.php");
+require ("$SQSPELL_DIR/sqspell_functions.php");
+
+// Now load the necessary module from the modules dir.
+//
+if (!$MOD) $MOD="init";
+
+// see if someone is attempting to be nasty by trying to get out of the
+// modules directory, although it probably wouldn't do them any good,
+// since every module has to end with .mod.php. Still, they deserve
+// to be warned. ;)
+if (strstr($MOD, ".") || strstr($MOD, "/") || strstr($MOD, "%")){
+ echo "SECURITY BREACH ON DECK 5! CMDR TUVOK AND SECURITY TEAM REQUESTED.";
+ exit;
+}
+// fetch the module now.
+include ("$SQSPELL_DIR/modules/$MOD.mod.php");
+?>
--- /dev/null
+<?php
+/**
+ SQSPELL_OPTIONS.PHP
+ --------------------
+ Main wrapper for the options interface.
+ **/
+// Set a couple of constants. Don't change these, the setuppable stuff is
+// in sqspell_config.php
+$SQSPELL_DIR="squirrelspell";
+$SQSPELL_CRYPTO=false;
+
+// Load some necessary stuff.
+chdir("..");
+include("../src/validate.php");
+include("../src/load_prefs.php");
+include("../functions/strings.php");
+include("../functions/page_header.php");
+include ("$SQSPELL_DIR/sqspell_config.php");
+require ("$SQSPELL_DIR/sqspell_functions.php");
+
+// Access the module needed
+//
+if (!$MOD) $MOD="options_main";
+
+// see if someone is attempting to be nasty by trying to get out of the
+// modules directory, although it probably wouldn't do them any good,
+// since every module has to end with .mod.php. Still, they deserve
+// to be warned. ;)
+if (strstr($MOD, ".") || strstr($MOD, "/") || strstr($MOD, "%")){
+ echo "SECURITY BREACH ON DECK 5! CMDR TUVOK AND SECURITY TEAM REQUESTED.";
+ exit;
+}
+// load the stuff already.
+include ("$SQSPELL_DIR/modules/$MOD.mod.php");
+?>
--- /dev/null
+Installing Plugins
+==================
+Simply untar the file in the plugins directory, and make sure it is
+in its own directory, and that the name of the directory is the name
+of the plugin. Example below uses "plug_demo" as the name of the
+plugin:
+
+ $ cd plugins
+ $ tar -zxvf /usr/archives/plug_demo.tar.gz
+
+Then go to your config directory and run conf.pl. Choose option
+8 and add the plugin. Save and exit, then that should be all
+if the plugin was made correctly. :)
+
+ $ cd ../config
+ $ ./conf.pl
--- /dev/null
+Message Translation -- Version 1.4
+
+If you have ever received a mail message from someone who is not in
+your country, you probably noticed that they used a different language
+than you. If you don't know their language, a translator might help you
+out.
+
+
+Features
+========
+
+* Multiple translation servers
+* Uses your language preference for setting up default translation options
+* You pick where you see the translation box
+* You decide which translation buttons you see
+
+
+Description
+===========
+
+This plugin lets you select, on a per-user basis, the translator you want
+to use. It defaults to None. It has different servers you can use, and
+it lists their strengths and limits with each one. Also, there are
+multiple servers just in case one changes their interface or goes down.
+
+Since SquirrelMail is designed to have multiple translations of the text,
+this plugin takes your preference and will use it for selecting what to
+translate the text into.
+
+
+Future Work
+===========
+
+* Grab translation directly from server (need to send POST request directly)
+* Translate your outgoing message
+
+
+Servers
+=======
+
+Babelfish = babelfish.altavista.com
+Go.com = translator.go.com
+Dictionary.com = www.dictionary.com/translate
+InterTran = tranexp.com
+GPLTrans = www.translator.cx
+
+
+Installation
+============
+
+As with other plugins, just uncompress the archive in the plugins
+directory, go back to the main directory, run configure and add the plugin.
+
+Questions/comments/flames/etc can be sent to the Squirrelmail Plugins list
+
+
+Changes
+=======
+1.3 -> 1.4
+ * Modified to use new option page hook.
+ Paul Joseph Thompson <captbunzo@squirrelmail.org>
+
+1.2 -> 1.3
+ * Stupid bugfix. :-)
+
+1.1 -> 1.2
+ * HTML changed to look better
+
+1.0 -> 1.1
+ * Added more servers
+ * Added better language handling
+ * You have to pick a server, but you can choose not to have the box
+ * Added better support for direction of translation
--- /dev/null
+<?php
+ /**
+ ** options.php
+ **
+ ** Pick your translator to translate the body of incoming mail messages
+ **
+ **/
+
+ chdir("..");
+
+ session_start();
+
+ if (!isset($config_php))
+ include("../config/config.php");
+ if (!isset($strings_php))
+ include("../functions/strings.php");
+ if (!isset($page_header_php))
+ include("../functions/page_header.php");
+ if (!isset($display_messages_php))
+ include("../functions/display_messages.php");
+ if (!isset($imap_php))
+ include("../functions/imap.php");
+ if (!isset($array_php))
+ include("../functions/array.php");
+ if (!isset($i18n_php))
+ include("../functions/i18n.php");
+
+
+ include("../src/load_prefs.php");
+ displayPageHeader($color, "None");
+
+ $translate_server = getPref($data_dir, $username, "translate_server");
+ if ($translate_server == '')
+ $translate_server = 'babelfish';
+ $translate_location = getPref($data_dir, $username, "translate_location");
+ if ($translate_location == '')
+ $translate_location = 'center';
+ $translate_show_read = getPref($data_dir, $username, 'translate_show_read');
+ $translate_show_send = getPref($data_dir, $username, 'translate_show_send');
+ $translate_same_window = getPref($data_dir, $username, 'translate_same_window');
+
+ function ShowOption($Var, $value, $Desc)
+ {
+ $Var = 'translate_' . $Var;
+
+ global $$Var;
+
+ echo '<option value="' . $value . '"';
+ if ($$Var == $value)
+ {
+ echo ' SELECTED';
+ }
+ echo '>' . $Desc . "</option>\n";
+ }
+
+
+?>
+ <br>
+ <table width=95% align=center border=0 cellpadding=2 cellspacing=0><tr><td bgcolor="<?php echo $color[0] ?>">
+ <center><b><?php echo _("Options") ?> - Translator</b></center>
+ </td></tr></table>
+
+ <p>Your server options are as follows:</p>
+
+ <ul>
+
+ <li><b>Babelfish</b> -
+ 13 language pairs,
+ maximum of 1000 characters translated,
+ powered by Systran
+ [ <a href="http://babelfish.altavista.com/"
+ target="_blank">Babelfish</a> ]</li>
+
+ <li><b>Go.com</b> -
+ 10 language pairs,
+ maximum of 25 kilobytes translated,
+ powered by Systran
+ [ <a href="http://translator.go.com/"
+ target="_blank">Translator.Go.com</a> ]</li>
+
+ <li><b>Dictionary.com</b> -
+ 12 language pairs,
+ no known limits,
+ powered by Systran
+ [ <a href="http://www.dictionary.com/translate"
+ target="_blank">Dictionary.com</a> ]</li>
+
+ <li><b>InterTran</b> -
+ 767 language pairs,
+ no known limits,
+ powered by Translation Experts's InterTran
+ [ <a href="http://www.tranexp.com/"
+ target="_blank">Translation Experts</a> ]</li>
+
+ <li><b>GPLTrans</b> -
+ 8 language pairs,
+ no known limits,
+ powered by GPLTrans (free, open source)
+ [ <a href="http://www.translator.cx/"
+ target="_blank">GPLTrans</a> ]</li>
+
+ </ul>
+
+ <p>You also decide if you want the translation box displayed,
+ and where it will be located.</p>
+
+ <form action="../../src/options.php" method=post>
+ <table border=0 cellpadding=0 cellspacing=2>
+ <tr><td align=right nowrap>Select your translator:</td>
+ <td><select name="translate_translate_server">
+<?PHP
+ ShowOption('server', 'babelfish', 'Babelfish');
+ ShowOption('server', 'go', 'Go.com');
+ ShowOption('server', 'dictionary', 'Dictionary.com');
+ ShowOption('server', 'intertran', 'Intertran');
+ ShowOption('server', 'gpltrans', 'GPLTrans');
+?> </select>
+ </td></tr>
+ <tr><td align=right nowrap valign="top">When reading:</td>
+ <td><input type=checkbox name="translate_translate_show_read"<?PHP
+ if ($translate_show_read)
+ echo " CHECKED";
+ ?>> - Show translation box
+ <select name="translate_translate_location">
+<?PHP
+ ShowOption('location', 'left', 'to the left');
+ ShowOption('location', 'center', 'in the center');
+ ShowOption('location', 'right', 'to the right');
+?> </select><br>
+ <input type=checkbox name="translate_translate_same_window"<?PHP
+ if ($translate_same_window)
+ echo " CHECKED";
+ ?>> - Translate inside the SquirrelMail frames</td></tr>
+ <tr><td align=right nowrap>When composing:</td>
+ <td><input type=checkbox name="translate_translate_show_send"<?PHP
+ if ($translate_show_send)
+ echo " CHECKED";
+ ?>> - Not yet functional, currently does nothing</td></tr>
+ <tr><td></td><td>
+ <input type="submit" value="Submit" name="submit_translate">
+ </td></tr>
+ </table>
+ </form>
+</body></html>
--- /dev/null
+<?php
+
+/* Easy plugin that sends the body of the message to a new browser
+window using the specified translator. It can also translate your
+outgoing message if you send it to someone in a different country.
+
+ Languages from i18n, incorporated in the auto-language selection:
+ en - English
+ no - Norwegian (Bokmål)
+ no_NO_ny - Norwegian (Nynorsk)
+ de - Deutsch
+ ru - Russian KOI8-R
+ pl - Polish
+ sv - Swedish
+ nl - Dutch
+ pt_BR - Portuguese (Brazil)
+ fr - French
+ it - Italian
+ cs - Czech
+ es - Spanish
+ ko - Korean
+*/
+
+
+/* Initialize the translation plugin */
+function squirrelmail_plugin_init_translate() {
+ global $squirrelmail_plugin_hooks;
+
+ $squirrelmail_plugin_hooks['read_body_bottom']['translate'] = 'translate_read_form';
+ $squirrelmail_plugin_hooks['options_register']['translate'] = 'translate_opt';
+ $squirrelmail_plugin_hooks['options_save']['translate'] = 'translate_sav';
+ $squirrelmail_plugin_hooks['loading_prefs']['translate'] = 'translate_pref';
+ $squirrelmail_plugin_hooks['compose_button_row']['translate'] = 'translate_button';
+}
+
+
+/* Show the translation for a message you're reading */
+function translate_read_form() {
+ global $color, $translate_server;
+ global $body, $translate_dir;
+ global $translate_show_read;
+
+ if (!$translate_show_read) {
+ return;
+ }
+
+ $translate_dir = 'to';
+
+ $new_body = $body;
+ $pos = strpos($new_body,
+ '">Download this as a file</A></CENTER><BR></SMALL>');
+ if (is_int($pos)) {
+ $new_body = substr($new_body, 0, $pos);
+ }
+
+ $trans = get_html_translation_table('HTMLENTITIES');
+ $trans[' '] = ' ';
+ $trans = array_flip($trans);
+ $new_body = strtr($new_body, $trans);
+
+ $new_body = urldecode($new_body);
+ $new_body = strip_tags($new_body);
+
+ /* I really don't like this next part ... */
+ $new_body = str_replace('"', "''", $new_body);
+ $new_body = strtr($new_body, "\n", ' ');
+
+ $function = 'translate_form_' . $translate_server;
+ $function($new_body);
+}
+
+function translate_table_end() {
+ ?></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </form>
+ <?php
+}
+
+
+function translate_button() {
+ global $translate_show_send;
+
+ if (! $translate_show_send) {
+ return;
+ }
+}
+
+
+function translate_opt() {
+ global $optionpages;
+ $optionpages[] = array(
+ 'name' => 'Translation Options',
+ 'url' => '../plugins/translate/options.php',
+ 'desc' => 'Which translator should be used when you get messages in a different language?',
+ 'js' => false
+ );
+}
+
+function translate_sav() {
+ global $username,$data_dir;
+ global $submit_translate, $translate_translate_server;
+ global $translate_translate_location;
+ global $translate_translate_show_read;
+ global $translate_translate_show_send;
+ global $translate_translate_same_window;
+
+ if ($submit_translate) {
+ if (isset($translate_translate_server)) {
+ setPref($data_dir, $username, 'translate_server', $translate_translate_server);
+ } else {
+ setPref($data_dir, $username, 'translate_server', 'babelfish');
+ }
+
+ if (isset($translate_translate_location)) {
+ setPref($data_dir, $username, 'translate_location', $translate_translate_location);
+ } else {
+ setPref($data_dir, $username, 'translate_location', 'center');
+ }
+
+ if (isset($translate_translate_show_read)) {
+ setPref($data_dir, $username, 'translate_show_read', '1');
+ } else {
+ setPref($data_dir, $username, 'translate_show_read', '');
+ }
+
+ if (isset($translate_translate_show_send)) {
+ setPref($data_dir, $username, 'translate_show_send', '1');
+ } else {
+ setPref($data_dir, $username, 'translate_show_send', '');
+ }
+
+ if (isset($translate_translate_same_window)) {
+ setPref($data_dir, $username, 'translate_same_window', '1');
+ } else {
+ setPref($data_dir, $username, 'translate_same_window', '');
+ }
+
+ echo '<center>Translation options saved.</center>';
+ }
+}
+
+
+function translate_pref() {
+ global $username, $data_dir;
+ global $translate_server, $translate_location;
+ global $translate_show_send, $translate_show_read;
+ global $translate_same_window;
+
+ $translate_server = getPref($data_dir, $username, 'translate_server');
+ if ($translate_server == '') {
+ $translate_server = 'babelfish';
+ }
+
+ $translate_location = getPref($data_dir, $username, 'translate_location');
+ if ($translate_location == '') {
+ $translate_location = 'center';
+ }
+
+ $translate_show_send = getPref($data_dir, $username, 'translate_show_send');
+ $translate_show_read = getPref($data_dir, $username, 'translate_show_read');
+ $translate_same_window = getPref($data_dir, $username, 'translate_same_window');
+}
+
+
+/**
+ * This function could be sped up.
+ * It basically negates the process if a ! is found in the beginning and
+ * matches a * at the end with 0 or more characters.
+ */
+function translate_does_it_match_language($test) {
+ global $squirrelmail_language;
+ $true = 1;
+ $false = 0;
+ $index = 0;
+ $smindex = 0;
+
+ if (! $test || ! $squirrelmail_language) {
+ return $false;
+ }
+
+ if ($test[$index] == '!') {
+ $index ++;
+ $true = 0;
+ $false = 1;
+ }
+
+ if (($index == 0) && ($test == $squirrelmail_language)) {
+ return $true;
+ }
+
+ while ($test[$index]) {
+ if ($test[$index] == '*') {
+ return $true;
+ }
+ if ($test[$index] != $squirrelmail_language[$smindex]) {
+ return $false;
+ }
+ $index ++;
+ $smindex ++;
+ }
+
+ return $false;
+}
+
+
+function translate_lang_opt($from, $to, $value, $text) {
+ global $translate_dir;
+
+ echo ' <option value="' . $value . '"';
+
+ if (translate_does_it_match_language($to) && ($translate_dir == 'to')) {
+ echo ' SELECTED';
+ }
+
+ if (translate_does_it_match_language($from) && ($translate_dir == 'from')) {
+ echo ' SELECTED';
+ }
+
+ echo '>' . $text . "</option>\n";
+}
+
+
+function translate_new_form($action) {
+ global $translate_dir, $translate_new_window, $translate_location;
+ global $color, $translate_same_window;
+
+ echo '<form action="';
+
+ if ($translate_dir == 'to') {
+ echo $action;
+ } else {
+ echo 'translate.php';
+ }
+
+ echo '" method="post"';
+
+ if (!$translate_same_window) {
+ echo ' target="_blank"';
+ }
+
+ echo ">\n";
+
+ ?><table align="<?php echo $translate_location ?>" cellpadding=3 cellspacing=0 border=0 bgcolor=<?php echo $color[10] ?>>
+ <tr>
+ <td>
+ <table cellpadding=2 cellspacing=1 border=0 bgcolor="<?php echo $color[5] ?>">
+ <tr>
+ <td><?php
+}
+
+function translate_form_babelfish($message) {
+ translate_new_form('http://babelfish.altavista.com/translate.dyn');
+?>
+ <input type="hidden" name="doit" value="done">
+ <input type="hidden" name="BabelFishFrontPage" value="yes">
+ <input type="hidden" name="bblType" value="urltext">
+ <input type="hidden" name="urltext" value="<?php echo $message; ?>">
+ <select name="lp"><?php
+ translate_lang_opt('en', 'fr', 'en_fr', 'English to French');
+ translate_lang_opt('', 'de', 'en_de', 'English to German');
+ translate_lang_opt('', 'it', 'en_it', 'English to Italian');
+ translate_lang_opt('', 'pt*', 'en_pt', 'English to Portuguese');
+ translate_lang_opt('', 'es', 'en_es', 'English to Spanish');
+ translate_lang_opt('fr', 'en', 'fr_en', 'French to English');
+ translate_lang_opt('de', '', 'de_en', 'German to English');
+ translate_lang_opt('it', '', 'it_en', 'Italian to English');
+ translate_lang_opt('pt*', '', 'pt_en', 'Portuguese to English');
+ translate_lang_opt('es', '', 'es_en', 'Spanish to English');
+ translate_lang_opt('', '', 'de_fr', 'German to French');
+ translate_lang_opt('', '', 'fr_de', 'French to German');
+ translate_lang_opt('ru', '', 'ru_en', 'Russian to English');
+?></select>
+ Babelfish: <input type="Submit" value="Translate">
+<?php
+ translate_table_end();
+}
+
+function translate_form_go($message) {
+ translate_new_form('http://translator.go.com/cb/trans_entry');
+?>
+ <input type=hidden name=input_type value=text>
+ <select name=lp><?php
+ translate_lang_opt('en', 'es', 'en_sp', 'English to Spanish');
+ translate_lang_opt('', 'fr', 'en_fr', 'English to French');
+ translate_lang_opt('', 'de', 'en_ge', 'English to German');
+ translate_lang_opt('', 'it', 'en_it', 'English to Italian');
+ translate_lang_opt('', 'pt', 'en_pt', 'English to Portuguese');
+ translate_lang_opt('es', 'en', 'sp_en', 'Spanish to English');
+ translate_lang_opt('fr', '', 'fr_en', 'French to English');
+ translate_lang_opt('de', '', 'ge_en', 'German to English');
+ translate_lang_opt('it', '', 'it_en', 'Italian to English');
+ translate_lang_opt('pt', '', 'pt_en', 'Portuguese to English');
+?></select>
+ <input type="hidden" name="text" value="<?php echo $message ?>">
+ Go.com: <input type="Submit" value="Translate">
+<?php
+ translate_table_end();
+}
+
+function translate_form_intertran($message) {
+ translate_new_form('http://www.tranexp.com:2000/InterTran');
+?>
+ <INPUT TYPE="hidden" NAME="topframe" VALUE="yes">
+ <INPUT TYPE="hidden" NAME="type" VALUE="text">
+ <input type="hidden" name="text" value="<?php echo $message ?>">
+ <SELECT name="from"><?PHP
+ translate_lang_opt('pt_BR', '', 'pob', 'Brazilian Portuguese');
+ translate_lang_opt('', '', 'bul', 'Bulgarian (CP 1251)');
+ translate_lang_opt('', '', 'cro', 'Croatian (CP 1250)');
+ translate_lang_opt('cs', '', 'che', 'Czech (CP 1250)');
+ translate_lang_opt('', '', 'dan', 'Danish');
+ translate_lang_opt('nl', '', 'dut', 'Dutch');
+ translate_lang_opt('en', '!en', 'eng', 'English');
+ translate_lang_opt('', '', 'spe', 'European Spanish');
+ translate_lang_opt('', '', 'fin', 'Finnish');
+ translate_lang_opt('fr', '', 'fre', 'French');
+ translate_lang_opt('de', '', 'ger', 'German');
+ translate_lang_opt('', '', 'grk', 'Greek');
+ translate_lang_opt('', '', 'hun', 'Hungarian (CP 1250)');
+ translate_lang_opt('', '', 'ice', 'Icelandic');
+ translate_lang_opt('it', '', 'ita', 'Italian');
+ translate_lang_opt('', '', 'jpn', 'Japanese (Shift JIS)');
+ translate_lang_opt('', '', 'spl', 'Latin American Spanish');
+ translate_lang_opt('no*', '', 'nor', 'Norwegian');
+ translate_lang_opt('pl', '', 'pol', 'Polish (ISO 8859-2)');
+ translate_lang_opt('', '', 'poe', 'Portuguese');
+ translate_lang_opt('', '', 'rom', 'Romanian (CP 1250)');
+ translate_lang_opt('ru', '', 'rus', 'Russian (CP 1251)');
+ translate_lang_opt('', '', 'sel', 'Serbian (CP 1250)');
+ translate_lang_opt('', '', 'slo', 'Slovenian (CP 1250)');
+ translate_lang_opt('es', '', 'spa', 'Spanish');
+ translate_lang_opt('sv', '', 'swe', 'Swedish');
+ translate_lang_opt('', '', 'wel', 'Welsh');
+?></SELECT> to <SELECT name="to"><?PHP
+ translate_lang_opt('', 'pt_BR', 'pob', 'Brazilian Portuguese');
+ translate_lang_opt('', '', 'bul', 'Bulgarian (CP 1251)');
+ translate_lang_opt('', '', 'cro', 'Croatian (CP 1250)');
+ translate_lang_opt('', 'cs', 'che', 'Czech (CP 1250)');
+ translate_lang_opt('', '', 'dan', 'Danish');
+ translate_lang_opt('', 'nl', 'dut', 'Dutch');
+ translate_lang_opt('!en', 'en', 'eng', 'English');
+ translate_lang_opt('', '', 'spe', 'European Spanish');
+ translate_lang_opt('', '', 'fin', 'Finnish');
+ translate_lang_opt('', 'fr', 'fre', 'French');
+ translate_lang_opt('', 'de', 'ger', 'German');
+ translate_lang_opt('', '', 'grk', 'Greek');
+ translate_lang_opt('', '', 'hun', 'Hungarian (CP 1250)');
+ translate_lang_opt('', '', 'ice', 'Icelandic');
+ translate_lang_opt('', 'it', 'ita', 'Italian');
+ translate_lang_opt('', '', 'jpn', 'Japanese (Shift JIS)');
+ translate_lang_opt('', '', 'spl', 'Latin American Spanish');
+ translate_lang_opt('', 'no*', 'nor', 'Norwegian');
+ translate_lang_opt('', 'pl', 'pol', 'Polish (ISO 8859-2)');
+ translate_lang_opt('', '', 'poe', 'Portuguese');
+ translate_lang_opt('', '', 'rom', 'Romanian (CP 1250)');
+ translate_lang_opt('', 'ru', 'rus', 'Russian (CP 1251)');
+ translate_lang_opt('', '', 'sel', 'Serbian (CP 1250)');
+ translate_lang_opt('', '', 'slo', 'Slovenian (CP 1250)');
+ translate_lang_opt('', 'es', 'spa', 'Spanish');
+ translate_lang_opt('', 'sv', 'swe', 'Swedish');
+ translate_lang_opt('', '', 'wel', 'Welsh');
+?></SELECT>
+ InterTran: <input type=submit value="Translate">
+<?php
+ translate_table_end();
+}
+
+function translate_form_gpltrans($message) {
+ translate_new_form('http://www.translator.cx/cgi-bin/gplTrans');
+?><select name="toenglish"><?php
+ translate_lang_opt('en', '!en', 'no', 'From English');
+ translate_lang_opt('!en', 'en', 'yes', 'To English');
+?></select><select name="language">
+<?php
+ translate_lang_opt('nl', 'nl', 'dutch_dict', 'Dutch');
+ translate_lang_opt('fr', 'fr', 'french_dict', 'French');
+ translate_lang_opt('de', 'de', 'german_dict', 'German');
+ translate_lang_opt('', '', 'indonesian_dict', 'Indonesian');
+ translate_lang_opt('it', 'it', 'italian_dict', 'Italian');
+ translate_lang_opt('', '', 'latin_dict', 'Latin');
+ translate_lang_opt('pt', 'pt', 'portuguese_dict', 'Portuguese');
+ translate_lang_opt('es', 'es', 'spanish_dict', 'Spanish');
+?></select>
+ <input type="hidden" name="text" value="<?php echo $message ?>">
+ GPLTrans: <input type="submit" value="Translate">
+<?php
+ translate_table_end();
+}
+
+function translate_form_dictionary($message) {
+ translate_new_form('http://translate.dictionary.com:8800/systran/cgi');
+?><INPUT TYPE=HIDDEN NAME=partner VALUE=LEXICO>
+ <input type=hidden name=urltext value="<?php echo $message ?>">
+<SELECT NAME="lp"><?php
+ translate_lang_opt('en', 'fr', 'en_fr', 'English to French');
+ translate_lang_opt('', 'de', 'en_de', 'English to German');
+ translate_lang_opt('', 'it', 'en_it', 'English to Italian');
+ translate_lang_opt('', 'pt*', 'en_pt', 'English to Portuguese');
+ translate_lang_opt('', 'es', 'en_sp', 'English to Spanish');
+ translate_lang_opt('fr', '', 'fr_en', 'French to English');
+ translate_lang_opt('', '', 'fr_ge', 'French to German');
+ translate_lang_opt('', '', 'ge_fr', 'German to French');
+ translate_lang_opt('de', '', 'de_en', 'German to English');
+ translate_lang_opt('it', '', 'it_en', 'Italian to English');
+ translate_lang_opt('pt*', '', 'pt_en', 'Portuguese to English');
+ translate_lang_opt('es', '', 'sp_en', 'Spanish to English');
+?></SELECT>
+ Dictionary.com: <INPUT TYPE="submit" VALUE="Translate">
+<?php
+ translate_table_end();
+}
+?>
<?php
- /**
- ** options.php
- **
- ** Copyright (c) 1999-2000 The SquirrelMail development team
- ** Licensed under the GNU GPL. For full terms see the file COPYING.
- **
- ** Displays the options page. Pulls from proper user preference files
- ** and config.php. Displays preferences as selected and other options.
- **
- ** $Id$
- **/
-
- require_once('../src/validate.php');
- require_once('../functions/display_messages.php');
- require_once('../functions/imap.php');
- require_once('../functions/array.php');
+ /**
+ * options.php
+ *
+ * Copyright (c) 1999-2001 The SquirrelMail Development Team
+ * Licensed under the GNU GPL. For full terms see the file COPYING.
+ *
+ * Displays the options page. Pulls from proper user preference files
+ * and config.php. Displays preferences as selected and other options.
+ *
+ * $Id$
+ */
+
+ require_once('../src/validate.php');
+ require_once('../functions/display_messages.php');
+ require_once('../functions/imap.php');
+ require_once('../functions/array.php');
- ereg ("(^.*/)[^/]+/[^/]+$", $PHP_SELF, $regs);
- $base_uri = $regs[1];
+ ereg ("(^.*/)[^/]+/[^/]+$", $PHP_SELF, $regs);
+ $base_uri = $regs[1];
- if (isset($language)) {
- setcookie('squirrelmail_language', $language, time()+2592000, $base_uri);
- $squirrelmail_language = $language;
- }
+ if (isset($language)) {
+ setcookie('squirrelmail_language', $language, time()+2592000, $base_uri);
+ $squirrelmail_language = $language;
+ }
- displayPageHeader($color, _("None"));
+ displayPageHeader($color, _("None"));
?>
<br>
<table bgcolor="<?php echo $color[0] ?>" width="95%" align="center" cellpadding="2" cellspacing="0" border="0">
<tr><td align="center">
-
- <b><?php echo _("Options") ?></b><br>
+ <b><?php echo _("Options") ?></b><br>
<table width="100%" border="0" cellpadding="5" cellspacing="0">
<tr><td bgcolor="<?php echo $color[4] ?>" align="center">
<?php
- if (isset($submit_personal)) {
- # Save personal information
- if (isset($full_name)) {
- setPref($data_dir, $username, 'full_name', $full_name);
- }
- if (isset($email_address)) {
- setPref($data_dir, $username, 'email_address', $email_address);
- }
- if (isset($reply_to)) {
- setPref($data_dir, $username, 'reply_to', $reply_to);
- }
- setPref($data_dir, $username, 'reply_citation_style', $new_reply_citation_style);
- setPref($data_dir, $username, 'reply_citation_start', $new_reply_citation_start);
- setPref($data_dir, $username, 'reply_citation_end', $new_reply_citation_end);
- if (! isset($usesignature))
- $usesignature = 0;
- setPref($data_dir, $username, 'use_signature', $usesignature);
- if (! isset($prefixsig)) {
- $prefixsig = 0;
- }
- setPref($data_dir, $username, 'prefix_sig', $prefixsig);
- if (isset($signature_edit)) {
- setSig($data_dir, $username, $signature_edit);
- }
+ if (isset($submit_personal)) {
+ /* Save personal information. */
+ if (isset($full_name)) {
+ setPref($data_dir, $username, 'full_name', $full_name);
+ }
+ if (isset($email_address)) {
+ setPref($data_dir, $username, 'email_address', $email_address);
+ }
+ if (isset($reply_to)) {
+ setPref($data_dir, $username, 'reply_to', $reply_to);
+ }
+ setPref($data_dir, $username, 'reply_citation_style', $new_reply_citation_style);
+ setPref($data_dir, $username, 'reply_citation_start', $new_reply_citation_start);
+ setPref($data_dir, $username, 'reply_citation_end', $new_reply_citation_end);
+ if (! isset($usesignature))
+ $usesignature = 0;
+ setPref($data_dir, $username, 'use_signature', $usesignature);
+ if (! isset($prefixsig)) {
+ $prefixsig = 0;
+ }
+ setPref($data_dir, $username, 'prefix_sig', $prefixsig);
+ if (isset($signature_edit)) {
+ setSig($data_dir, $username, $signature_edit);
+ }
- do_hook('options_personal_save');
+ do_hook('options_personal_save');
- echo '<br><b>'._("Successfully saved personal information!").'</b><br>';
- } else if (isset($submit_display)) {
- // Do checking to make sure $chosentheme is in the array
- $in_ary = false;
- for ($i=0; $i < count($theme); $i++)
- {
- if ($theme[$i]['PATH'] == $chosentheme)
- {
- $in_ary = true;
- break;
- }
- }
- if (! $in_ary)
- $chosentheme = '';
-
- # Save display preferences
- setPref($data_dir, $username, 'chosen_theme', $chosentheme);
- setPref($data_dir, $username, 'language', $language);
- setPref($data_dir, $username, 'use_javascript_addr_book', $javascript_abook);
- setPref($data_dir, $username, 'show_num', $shownum);
- setPref($data_dir, $username, 'wrap_at', $wrapat);
- setPref($data_dir, $username, 'editor_size', $editorsize);
- setPref($data_dir, $username, 'left_refresh', $leftrefresh);
- setPref($data_dir, $username, 'location_of_bar', $folder_new_location);
- setPref($data_dir, $username, 'location_of_buttons', $button_new_location);
- setPref($data_dir, $username, 'left_size', $leftsize);
-
- if (isset($altIndexColors) && $altIndexColors == 1) {
- setPref($data_dir, $username, 'alt_index_colors', 1);
- } else {
- setPref($data_dir, $username, 'alt_index_colors', 0);
- }
-
- setPref($data_dir, $username, 'show_html_default', ($showhtmldefault?1:0) );
-
- if (isset($includeselfreplyall)) {
- setPref($data_dir, $username, 'include_self_reply_all', 1);
- } else {
- removePref($data_dir, $username, 'include_self_reply_all');
- }
-
- if (isset($pageselectormax)) {
- setPref($data_dir, $username, 'page_selector_max', $pageselectormax);
- } else {
- removePref($data_dir, $username, 'page_selector_max', 0 );
- }
-
- if (isset($pageselector)) {
- removePref($data_dir, $username, 'page_selector');
- } else {
- setPref($data_dir, $username, 'page_selector', 1);
- }
-
- do_hook('options_display_save');
-
- echo '<br><b>'._("Successfully saved display preferences!").'</b><br>';
- echo '<a href="../src/webmail.php?right_frame=options.php" target=_top>' . _("Refresh Page") . '</a><br>';
- } else if (isset($submit_folder)) {
- # Save folder preferences
- if ($trash != 'none') {
- setPref($data_dir, $username, 'move_to_trash', true);
- setPref($data_dir, $username, 'trash_folder', $trash);
- } else {
- setPref($data_dir, $username, 'move_to_trash', '0');
- setPref($data_dir, $username, 'trash_folder', 'none');
- }
- if ($sent != 'none') {
- setPref($data_dir, $username, 'move_to_sent', true);
- setPref($data_dir, $username, 'sent_folder', $sent);
- } else {
- setPref($data_dir, $username, 'move_to_sent', '0');
- setPref($data_dir, $username, 'sent_folder', 'none');
- }
- if ($draft != 'none') {
- setPref($data_dir, $username, 'save_as_draft', true);
- setPref($data_dir, $username, 'draft_folder', $draft);
- } else {
- setPref($data_dir, $username, 'save_as_draft', '0');
- setPref($data_dir, $username, 'draft_folder', 'none');
- }
- if (isset($folderprefix)) {
- setPref($data_dir, $username, 'folder_prefix', $folderprefix);
- } else {
- setPref($data_dir, $username, 'folder_prefix', '');
- }
- setPref($data_dir, $username, 'unseen_notify', $unseennotify);
- setPref($data_dir, $username, 'unseen_type', $unseentype);
- if (isset($collapsefolders))
- setPref($data_dir, $username, 'collapse_folders', $collapsefolders);
- else
- removePref($data_dir, $username, 'collapse_folders');
- setPref($data_dir, $username, 'date_format', $dateformat);
- setPref($data_dir, $username, 'hour_format', $hourformat);
- do_hook('options_folders_save');
- echo '<br><b>'._("Successfully saved folder preferences!").'</b><br>';
- echo '<a href="../src/left_main.php" target=left>' . _("Refresh Folder List") . '</a><br>';
- } else {
- do_hook('options_save');
- }
+ echo '<br><b>'._("Successfully saved personal information!").'</b><br>';
+ } else if (isset($submit_display)) {
+ // Do checking to make sure $chosentheme is in the array
+ $in_ary = false;
+ for ($i=0; $i < count($theme); $i++) {
+ if ($theme[$i]['PATH'] == $chosentheme) {
+ $in_ary = true;
+ break;
+ }
+ }
+ if (! $in_ary) {
+ $chosentheme = '';
+ }
+ /* Save display preferences. */
+ setPref($data_dir, $username, 'chosen_theme', $chosentheme);
+ setPref($data_dir, $username, 'language', $language);
+ setPref($data_dir, $username, 'use_javascript_addr_book', $javascript_abook);
+ setPref($data_dir, $username, 'show_num', $shownum);
+ setPref($data_dir, $username, 'wrap_at', $wrapat);
+ setPref($data_dir, $username, 'editor_size', $editorsize);
+ setPref($data_dir, $username, 'left_refresh', $leftrefresh);
+ setPref($data_dir, $username, 'location_of_bar', $folder_new_location);
+ setPref($data_dir, $username, 'location_of_buttons', $button_new_location);
+ setPref($data_dir, $username, 'left_size', $leftsize);
+
+ if (isset($altIndexColors) && $altIndexColors == 1) {
+ setPref($data_dir, $username, 'alt_index_colors', 1);
+ } else {
+ setPref($data_dir, $username, 'alt_index_colors', 0);
+ }
+
+ setPref($data_dir, $username, 'show_html_default', ($showhtmldefault?1:0) );
+
+ if (isset($includeselfreplyall)) {
+ setPref($data_dir, $username, 'include_self_reply_all', 1);
+ } else {
+ removePref($data_dir, $username, 'include_self_reply_all');
+ }
+
+ if (isset($pageselectormax)) {
+ setPref($data_dir, $username, 'page_selector_max', $pageselectormax);
+ } else {
+ removePref($data_dir, $username, 'page_selector_max', 0 );
+ }
+
+ if (isset($pageselector)) {
+ removePref($data_dir, $username, 'page_selector');
+ } else {
+ setPref($data_dir, $username, 'page_selector', 1);
+ }
+
+ do_hook('options_display_save');
+
+ echo '<br><b>'._("Successfully saved display preferences!").'</b><br>';
+ echo '<a href="../src/webmail.php?right_frame=options.php" target=_top>' . _("Refresh Page") . '</a><br>';
+ } else if (isset($submit_folder)) {
+ /* Save folder preferences. */
+ if ($trash != 'none') {
+ setPref($data_dir, $username, 'move_to_trash', true);
+ setPref($data_dir, $username, 'trash_folder', $trash);
+ } else {
+ setPref($data_dir, $username, 'move_to_trash', '0');
+ setPref($data_dir, $username, 'trash_folder', 'none');
+ }
+ if ($sent != 'none') {
+ setPref($data_dir, $username, 'move_to_sent', true);
+ setPref($data_dir, $username, 'sent_folder', $sent);
+ } else {
+ setPref($data_dir, $username, 'move_to_sent', '0');
+ setPref($data_dir, $username, 'sent_folder', 'none');
+ }
+ if ($draft != 'none') {
+ setPref($data_dir, $username, 'save_as_draft', true);
+ setPref($data_dir, $username, 'draft_folder', $draft);
+ } else {
+ setPref($data_dir, $username, 'save_as_draft', '0');
+ setPref($data_dir, $username, 'draft_folder', 'none');
+ }
+ if (isset($folderprefix)) {
+ setPref($data_dir, $username, 'folder_prefix', $folderprefix);
+ } else {
+ setPref($data_dir, $username, 'folder_prefix', '');
+ }
+ setPref($data_dir, $username, 'unseen_notify', $unseennotify);
+ setPref($data_dir, $username, 'unseen_type', $unseentype);
+ if (isset($collapsefolders))
+ setPref($data_dir, $username, 'collapse_folders', $collapsefolders);
+ else
+ removePref($data_dir, $username, 'collapse_folders');
+ setPref($data_dir, $username, 'date_format', $dateformat);
+ setPref($data_dir, $username, 'hour_format', $hourformat);
+ do_hook('options_folders_save');
+ echo '<br><b>'._("Successfully saved folder preferences!").'</b><br>';
+ echo '<a href="../src/left_main.php" target=left>' . _("Refresh Folder List") . '</a><br>';
+ } else {
+ do_hook('options_save');
+ }
+
+ /****************************************/
+ /* Now build our array of option pages. */
+ /****************************************/
+
+ /* Build a section for Personal Options. */
+ $optionpages[] = array(
+ 'name' => _("Personal Information"),
+ 'url' => 'options_personal.php',
+ 'desc' => _("This contains personal information about yourself such as your name, your email address, etc."),
+ 'js' => false
+ );
+
+ /* Build a section for Display Options. */
+ $optionpages[] = array(
+ 'name' => _("Display Preferences"),
+ 'url' => 'options_display.php',
+ 'desc' => _("You can change the way that SquirrelMail looks and displays information to you, such as the colors, the language, and other settings."),
+ 'js' => false
+ );
+
+ /* Build a section for Message Highlighting Options. */
+ $optionpages[] = array(
+ 'name' =>_("Message Highlighting"),
+ 'url' => 'options_highlight.php',
+ 'desc' =>_("Based upon given criteria, incoming messages can have different background colors in the message list. This helps to easily distinguish who the messages are from, especially for mailing lists."),
+ 'js' => false
+ );
+
+ /* Build a section for Folder Options. */
+ $optionpages[] = array(
+ 'name' => _("Folder Preferences"),
+ 'url' => 'options_folder.php',
+ 'desc' => _("These settings change the way your folders are displayed and manipulated."),
+ 'js' => false
+ );
+
+ /* Build a section for Index Order Options. */
+ $optionpages[] = array(
+ 'name' => _("Index Order"),
+ 'url' => 'options_order.php',
+ 'desc' => _("The order of the message index can be rearanged and changed to contain the headers in any order you want."),
+ 'js' => false
+ );
+ /* Build a section for plugins wanting to register an optionpage. */
+ do_hook('options_register');
+
+ /*****************************************************/
+ /* Let's sort Javascript Option Pages to the bottom. */
+ /*****************************************************/
+ foreach ($optionpages as $optpage) {
+ if ($optpage['js']) {
+ $js_optionpages[] = $optpage;
+ } else {
+ $nojs_optionpages[] = $optpage;
+ }
+ }
+ $optionpages = array_merge($nojs_optionpages, $js_optionpages);
+
+ /********************************************/
+ /* Now, print out each option page section. */
+ /********************************************/
+ $first_optpage = false;
+ foreach ($optionpages as $next_optpage) {
+ if ($first_optpage == false) {
+ $first_optpage = $next_optpage;
+ } else {
+ print_optionpages_row($first_optpage, $next_optpage);
+ $first_optpage = false;
+ }
+ }
+
+ if ($first_optpage != false) {
+ print_optionpages_row($first_optpage);
+ }
+
+ do_hook('options_link_and_description');
+
?>
+ </td></tr>
+ </table>
+
+</td></tr>
+</table>
+
+</body></html>
+
+<?php
+
+ /*******************************************************************/
+ /* Please be warned. The code below this point sucks. This is just */
+ /* my first implementation to make the option rows work for both */
+ /* Javascript and non-Javascript option chunks. */
+ /* */
+ /* Please, someone make these better for me. All three functions */
+ /* below REALLY do close to the same thing. */
+ /* */
+ /* This code would be GREATLY improved by a templating system. */
+ /* Don't try to implement that now, however. That will come later. */
+ /*******************************************************************/
+
+ /*******************************************************************/
+ /* Actually, now that I think about it, don't do anything with */
+ /* this code yet. There is ACTUALLY supposed to be a difference */
+ /* between the three functions that write the option rows. I just */
+ /* have not yet gotten to integrating that yet. */
+ /*******************************************************************/
+
+ /**
+ * This function prints out an option page row. All it actually
+ * does is call the three functions below.
+ */
+ function print_optionpages_row($leftopt, $rightopt = false) {
+ if ($rightopt == false) {
+ if ($leftopt['js']) {
+ print_optionpages_row_fulljs($leftopt);
+ } else {
+ print_optionpages_row_nojs($leftopt);
+ }
+ } else {
+ if ($leftopt['js']) {
+ if ($rightopt['js']) {
+ print_optionpages_row_fulljs($leftopt, $rightopt);
+ } else {
+ print_optionpages_row_partjs($leftopt, $rightopt);
+ }
+ } else {
+ print_optionpages_row_nojs($leftopt, $rightopt);
+ }
+ }
+ }
-<table bgcolor="<?php echo $color[4] ?>" width="100%" cellpadding="5" cellspacing="0" border="0">
-<tr>
- <td width="50%" valign="top">
+ /**
+ * This function prints out an option page row: in which the left
+ * Left: options for functionality that do not require javascript
+ * Right: options for functionality that do not require javascript
+ */
+ function print_optionpages_row_nojs($leftopt, $rightopt = false) {
+ global $color;
+?>
+<table bgcolor="<?php echo $color[4] ?>" width="100%" cellpadding="0" cellspacing="5" border="0">
+ <tr><td valign=top>
<table width="100%" cellpadding="3" cellspacing="0" border="0">
<tr>
- <td bgcolor="<?php echo $color[9] ?>">
- <a href="options_personal.php"><?php echo _("Personal Information"); ?></a>
+ <td valign="top" bgcolor="<?php echo $color[9] ?>" width="50%">
+ <a href="<?php echo $leftopt['url'] ?>"><?php echo $leftopt['name'] ?></a>
+ </td>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php if ($rightopt != false) { ?>
+ <td valign="top" bgcolor="<?php echo $color[9] ?>" width="50%">
+ <a href="<?php echo $rightopt['url'] ?>"><?php echo $rightopt['name'] ?></a>
</td>
+<?php } else { ?>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>" width="50%"> </td>
+<?php } ?>
</tr>
<tr>
- <td bgcolor="<?php echo $color[0] ?>">
- <?php echo _("This contains personal information about yourself such as your name, your email address, etc.") ?>
+ <td valign="top" bgcolor="<?php echo $color[0] ?>">
+ <?php echo $leftopt['desc'] ?>
</td>
- </tr>
- </table><br>
- <table width="100%" cellpadding="3" cellspacing="0" border="0">
- <tr>
- <td bgcolor="<?php echo $color[9] ?>">
- <a href="options_highlight.php"><?php echo _("Message Highlighting"); ?></a>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php if ($rightopt != false) { ?>
+ <td valign="top" bgcolor="<?php echo $color[0] ?>">
+ <?php echo $rightopt['desc'] ?>
</td>
+<?php } else { ?>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php } ?>
</tr>
- <tr>
- <td bgcolor="<?php echo $color[0] ?>">
- <?php echo _("Based upon given criteria, incoming messages can have different background colors in the message list. This helps to easily distinguish who the messages are from, especially for mailing lists.") ?>
- </td>
- </tr>
- </table><br>
+ </table>
+ </td></tr>
+</table>
+<?php
+ }
+
+ /**
+ * This function prints out an option page row: in which the left
+ * Left: options for functionality that does not require javascript
+ * Right: options for functionality that are javascript only
+ */
+ function print_optionpages_row_partjs($leftopt, $rightopt = false) {
+ global $color;
+?>
+<table bgcolor="<?php echo $color[4] ?>" width="100%" cellpadding="0" cellspacing="5" border="0">
+ <tr><td valign=top>
<table width="100%" cellpadding="3" cellspacing="0" border="0">
<tr>
- <td bgcolor="<?php echo $color[9] ?>">
- <a href="options_order.php"><?php echo _("Index Order"); ?></a>
+ <td valign="top" bgcolor="<?php echo $color[9] ?>" width="50%">
+ <a href="<?php echo $leftopt['url'] ?>"><?php echo $leftopt['name'] ?></a>
+ </td>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php if ($rightopt != false) { ?>
+ <td valign="top" bgcolor="<?php echo $color[9] ?>" width="50%">
+ <a href="<?php echo $rightopt['url'] ?>"><?php echo $rightopt['name'] ?></a>
</td>
+<?php } else { ?>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>" width="50%"> </td>
+<?php } ?>
</tr>
<tr>
- <td bgcolor="<?php echo $color[0] ?>">
- <?php echo _("The order of the message index can be rearanged and changed to contain the headers in any order you want.") ?>
+ <td valign="top" bgcolor="<?php echo $color[0] ?>">
+ <?php echo $leftopt['desc'] ?>
</td>
- </tr>
- </table><br>
- </td>
- <td valign="top" width="50%">
- <table width="100%" cellpadding="3" cellspacing="0" border="0">
- <tr>
- <td bgcolor="<?php echo $color[9] ?>">
- <a href="options_display.php"><?php echo _("Display Preferences"); ?></a>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php if ($rightopt != false) { ?>
+ <td valign="top" bgcolor="<?php echo $color[0] ?>">
+ <?php echo $rightopt['desc'] ?>
</td>
+<?php } else { ?>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php } ?>
</tr>
- <tr>
- <td bgcolor="<?php echo $color[0] ?>">
- <?php echo _("You can change the way that SquirrelMail looks and displays information to you, such as the colors, the language, and other settings.") ?>
- </td>
- </tr>
- </table><br>
+ </table>
+ </td></tr>
+</table>
+<?php
+ }
+
+ /**
+ * This function prints out an option page row: in which the left
+ * Left: options for functionality that are javascript only
+ * Right: options for functionality that are javascript only
+ */
+ function print_optionpages_row_fulljs($leftopt, $rightopt = false) {
+ global $color;
+?>
+<table bgcolor="<?php echo $color[4] ?>" width="100%" cellpadding="0" cellspacing="5" border="0">
+ <tr><td valign=top>
<table width="100%" cellpadding="3" cellspacing="0" border="0">
<tr>
- <td bgcolor="<?php echo $color[9] ?>">
- <a href="options_folder.php"><?php echo _("Folder Preferences"); ?></a>
+ <td valign="top" bgcolor="<?php echo $color[9] ?>" width="50%">
+ <a href="<?php echo $leftopt['url'] ?>"><?php echo $leftopt['name'] ?></a>
</td>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php if ($rightopt != false) { ?>
+ <td valign="top" bgcolor="<?php echo $color[9] ?>" width="50%">
+ <a href="<?php echo $rightopt['url'] ?>"><?php echo $rightopt['name'] ?></a>
+ </td>
+<?php } else { ?>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>" width="50%"> </td>
+<?php } ?>
</tr>
<tr>
- <td bgcolor="<?php echo $color[0] ?>">
- <?php echo _("These settings change the way your folders are displayed and manipulated.") ?>
+ <td valign="top" bgcolor="<?php echo $color[0] ?>">
+ <?php echo $leftopt['desc'] ?>
</td>
- </tr>
- </table><br>
- </td>
-</tr>
-</table>
-
- <?php do_hook('options_link_and_description'); ?>
-
-
- </td></tr>
- </table>
-
-</td></tr>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php if ($rightopt != false) { ?>
+ <td valign="top" bgcolor="<?php echo $color[0] ?>">
+ <?php echo $rightopt['desc'] ?>
+ </td>
+<?php } else { ?>
+ <td valign="top" bgcolor="<?php echo $color[4] ?>"> </td>
+<?php } ?>
+ </tr>
+ </table>
+ </td></tr>
</table>
+<?php
+ }
-</body></html>
+?>