#! @im_path_perl@ ################################################################ ### ### imsort ### ### Author: Internet Message Group ### Created: Jul 2, 1997 ### Revised: Feb 28, 2000 ### BEGIN { @im_my_siteperl@ @im_src_siteperl@ }; my $VERSION = "imsort version 20000228(IM140)"; $Prog = 'imsort'; ## ## Require packages ## use IM::Config; use IM::Folder; use IM::File; use IM::Util; use integer; use strict; use vars qw($Prog $EXPLANATION @OptConfig $opt_field $opt_mode $opt_noharm $opt_src $opt_verbose $opt_debug $opt_help); ## ## Environments ## $EXPLANATION = " $Prog :: Internet Message Sort $VERSION Usage: $Prog [options] +folder [msgs...] "; @OptConfig = ( 'src;F;;' => "Set source folder.", 'field;s;date;'=> "Sort by the specified field.", 'mode;s;date;' => "Set sort mode to date, num, text or ml.", 'noharm;b;;' => "Display the commands but do not actually execute them.", 'verbose;b;;' => 'With verbose messages.', 'debug;d;;' => "With debug message.", 'help;b;;' => "Show this message.", ); ## ## Profile and option processing ## init_opt(\@OptConfig); read_cfg(); read_opt(\@ARGV); # help? help($EXPLANATION) && exit $EXIT_SUCCESS if $opt_help; debug_option($opt_debug) if $opt_debug; ## ## Main ## my @msgs = @ARGV; @msgs = ('all') if (!@ARGV); my $msgs = \@msgs; $opt_src || im_die "no folder specified.\n"; @msgs || im_die "no message specified.\n"; $opt_field || im_die "no field specified.\n"; $opt_mode =~ /^(date|num|text|ml)$/ || im_die "Wrong mode $opt_mode.\n"; # # Set date relative magic values. # my @TBL = (0, 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275); my %ZONE = ('PST', -8, 'PDT', -7, 'MST', -7, 'MDT', -6, 'CST', -6, 'CDT', -5, 'EST', -5, 'EDT', -4, 'AST', -4, 'NST', -3, 'UT' , +0, 'GMT', +0, 'BST', +1, 'MET', +1, 'EET', +2, 'JST', +9,); my %MONTH = ('Jan', 1, 'Feb', 2, 'Mar', 3, 'Apr', 4, 'May', 5, 'Jun', 6, 'Jul', 7, 'Aug', 8, 'Sep', 9, 'Oct', 10, 'Nov', 11, 'Dec', 12); sub rxp_or { join('|', @_); } my $m_rxp = rxp_or(keys(%MONTH)); my $z_rxp = rxp_or(keys(%ZONE), '[-+]\d{4}'); # # do it. # imsort($opt_src, $msgs, $opt_mode, $opt_field); exit $EXIT_SUCCESS; ################################################## ## ## Work horse ## sub imsort ($$$$) { my ($src, $msgs, $mode, $field) = @_; my ($i, $path, $from, $to, $tmp, @msg_all, @msg_paths, @sorted_index); my @param = (); my $HOLE_PATH = get_impath($src, 'new'); @msg_all = get_impath($src, @{$msgs}); foreach $path (@msg_all) { if (-f $path) { push(@msg_paths, $path); push(@param, get_field_value($path, $field, $mode)); } } if (($mode eq 'text') || ($mode eq 'ml')) { @sorted_index = sort { $param[$a] cmp $param[$b] } 0 .. $#msg_paths; } else { @sorted_index = sort { $param[$a] <=> $param[$b] } 0 .. $#msg_paths; } $tmp = $#msg_paths + 1; for $i (0 .. $#msg_paths) { next if $i == $sorted_index[$i] or $sorted_index[$i] < 0; $msg_paths[$tmp] = $HOLE_PATH; $sorted_index[$tmp] = $i; $to = $tmp; do { $from = $sorted_index[$to]; if ($sorted_index[$from] < 0) { $from = $tmp; } $sorted_index[$to] = -1; im_rename($msg_paths[$from], $msg_paths[$to]) || die; } while ($to = $from) != $tmp; $#msg_paths = $#sorted_index = $tmp - 1; } touch_folder($src) unless $opt_noharm; } sub get_field_value ($$$) { my ($path, $field, $smode) = @_; local $_; local $/ = ''; my ($ml, $num); if (im_open(\*MSG, "< $path")){ ($_ = ) =~ s/\n\s+/ /g; close(MSG); } else { im_die("Can't open $path. (Nothing was done.)\n"); } ($_) = /^$field:\s+([^\n]*)/imo; if (lc($field) eq 'subject') { if ($smode eq 'ml') { if(s/^[\[\(]([^\]\)]*)[\]\)]\s*//i){ $1 =~ /^(.*)[:,\s](.*)$/; $ml=$1; $num=$2; s/^(re:\s*)(.*)$/$2$1/i; $_ = $ml . $_ . $num; } } else { s/^(re:\s*)(.*)$/$2$1/i; } } if ($smode eq 'num') { m/(\d+)\D*$/; $_ = $1; } if ($smode eq 'date'){ if (/(\d+)\s+($m_rxp)\s+(\d+)\s+(\d+):(\d+)(:(\d+))?\s*($z_rxp)?/io){ ## Y2K: conform to drums if ($3 < 50) { return sec_from_epoc($3 + 2000, $MONTH{$2}, $1, $4, $5, $7+0, $8); } elsif ($3 < 100) { return sec_from_epoc($3 + 1900, $MONTH{$2}, $1, $4, $5, $7+0, $8); } else { return sec_from_epoc($3, $MONTH{$2}, $1, $4, $5, $7+0, $8); } } return (stat($path))[9]; } return $_; } sub sec_from_epoc ($$$$$$$) { my ($y, $m, $d, $hh, $mm, $ss, $tz) = @_; $tz = ($ZONE{$tz} * 3600) || (int($tz/100)*3600 + ($tz%100)*60); $y-- if ($m < 3); ($y * 365 + int($y/4) - int($y/100) + int($y/400) + $TBL[$m] + $d - 719469) * 86400 + $hh * 3600 + $mm * 60 + $ss - $tz; } ### Copyright (C) 1997, 1998, 1999 IM developing team ### All rights reserved. ### ### Redistribution and use in source and binary forms, with or without ### modification, are permitted provided that the following conditions ### are met: ### ### 1. Redistributions of source code must retain the above copyright ### notice, this list of conditions and the following disclaimer. ### 2. Redistributions in binary form must reproduce the above copyright ### notice, this list of conditions and the following disclaimer in the ### documentation and/or other materials provided with the distribution. ### 3. Neither the name of the team nor the names of its contributors ### may be used to endorse or promote products derived from this software ### without specific prior written permission. ### ### THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND ### ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ### IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ### PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE ### LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ### CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ### SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ### BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ### WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ### OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ### IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ### Local Variables: ### mode: perl ### End: