Changeset 5269
- Timestamp:
- 10/15/09 19:28:59 (2 years ago)
- Location:
- branches/Release01x00/MailerContrib
- Files:
-
- 13 edited
-
data/System/MailerContrib.txt (modified) (3 diffs)
-
lib/Foswiki/Contrib/MailerContrib.pm (modified) (25 diffs)
-
lib/Foswiki/Contrib/MailerContrib/Change.pm (modified) (8 diffs)
-
lib/Foswiki/Contrib/MailerContrib/CompatibilityHacks.pm (modified) (3 diffs)
-
lib/Foswiki/Contrib/MailerContrib/Config.spec (modified) (2 diffs)
-
lib/Foswiki/Contrib/MailerContrib/Constants.pm (modified) (2 diffs)
-
lib/Foswiki/Contrib/MailerContrib/Subscriber.pm (modified) (9 diffs)
-
lib/Foswiki/Contrib/MailerContrib/Subscription.pm (modified) (7 diffs)
-
lib/Foswiki/Contrib/MailerContrib/TopicContext.pm (modified) (1 diff)
-
lib/Foswiki/Contrib/MailerContrib/UpData.pm (modified) (2 diffs)
-
lib/Foswiki/Contrib/MailerContrib/WebNotify.pm (modified) (17 diffs)
-
lib/Foswiki/Contrib/MailerContrib/build.pl (modified) (3 diffs)
-
tools/mailnotify (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/Release01x00/MailerContrib/data/System/MailerContrib.txt
r5033 r5269 136 136 137 137 <!-- 138 * Set SHORTDESCRIPTION = Supports e-mail notification of changes.138 * Set SHORTDESCRIPTION = %$SHORTDESCRIPTION% 139 139 --> 140 ---++ Developer Notes140 ---+++ Tailoring the email format 141 141 The changes mails sent to subscribers are based on a Foswiki template called =mailnotify=. This template must contain the following definitions. 142 142 | =HTML:before= | Section of a HTML mail before the changes | … … 147 147 | =PLAIN:after= | Section of a plain text mail after the changes | 148 148 | =MailNotifyBody= | All the above are embedded in this. %<nop>HTML_TEXT% expands to the HTML obtained by expanding the =HTML:*= templates, and %<nop>PLAIN_TEXT% from the =PLAIN:*= templates. | 149 The default template sends multipart mails containing both HTML and plaintext versions. You can easily provide a custom version of this template using a local skin. 149 The default template sends multipart mails containing both HTML and plaintext versions. 150 151 To tailor the email format please avoid editing the distributed mailnotify.tmpl file as you will regret when it later gets overwritten when you upgrade Foswiki. Instead you should either use a skin setting to choose the template file or use web part of the [[%SYSTEMWEB%.SkinTemplates#FindingTemplates][template search path rules]]. 152 153 It is recommended to use the skin method as it is easier to control, and requires less hacking around. Especially if you need to use the same tailoring for many or all webs. 154 155 * Simple global tailoring used in all webs using your normal default skin 156 * Make a copy of =templates/mailnotify.tmpl= called =templates/mailnotify.skiname.tmpl=. For example =templates/mailnotify.pattern.tmpl= and modify this copy to your need. If you use the !NatSkin simply use =templates/mailnotify.nat.tmpl= instead 157 158 * Using a dummy skin name globally 159 * In !%USERSWEB%.SitePreferences define a setting =* Set SKIN = notifyskin,pattern= where the notifyskin is the dummy skin name and the pattern in this example is the real skin. 160 * Create a =templates/mailnotify.notifyskin.tmpl= with your tailorings 161 162 * Using a dummy skin name per web 163 * In each web where you want a special mailnotify template add the setting =* Set SKIN = notifywebname,pattern= where the notifywebname is the dummy skin name for this web and the pattern in this example is the real skin. 164 * For each web where you need a special mailnotify template create a =templates/mailnotify.notifywebname.tmpl= with your tailorings 165 166 * Using the web path in the templates directory 167 * For each web where you want a special mailnotify create subdirectories in =templates= with the same names as the webs and place a =templates/mailnotify.tmpl= in these subdirectories with your tailorings 150 168 151 169 Newsletters are sent after formatting using the standard =view= template, using whatever skin is selected in the topic being mailed. 170 171 ---+++ Using a topic defined email template 172 173 If you want to use a topic to define the notify email format this is possible with a small workaround. Before you go ahead and do this you need to consider the security implication. Making the email format available to any user from a browser means that spammers can abuse this to create messages where they can spoof the from address. Only use this method if your Foswiki installation is safely behind a firewall and your users can be trusted. 174 175 The method can best be shown with an example. In the following we... 176 177 * Define a custom mailnotify template based on a skin setting in !WebNotify 178 * Allow the users to define the mail format in a topic called !WebNotifyCustomTemplate 179 180 Here are the steps 181 182 First we create a file =templates/mailnotify.customnotify.tmpl= which only contains these two lines 183 184 <verbatim> 185 %TMPL:INCLUDE{"mailnotify"}% 186 %TMPL:INCLUDE{"WebNotifyCustom"}% 187 </verbatim> 188 189 In the webs where you want the topic defined mail format we add the setting =* Set SKIN = customnotify,pattern= (assuming pattern is the normal skin) 190 191 And we create a topic in the web called !WebNotifyCustomTemplate which contains the entire mailnotify template you want to use. Simply copy the content from =templates/mailnotify.tmpl= to this template and do the tailoring. 152 192 153 193 ---+++ Contrib Info … … 160 200 161 201 | Author: | [[http://c-dot.co.uk][Crawford Currie]] | 162 | Copyright ©: | 2004, Wind River Systems; 2008, http://WikiRing.com |202 | Copyright ©: | 2004, Wind River Systems; 2008, http://WikiRing.com; 2009 Foswiki Contributors | 163 203 | License: | GPL | 164 204 | Version: | %$VERSION% | 165 205 | Release: | %$RELEASE% | 166 206 | Change History: | | 207 | 15 Oct 2009 | Foswikitask:Item2260. Make the feature that allows defining the email template based in either skin or web path. And improve the documentation so people can learn how to tailor the emails that the WebNotify feature sends. <br /> Foswikitask:Item1603: use quotes to protect topic names with odd characters in them | 167 208 | 20 Sep 2009 | Small documentation update for Foswiki 1.0.7 release (RELEASE and adding parent) | 168 209 | 23 Apr 2009 | Foswikitask:Item1501: Minor bug in logfile output fixed | -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib.pm
r5033 r5269 15 15 use strict; 16 16 17 use URI ;17 use URI (); 18 18 use CGI qw(-any); 19 19 20 require Foswiki; 21 require Foswiki::Plugins; 22 require Foswiki::Time; 23 require Foswiki::Func; 24 require Foswiki::Contrib::MailerContrib::WebNotify; 25 require Foswiki::Contrib::MailerContrib::Change; 26 require Foswiki::Contrib::MailerContrib::UpData; 27 28 use vars qw ( $VERSION $RELEASE $verbose ); 29 30 $VERSION = '$Rev$'; 31 $RELEASE = '20 Sep 2009'; 20 use Foswiki (); 21 use Foswiki::Plugins (); 22 use Foswiki::Time (); 23 use Foswiki::Func (); 24 use Foswiki::Contrib::MailerContrib::WebNotify (); 25 use Foswiki::Contrib::MailerContrib::Change (); 26 use Foswiki::Contrib::MailerContrib::UpData (); 27 28 our $VERSION = '$Rev$'; 29 our $RELEASE = '15 Oct 2009'; 30 our $SHORTDESCRIPTION = 'Supports e-mail notification of changes'; 31 32 our $verbose = 0; 32 33 33 34 # PROTECTED STATIC ensure the contrib is initernally initialised … … 54 55 55 56 sub mailNotify { 56 my ( $webs, $twiki, $noisy, $exwebs ) = @_;57 my ( $webs, $twiki, $noisy, $exwebs ) = @_; 57 58 58 59 $verbose = $noisy; 59 60 60 61 my $webstr; 61 if ( defined( $webs )) {62 if ( defined($webs) ) { 62 63 $webstr = join( '|', @$webs ); 63 64 } 64 $webstr = '*' unless ( $webstr);65 $webstr = '*' unless ($webstr); 65 66 $webstr =~ s/\*/\.\*/g; 66 67 67 68 my $exwebstr = ''; 68 if ( defined( $exwebs )) {69 if ( defined($exwebs) ) { 69 70 $exwebstr = join( '|', @$exwebs ); 70 71 } 71 72 $exwebstr =~ s/\*/\.\*/g; 72 73 73 if ( !defined $twiki) {74 if ( !defined $twiki ) { 74 75 $twiki = new Foswiki(); 75 76 } … … 87 88 88 89 my $report = ''; 89 foreach my $web ( Foswiki::Func::getListOfWebs( 'user ') ) {90 if ( $web =~ /^($webstr)$/ && $web !~ /^($exwebstr)$/ ) {91 $report .= _processWeb( $twiki, $web );92 }90 foreach my $web ( Foswiki::Func::getListOfWebs('user ') ) { 91 if ( $web =~ /^($webstr)$/ && $web !~ /^($exwebstr)$/ ) { 92 $report .= _processWeb( $twiki, $web ); 93 } 93 94 } 94 95 … … 103 104 104 105 sub changeSubscription { 105 my ($defaultWeb, $who, $topicList, $unsubscribe) = @_; 106 107 #we can get away with a normalise on a list of topics, so long as the list starts with a topic 108 my ($web, $t) = Foswiki::Func::normalizeWebTopicName($defaultWeb, $topicList); 106 my ( $defaultWeb, $who, $topicList, $unsubscribe ) = @_; 107 108 #we can get away with a normalise on a list of topics, so long as the list starts with a topic 109 my ( $web, $t ) = 110 Foswiki::Func::normalizeWebTopicName( $defaultWeb, $topicList ); 111 109 112 #TODO: this limits us to subscribing to one web. 110 113 my $wn = new Foswiki::Contrib::MailerContrib::WebNotify( … … 115 118 } 116 119 117 118 120 =pod 119 121 ---+++ isSubscribedTo ($web, $who, $topicList) -> boolean … … 126 128 127 129 sub isSubscribedTo { 128 my ( $defaultWeb, $who, $topicList) = @_;129 130 my ( $defaultWeb, $who, $topicList ) = @_; 131 130 132 my $subscribed = { 131 currentWeb=>$defaultWeb, 132 topicSub=>\&_isSubscribedToTopic 133 }; 134 135 my $ret = Foswiki::Contrib::MailerContrib::parsePageList($subscribed, $who, $topicList); 136 137 return (!defined($subscribed->{not_subscribed}) || 138 (0 == scalar($subscribed->{not_subscribed})) ); 139 } 133 currentWeb => $defaultWeb, 134 topicSub => \&_isSubscribedToTopic 135 }; 136 137 my $ret = parsePageList( $subscribed, $who, $topicList ); 138 139 return ( !defined( $subscribed->{not_subscribed} ) 140 || ( 0 == scalar( $subscribed->{not_subscribed} ) ) ); 141 } 142 140 143 sub _isSubscribedToTopic { 141 144 my ( $subscribed, $who, $unsubscribe, $topic, $options, $childDepth ) = @_; 142 145 143 146 require Foswiki::Contrib::MailerContrib::WebNotify; 144 my ($sweb, $stopic) = Foswiki::Func::normalizeWebTopicName($subscribed->{currentWeb}, $topic); 145 146 #TODO: extract this code so we only create $wn objects for each web once.. 147 my $wn = new Foswiki::Contrib::MailerContrib::WebNotify( $Foswiki::Plugins::SESSION, $sweb, $Foswiki::cfg{NotifyTopicName} ); 147 my ( $sweb, $stopic ) = 148 Foswiki::Func::normalizeWebTopicName( $subscribed->{currentWeb}, $topic ); 149 150 #TODO: extract this code so we only create $wn objects for each web once.. 151 my $wn = new Foswiki::Contrib::MailerContrib::WebNotify( 152 $Foswiki::Plugins::SESSION, $sweb, $Foswiki::cfg{NotifyTopicName} ); 148 153 my $subscriber = $wn->getSubscriber($who); 149 150 my $db = new Foswiki::Contrib::MailerContrib::UpData( $Foswiki::Plugins::SESSION, $sweb ); 154 155 my $db = 156 new Foswiki::Contrib::MailerContrib::UpData( $Foswiki::Plugins::SESSION, 157 $sweb ); 158 151 159 #TODO: need to check $childDepth topics too (somehow) 152 if ( $subscriber->isSubscribedTo($stopic, $db) && 153 (!$subscriber->isUnsubscribedFrom($stopic, $db))) { 154 push(@{$subscribed->{subscribed}}, $stopic); 155 } else { 156 push(@{$subscribed->{not_subscribed}}, $stopic); 157 } 158 return ''; 160 if ( $subscriber->isSubscribedTo( $stopic, $db ) 161 && ( !$subscriber->isUnsubscribedFrom( $stopic, $db ) ) ) 162 { 163 push( @{ $subscribed->{subscribed} }, $stopic ); 164 } 165 else { 166 push( @{ $subscribed->{not_subscribed} }, $stopic ); 167 } 159 168 } 160 169 161 170 =pod 171 162 172 ---+++ sub parsePageList ( $object, $who, $spec, $unsubscribe ) => unprocessable remainder of $spec line 163 calls the $topicSub (ref to sub)once per identified topic entry.164 * $object ( is a hashref) can be used to set status' and its definition is dependent on $topicSub165 * $object->{topicSub} _must_ be a sub ref and _must_ return an empty string166 * $unsubscribe can be set to '-' to force an unsubscription (used by SubscribePlugin)167 168 $object is a functor.173 Calls the $object->{topicSub} once per identified topic entry. 174 * $object (a hashref) may be a hashref that has the field, =topicSub=, 175 which _may_ be a sub ref as follows: 176 =&topicSub($object, $who, $unsubscribe, $webTopic, $options, $childDepth)= 177 * =$unsubscribe= can be set to '-' to force an unsubscription 178 (used by SubscribePlugin) 169 179 170 180 =cut … … 172 182 sub parsePageList { 173 183 my ( $object, $who, $spec, $unsubscribe ) = @_; 184 174 185 #ASSERT(defined($object->{topicSub})); 175 176 return $spec if ( !defined($object->{topicSub}));177 186 187 return $spec if ( !$object || !defined( $object->{topicSub} ) ); 188 178 189 $spec =~ s/,/ /g; 179 #TODO: refine the $2 regex to be proper web.topic/topic/* style.. 180 while ($spec =~ s/^\s*([+-])?\s*([\w.\*]+)([!?]?)\s*(?:\((\d+)\))?/&{$object->{topicSub}}($object, $who, $unsubscribe||$1, $2, $3, $4)/e) { 181 #go 190 191 # $1: + or -, optional 192 # $2: the wildcarded topic specifier (may be quoted) 193 # TODO: refine the $2 regex to be proper web.topic/topic/* style.. 194 # $3: options 195 # $4: child depth 196 while ( $spec =~ 197 s/^\s*([+-])?\s*([*\w.]+|'.*?'|".*?")([!?]?)\s*(?:\((\d+)\))?//) { 198 my ( $us, $webTopic, $options, $childDepth ) = ( 199 $unsubscribe||$1||'+', $2, $3, $4||0 ); 200 $webTopic =~ s/^(['"])(.*)\1$/$2/; # remove quotes 201 &{$object->{topicSub}}( 202 $object, $who, $us, $webTopic, $options, $childDepth); 203 #go 182 204 } 183 205 return $spec; 184 206 } 185 186 207 187 208 # PRIVATE: Read the webnotify, and notify changes 188 209 sub _processWeb { 189 my( $twiki, $web) = @_; 190 191 if( ! Foswiki::Func::webExists( $web ) ) { 192 # print STDERR "**** ERROR mailnotifier cannot find web $web\n"; 210 my ( $twiki, $web ) = @_; 211 212 if ( !Foswiki::Func::webExists($web) ) { 213 214 # print STDERR "**** ERROR mailnotifier cannot find web $web\n"; 193 215 return ''; 194 216 } … … 199 221 200 222 # Read the webnotify and load subscriptions 201 my $wn = new Foswiki::Contrib::MailerContrib::WebNotify( 202 $twiki, $web, $Foswiki::cfg{NotifyTopicName} ); 223 my $wn = 224 new Foswiki::Contrib::MailerContrib::WebNotify( $twiki, $web, 225 $Foswiki::cfg{NotifyTopicName} ); 203 226 if ( $wn->isEmpty() ) { 204 227 print "\t$web has no subscribers\n" if $verbose; 205 } else { 228 } 229 else { 230 206 231 # create a DB object for parent pointers 207 232 print $wn->stringify(1) if $verbose; … … 223 248 224 249 my $timeOfLastNotify = 0; 225 if ( open(F, "<$notmeta")) {250 if ( open( F, '<', $notmeta ) ) { 226 251 local $/ = undef; 227 252 $timeOfLastNotify = <F>; … … 229 254 } 230 255 231 if ( $verbose) {232 print "\tLast notification was at " .233 Foswiki::Time::formatTime( $timeOfLastNotify, 'iso' ). "\n";256 if ($verbose) { 257 print "\tLast notification was at " 258 . Foswiki::Time::formatTime( $timeOfLastNotify, 'iso' ) . "\n"; 234 259 } 235 260 … … 252 277 my %allSet; 253 278 254 if ( !defined( &Foswiki::Func::eachChangeSince )) {279 if ( !defined(&Foswiki::Func::eachChangeSince) ) { 255 280 require Foswiki::Contrib::MailerContrib::CompatibilityHacks; 256 281 } … … 258 283 # + 1 because the 'since' check is >= 259 284 my $it = Foswiki::Func::eachChangeSince( $web, $timeOfLastNotify + 1 ); 260 while ( $it->hasNext() ) {285 while ( $it->hasNext() ) { 261 286 my $change = $it->next(); 262 287 next if $change->{more} && $change->{more} =~ /minor$/; … … 264 289 next unless Foswiki::Func::topicExists( $web, $change->{topic} ); 265 290 266 $timeOfLastChange = $change->{time} unless( $timeOfLastChange ); 267 268 print "\tChange to $change->{topic} at ". 269 Foswiki::Time::formatTime( $change->{time}, 'iso' ). 270 ". New revision is $change->{revision}\n" if ( $verbose ); 291 $timeOfLastChange = $change->{time} unless ($timeOfLastChange); 292 293 print "\tChange to $change->{topic} at " 294 . Foswiki::Time::formatTime( $change->{time}, 'iso' ) 295 . ". New revision is $change->{revision}\n" 296 if ($verbose); 271 297 272 298 # Formulate a change record, irrespective of 273 299 # whether any subscriber is interested 274 $change = new Foswiki::Contrib::MailerContrib::Change( 275 $twiki, $web, $change->{topic}, $change->{user}, 276 $change->{time}, $change->{revision} ); 300 $change = 301 new Foswiki::Contrib::MailerContrib::Change( $twiki, $web, 302 $change->{topic}, $change->{user}, $change->{time}, 303 $change->{revision} ); 277 304 278 305 # Now, find subscribers to this change and extend the change set 279 $notify->processChange( 280 $change, $db, \%changeset, \%seenset, \%allSet ); 281 } 306 $notify->processChange( $change, $db, \%changeset, \%seenset, 307 \%allSet ); 308 } 309 282 310 # For each topic, see if there's a compulsory subscription independent 283 311 # of the time since last notify 284 foreach my $topic ( Foswiki::Func::getTopicList($web)) {312 foreach my $topic ( Foswiki::Func::getTopicList($web) ) { 285 313 $notify->processCompulsory( $topic, $db, \%allSet ); 286 314 } 287 315 288 316 # Now generate emails for each recipient 289 my $report = _sendChangesMails(290 $twiki, $web, \%changeset,317 my $report = 318 _sendChangesMails( $twiki, $web, \%changeset, 291 319 Foswiki::Time::formatTime($timeOfLastNotify) ); 292 320 293 $report .= _sendNewsletterMails( $twiki, $web, \%allSet );294 295 if ( $timeOfLastChange != 0) {296 if ( open(F, ">$notmeta" )) {321 $report .= _sendNewsletterMails( $twiki, $web, \%allSet ); 322 323 if ( $timeOfLastChange != 0 ) { 324 if ( open( F, '>', $notmeta ) ) { 297 325 print F $timeOfLastChange; 298 326 close(F); … … 308 336 my $report = ''; 309 337 338 # We read the mailnotify template in the context (skin and web) or the 339 # WebNotify topic we are currently processing 340 Foswiki::Func::pushTopicContext( $web, $Foswiki::cfg{NotifyTopicName} ); 310 341 my $skin = Foswiki::Func::getSkin(); 311 342 my $template = Foswiki::Func::readTemplate( 'mailnotify', $skin ); 343 Foswiki::Func::popTopicContext(); 312 344 313 345 my $homeTopic = $Foswiki::cfg{HomeTopicName}; 314 346 315 my $before_html = Foswiki::Func::expandTemplate( 'HTML:before' ); 316 my $middle_html = Foswiki::Func::expandTemplate( 'HTML:middle' ); 317 my $after_html = Foswiki::Func::expandTemplate( 'HTML:after' ); 318 319 my $before_plain = Foswiki::Func::expandTemplate( 'PLAIN:before' ); 320 my $middle_plain = Foswiki::Func::expandTemplate( 'PLAIN:middle' ); 321 my $after_plain = Foswiki::Func::expandTemplate( 'PLAIN:after' ); 322 323 my $mailtmpl = Foswiki::Func::expandTemplate( 'MailNotifyBody' ); 324 $mailtmpl = Foswiki::Func::expandCommonVariables( 325 $mailtmpl, $homeTopic, $web ); 326 if( $Foswiki::cfg{RemoveImgInMailnotify} ) { 347 my $before_html = Foswiki::Func::expandTemplate('HTML:before'); 348 my $middle_html = Foswiki::Func::expandTemplate('HTML:middle'); 349 my $after_html = Foswiki::Func::expandTemplate('HTML:after'); 350 351 my $before_plain = Foswiki::Func::expandTemplate('PLAIN:before'); 352 my $middle_plain = Foswiki::Func::expandTemplate('PLAIN:middle'); 353 my $after_plain = Foswiki::Func::expandTemplate('PLAIN:after'); 354 355 my $mailtmpl = Foswiki::Func::expandTemplate('MailNotifyBody'); 356 $mailtmpl = 357 Foswiki::Func::expandCommonVariables( $mailtmpl, $homeTopic, $web ); 358 if ( $Foswiki::cfg{RemoveImgInMailnotify} ) { 359 327 360 # change images to [alt] text if there, else remove image 328 361 $mailtmpl =~ s/<img\s[^>]*\balt=\"([^\"]+)[^>]*>/[$1]/goi; … … 333 366 334 367 foreach my $email ( keys %{$changeset} ) { 335 my $html = '';368 my $html = ''; 336 369 my $plain = ''; 337 foreach my $change (sort { $a->{TIME} cmp $b->{TIME} } 338 @{$changeset->{$email}} ) { 339 340 $html .= $change->expandHTML( $middle_html ); 341 $plain .= $change->expandPlain( $middle_plain ); 370 foreach my $change ( sort { $a->{TIME} cmp $b->{TIME} } 371 @{ $changeset->{$email} } ) 372 { 373 374 $html .= $change->expandHTML($middle_html); 375 $plain .= $change->expandPlain($middle_plain); 342 376 } 343 377 … … 363 397 if ($error) { 364 398 print STDERR "Error sending mail forf $web: $error\n"; 365 $report .= $error."\n"; 366 } else { 399 $report .= $error . "\n"; 400 } 401 else { 367 402 print "Notified $email of changes in $web\n" if $verbose; 368 403 $sentMails++; … … 375 410 376 411 sub relativeURL { 377 my ( $base, $link ) = @_;412 my ( $base, $link ) = @_; 378 413 return URI->new_abs( $link, URI->new($base) )->as_string; 379 414 } 380 415 381 416 sub _sendNewsletterMails { 382 my ( $twiki, $web, $allSet) = @_;417 my ( $twiki, $web, $allSet ) = @_; 383 418 384 419 my $report = ''; 385 foreach my $topic ( keys %$allSet) {386 $report .= _sendNewsletterMail(387 $twiki, $web, $topic, $allSet->{$topic});420 foreach my $topic ( keys %$allSet ) { 421 $report .= 422 _sendNewsletterMail( $twiki, $web, $topic, $allSet->{$topic} ); 388 423 } 389 424 return $report; … … 391 426 392 427 sub _sendNewsletterMail { 393 my ( $twiki, $web, $topic, $emails) = @_;428 my ( $twiki, $web, $topic, $emails ) = @_; 394 429 my $wikiName = Foswiki::Func::getWikiName(); 395 430 … … 397 432 398 433 # Read topic data. 399 my ( $meta, $text) = Foswiki::Func::readTopic( $web, $topic );400 401 if ( !defined( &Foswiki::Func::pushTopicContext )) {434 my ( $meta, $text ) = Foswiki::Func::readTopic( $web, $topic ); 435 436 if ( !defined(&Foswiki::Func::pushTopicContext) ) { 402 437 require Foswiki::Contrib::MailerContrib::TopicContext; 403 438 } 439 440 # SMELL: Have to hack into the core to set internal preferences :-( 441 my %old = map { $_ => undef } qw(BASEWEB BASETOPIC INCLUDINGWEB INCLUDINGTOPIC); 442 if (defined $Foswiki::Plugins::SESSION->{SESSION_TAGS}) { 443 444 # In 1.0.6 and earlier, have to handle some session tags ourselves 445 # because pushTopicContext doesn't do it. ** 446 foreach my $macro (keys %old) { 447 $old{$macro} = Foswiki::Func::getPreferencesValue($macro); 448 } 449 } 404 450 Foswiki::Func::pushTopicContext( $web, $topic ); 451 452 # See ** above 453 if (defined $Foswiki::Plugins::SESSION->{SESSION_TAGS}) { 454 my $stags = $Foswiki::Plugins::SESSION->{SESSION_TAGS}; 455 $stags->{BASEWEB} = $web; 456 $stags->{BASETOPIC} = $topic; 457 $stags->{INCLUDINGWEB} = $web; 458 $stags->{INCLUDINGTOPIC} = $topic; 459 } 405 460 406 461 $twiki->enterContext( 'can_render_meta', $meta ); … … 409 464 my $skin = Foswiki::Func::getSkin(); 410 465 Foswiki::Func::readTemplate( 'newsletter', $skin ); 411 my $header = Foswiki::Func::expandTemplate( 'NEWS:header');412 my $body = Foswiki::Func::expandTemplate( 'NEWS:body');413 my $footer = Foswiki::Func::expandTemplate( 'NEWS:footer');414 415 my ( $revdate, $revuser, $maxrev);416 ( $revdate, $revuser, $maxrev) = $meta->getRevisionInfo();466 my $header = Foswiki::Func::expandTemplate('NEWS:header'); 467 my $body = Foswiki::Func::expandTemplate('NEWS:body'); 468 my $footer = Foswiki::Func::expandTemplate('NEWS:footer'); 469 470 my ( $revdate, $revuser, $maxrev ); 471 ( $revdate, $revuser, $maxrev ) = $meta->getRevisionInfo(); 417 472 418 473 # Handle standard formatting. 419 474 $body =~ s/%TEXT%/$text/g; 475 420 476 # Don't render the header, it is preformatted 421 $header = Foswiki::Func::expandCommonVariables( $header, $topic, $web);477 $header = Foswiki::Func::expandCommonVariables( $header, $topic, $web ); 422 478 my $tmpl = "$body\n$footer"; 423 $tmpl = Foswiki::Func::expandCommonVariables( $tmpl, $topic, $web);424 $tmpl = Foswiki::Func::renderText( $tmpl, "", $meta);479 $tmpl = Foswiki::Func::expandCommonVariables( $tmpl, $topic, $web ); 480 $tmpl = Foswiki::Func::renderText( $tmpl, "", $meta ); 425 481 $tmpl = "$header$tmpl"; 426 482 … … 432 488 my $tagSeen = 0; 433 489 my $publish = 1; 434 foreach my $s ( split( /(%STARTPUBLISH%|%STOPPUBLISH%)/, $tmpl ) ) {435 if ( $s eq '%STARTPUBLISH%' ) {490 foreach my $s ( split( /(%STARTPUBLISH%|%STOPPUBLISH%)/, $tmpl ) ) { 491 if ( $s eq '%STARTPUBLISH%' ) { 436 492 $publish = 1; 437 $newTmpl = '' unless ( $tagSeen);493 $newTmpl = '' unless ($tagSeen); 438 494 $tagSeen = 1; 439 } elsif( $s eq '%STOPPUBLISH%' ) { 495 } 496 elsif ( $s eq '%STOPPUBLISH%' ) { 440 497 $publish = 0; 441 498 $tagSeen = 1; 442 } elsif( $publish ) { 499 } 500 elsif ($publish) { 443 501 $newTmpl .= $s; 444 502 } … … 453 511 # Remove <base.../> tag 454 512 $tmpl =~ s/<base[^>]+\/>//; 513 455 514 # Remove <base...>...</base> tag 456 515 $tmpl =~ s/<base[^>]+>.*?<\/base>//; … … 461 520 $tmpl =~ s/(action=\")([^"]+)/$1.relativeURL($base,$2)/goei; 462 521 463 my $report = '';522 my $report = ''; 464 523 my $sentMails = 0; 465 524 … … 482 541 if ($error) { 483 542 print STDERR "Error sending mail for $web: $error\n"; 484 $report .= $error."\n"; 485 } else { 543 $report .= $error . "\n"; 544 } 545 else { 486 546 print "Sent newletter for $web to $email\n" if $verbose; 487 547 $sentMails++; … … 491 551 492 552 Foswiki::Func::popTopicContext(); 553 554 # SMELL: See ** above 555 if (defined $Foswiki::Plugins::SESSION->{SESSION_TAGS}) { 556 557 # In 1.0.6 and earlier, have to handle some session tags ourselves 558 # because pushTopicContext doesn't do it. ** 559 foreach my $macro (keys %old) { 560 $Foswiki::Plugins::SESSION->{SESSION_TAGS}{$macro} = 561 $old{$macro}; 562 } 563 } 493 564 494 565 return $report; -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/Change.pm
r1340 r5269 53 53 54 54 $this->{SESSION} = $session; 55 $this->{WEB} = $web;56 $this->{TOPIC} = $topic;55 $this->{WEB} = $web; 56 $this->{TOPIC} = $topic; 57 57 my $user; 58 58 59 # SMELL: call to unpublished core function 59 if ( defined(&Foswiki::Users::findUser)) {60 if ( defined(&Foswiki::Users::findUser) ) { 60 61 $user = $session->{users}->findUser( $author, undef, 1 ); 61 62 $this->{AUTHOR} = $user ? $user->wikiName() : $author; 62 } else { 63 } 64 else { 63 65 $this->{AUTHOR} = Foswiki::Func::getWikiName($author); 64 66 } 65 67 $this->{TIME} = $time; 66 68 ASSERT($rev) if DEBUG; 69 67 70 # rev at this change 68 71 $this->{CURR_REV} = $rev; 72 69 73 # previous rev 70 74 $this->{BASE_REV} = $rev - 1 || 1; … … 76 80 my $this = shift; 77 81 78 return "$this->{WEB}.$this->{TOPIC} by $this->{AUTHOR} at $this->{TIME} from r$this->{BASE_REV} to r$this->{CURR_REV}"; 82 return 83 "$this->{WEB}.$this->{TOPIC} by $this->{AUTHOR} at $this->{TIME} from r$this->{BASE_REV} to r$this->{CURR_REV}"; 79 84 } 80 85 … … 89 94 90 95 sub merge { 91 my ( $this, $other ) = @_;92 ASSERT( $this->isa( 'Foswiki::Contrib::MailerContrib::Change' ))if DEBUG;93 ASSERT( $other->isa( 'Foswiki::Contrib::MailerContrib::Change' )) if DEBUG;94 95 if ( $other->{CURR_REV} > $this->{CURR_REV} ) {96 my ( $this, $other ) = @_; 97 ASSERT( $this->isa('Foswiki::Contrib::MailerContrib::Change') ) if DEBUG; 98 ASSERT( $other->isa('Foswiki::Contrib::MailerContrib::Change') ) if DEBUG; 99 100 if ( $other->{CURR_REV} > $this->{CURR_REV} ) { 96 101 $this->{CURR_REV} = $other->{CURR_REV}; 97 $this->{AUTHOR} = $other->{AUTHOR};98 $this->{TIME} = $other->{TIME};102 $this->{AUTHOR} = $other->{AUTHOR}; 103 $this->{TIME} = $other->{TIME}; 99 104 } 100 105 101 106 $this->{BASE_REV} = $other->{BASE_REV} 102 if ($other->{BASE_REV} < $this->{BASE_REV});107 if ( $other->{BASE_REV} < $this->{BASE_REV} ); 103 108 } 104 109 … … 118 123 my ( $this, $html ) = @_; 119 124 120 unless ( defined $this->{HTML_SUMMARY} ) {121 if ( defined &Foswiki::Func::summariseChanges ) {125 unless ( defined $this->{HTML_SUMMARY} ) { 126 if ( defined &Foswiki::Func::summariseChanges ) { 122 127 $this->{HTML_SUMMARY} = 123 Foswiki::Func::summariseChanges( 124 $this->{WEB}, $this->{TOPIC}, $this->{BASE_REV},125 $this->{CURR_REV}, 1 );126 }else {128 Foswiki::Func::summariseChanges( $this->{WEB}, $this->{TOPIC}, 129 $this->{BASE_REV}, $this->{CURR_REV}, 1 ); 130 } 131 else { 127 132 $this->{HTML_SUMMARY} = 128 $this->{SESSION}->{renderer} ->summariseChanges129 ( undef, $this->{WEB}, $this->{TOPIC}, $this->{BASE_REV},130 $this->{CURR_REV}, 1 );133 $this->{SESSION}->{renderer} 134 ->summariseChanges( undef, $this->{WEB}, $this->{TOPIC}, 135 $this->{BASE_REV}, $this->{CURR_REV}, 1 ); 131 136 } 132 137 } … … 134 139 $html =~ s/%TOPICNAME%/$this->{TOPIC}/g; 135 140 $html =~ s/%AUTHOR%/$this->{AUTHOR}/g; 136 my $tim = Foswiki::Time::formatTime( $this->{TIME} );141 my $tim = Foswiki::Time::formatTime( $this->{TIME} ); 137 142 $html =~ s/%TIME%/$tim/go; 138 143 $html =~ s/%CUR_REV%/$this->{CURR_REV}/g; 139 144 $html =~ s/%BASE_REV%/$this->{BASE_REV}/g; 140 145 my $frev = ''; 141 if( $this->{CURR_REV} ) { 142 if( $this->{CURR_REV} > 1 ) { 143 $frev = 'r'.$this->{BASE_REV}. 144 '->r'.$this->{CURR_REV}; 145 } else { 146 if ( $this->{CURR_REV} ) { 147 if ( $this->{CURR_REV} > 1 ) { 148 $frev = 'r' . $this->{BASE_REV} . '->r' . $this->{CURR_REV}; 149 } 150 else { 151 146 152 # new _since the last notification_ 147 $frev = CGI::span( { class =>'foswikiNew' }, 'NEW' );153 $frev = CGI::span( { class => 'foswikiNew' }, 'NEW' ); 148 154 } 149 155 } 150 156 $html =~ s/%REVISION%/$frev/g; 151 $html = Foswiki::Func::expandCommonVariables( 152 $html, $this->{TOPIC}, $this->{WEB} ); 153 $html = Foswiki::Func::renderText( $html ); 157 $html = 158 Foswiki::Func::expandCommonVariables( $html, $this->{TOPIC}, 159 $this->{WEB} ); 160 $html = Foswiki::Func::renderText($html); 154 161 $html =~ s/%TEXTHEAD%/$this->{HTML_SUMMARY}/g; 155 162 … … 167 174 my ( $this, $template ) = @_; 168 175 169 unless ( defined $this->{TEXT_SUMMARY} ) {176 unless ( defined $this->{TEXT_SUMMARY} ) { 170 177 my $s; 171 if( defined &Foswiki::Func::summariseChanges ) { 172 $s = Foswiki::Func::summariseChanges( 173 $this->{WEB}, $this->{TOPIC}, $this->{BASE_REV}, 174 $this->{CURR_REV}, 0 ); 175 } else { 176 $s = $this->{SESSION}->{renderer}->summariseChanges( 177 undef, $this->{WEB}, $this->{TOPIC}, $this->{BASE_REV}, 178 $this->{CURR_REV}, 0 ); 178 if ( defined &Foswiki::Func::summariseChanges ) { 179 $s = 180 Foswiki::Func::summariseChanges( $this->{WEB}, $this->{TOPIC}, 181 $this->{BASE_REV}, $this->{CURR_REV}, 0 ); 182 } 183 else { 184 $s = 185 $this->{SESSION}->{renderer} 186 ->summariseChanges( undef, $this->{WEB}, $this->{TOPIC}, 187 $this->{BASE_REV}, $this->{CURR_REV}, 0 ); 179 188 } 180 189 $s =~ s/\n/\n /gs; … … 183 192 } 184 193 185 my $tim = Foswiki::Time::formatTime( $this->{TIME} );194 my $tim = Foswiki::Time::formatTime( $this->{TIME} ); 186 195 187 196 # URL-encode topic names for use of I18N topic names in plain text … … 193 202 $template =~ s/%CUR_REV%/$this->{CURR_REV}/g; 194 203 $template =~ s/%BASE_REV%/$this->{BASE_REV}/g; 195 $template =~ s/%TOPICNAME%/$this->{TOPIC}/g; # deprecated DO NOT USE!204 $template =~ s/%TOPICNAME%/$this->{TOPIC}/g; # deprecated DO NOT USE! 196 205 $template =~ s/%TOPIC%/$this->{TOPIC}/g; 197 206 my $frev = ''; 198 if( $this->{CURR_REV} ) { 199 if( $this->{CURR_REV} > 1 ) { 200 $frev = 'r'.$this->{BASE_REV}. 201 '->r'.$this->{CURR_REV}; 202 } else { 207 if ( $this->{CURR_REV} ) { 208 if ( $this->{CURR_REV} > 1 ) { 209 $frev = 'r' . $this->{BASE_REV} . '->r' . $this->{CURR_REV}; 210 } 211 else { 212 203 213 # new _since the last notification_ 204 214 $frev = 'NEW'; -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/CompatibilityHacks.pm
r1340 r5269 4 4 package IteratorHack; 5 5 6 use strict; 7 6 8 sub new { 7 my ( $class, $list) = @_;8 my $this = bless( {list => $list, index => 0, next => undef }, $class);9 my ( $class, $list ) = @_; 10 my $this = bless( { list => $list, index => 0, next => undef }, $class ); 9 11 return $this; 10 12 } 11 13 12 14 sub hasNext { 13 my ( $this) = @_;15 my ($this) = @_; 14 16 return 1 if $this->{next}; 15 if ( $this->{index} < scalar(@{$this->{list}}) ) {16 $this->{next} = $this->{list}->[ $this->{index}++];17 if ( $this->{index} < scalar( @{ $this->{list} } ) ) { 18 $this->{next} = $this->{list}->[ $this->{index}++ ]; 17 19 return 1; 18 20 } … … 31 33 32 34 sub eachChangeSince { 33 my ( $web, $since) = @_;35 my ( $web, $since ) = @_; 34 36 35 37 my $changes; 36 if ( open(F, "<$Foswiki::cfg{DataDir}/$web/.changes")) {38 if ( open( F, '<', "$Foswiki::cfg{DataDir}/$web/.changes" ) ) { 37 39 local $/ = undef; 38 40 $changes = <F>; … … 44 46 my @changes = 45 47 map { 46 # Create a hash for this line 47 { topic => $_->[0], user => $_->[1], time => $_->[2], 48 revision => $_->[3], more => $_->[4] }; 48 49 # Create a hash for this line 50 { 51 topic => $_->[0], 52 user => $_->[1], 53 time => $_->[2], 54 revision => $_->[3], 55 more => $_->[4] 56 }; 49 57 } 50 grep { 51 # Filter on time 52 $_->[2] && $_->[2] >= $since 53 } 54 map { 55 # Split line into an array 56 my @row = split(/\t/, $_, 5); 57 \@row; 58 } 59 reverse split( /[\r\n]+/, $changes); 58 grep { 59 60 # Filter on time 61 $_->[2] && $_->[2] >= $since 62 } 63 map { 64 65 # Split line into an array 66 my @row = split( /\t/, $_, 5 ); 67 \@row; 68 } 69 reverse split( /[\r\n]+/, $changes ); 60 70 61 71 return new IteratorHack( \@changes ); -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/Config.spec
r1061 r5269 1 # ---+ Mail and Proxies 1 # ---+ Extensions 2 # ---++ MailerContrib 2 3 # **REGEX** 3 4 # Define the regular expression that an email address entered in WebNotify … … 5 6 # this expression to - for example - filter email addresses on your company 6 7 # domain, or even block use of raw emails in WebNotify altogether (just make 7 # it something that will never match, e.g. ='^notAnEmail$'=).8 # it something that will never match, e.g. <code>^notAnEmail$</code>). 8 9 # If this is not defined, then the default setting of 9 # =[A-Za-z0-9.+-_]+\@[A-Za-z0-9.-]+=is used.10 # <code>[A-Za-z0-9.+-_]+\@[A-Za-z0-9.-]+</code> is used. 10 11 $Foswiki::cfg{MailerContrib}{EmailFilterIn} = ''; 11 12 -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/Constants.pm
r1340 r5269 1 1 2 =pod 2 3 … … 14 15 package MailerConst; 15 16 16 our $ALWAYS = 1; # Always send, even if there are no changes 17 our $FULL_TOPIC = 2; # Send the full topic rather than just changes 17 use strict; 18 19 our $ALWAYS = 1; # Always send, even if there are no changes 20 our $FULL_TOPIC = 2; # Send the full topic rather than just changes 18 21 19 22 # ? = FULL_TOPIC -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/Subscriber.pm
r1340 r5269 67 67 my $this = shift; 68 68 69 unless ( defined( $this->{emails} ) ) {70 $this->{emails} = getEmailAddressesForUser( $this->{name} );69 unless ( defined( $this->{emails} ) ) { 70 $this->{emails} = getEmailAddressesForUser( $this->{name} ); 71 71 } 72 72 return $this->{emails}; … … 82 82 83 83 sub getEmailAddressesForUser { 84 my $name = shift;84 my $name = shift; 85 85 my $emails = []; 86 86 … … 89 89 if ( $name =~ /^$Foswiki::cfg{MailerContrib}{EmailFilterIn}$/ ) { 90 90 push( @{$emails}, $name ); 91 } else { 91 } 92 else { 92 93 my $users = $Foswiki::Plugins::SESSION->{users}; 93 if ($users->can('findUserByWikiName')) { 94 if ( $users->can('findUserByWikiName') ) { 95 94 96 # User is represented by a wikiname. Map to a canonical 95 97 # userid. 96 98 my $list = $users->findUserByWikiName($name); 97 99 foreach my $user (@$list) { 100 98 101 # Automatically expands groups 99 102 push( @{$emails}, $users->getEmails($user) ); 100 103 } 101 } else { 104 } 105 else { 106 102 107 # Old code; use the user object 103 108 my $user = $users->findUser( $name, undef, 1 ); 104 if ( $user) {109 if ($user) { 105 110 push( @{$emails}, $user->emails() ); 106 } else {107 $user = $users->findUser(108 $name, $name, 1 );109 if ( $user) {111 } 112 else { 113 $user = $users->findUser( $name, $name, 1 ); 114 if ($user) { 110 115 push( @{$emails}, $user->emails() ); 111 } else { 116 } 117 else { 118 112 119 # unknown - can't find an email 113 120 $emails = []; … … 123 130 # topics. 124 131 sub _addAndOptimise { 125 my ( $this, $set, $new ) = @_;132 my ( $this, $set, $new ) = @_; 126 133 127 134 # Don't add already covered duplicates 128 135 my $i = 0; 129 136 my @remove; 130 foreach my $known ( @{$this->{$set}}) {137 foreach my $known ( @{ $this->{$set} } ) { 131 138 return if $known->covers($new); 132 if( $new->covers( $known )) { 139 if ( $new->covers($known) ) { 140 133 141 # remove anything covered by the new subscription 134 unshift( @remove, $i);142 unshift( @remove, $i ); 135 143 } 136 144 $i++; 137 145 } 138 146 foreach $i (@remove) { 139 splice( @{$this->{$set}}, $i, 1);140 } 141 push( @{ $this->{$set}}, $new );147 splice( @{ $this->{$set} }, $i, 1 ); 148 } 149 push( @{ $this->{$set} }, $new ); 142 150 } 143 151 … … 145 153 # you can in the face of wildcards. 146 154 sub _subtract { 147 my ( $this, $set, $new ) = @_;155 my ( $this, $set, $new ) = @_; 148 156 149 157 my $i = 0; 150 158 my @remove; 151 foreach my $known (@{$this->{$set}}) { 152 if( $new->covers( $known )) { 159 foreach my $known ( @{ $this->{$set} } ) { 160 if ( $new->covers($known) ) { 161 153 162 # remove anything covered by the new subscription 154 unshift( @remove, $i);163 unshift( @remove, $i ); 155 164 } 156 165 $i++; 157 166 } 158 167 foreach $i (@remove) { 159 splice( @{$this->{$set}}, $i, 1);168 splice( @{ $this->{$set} }, $i, 1 ); 160 169 } 161 170 } … … 193 202 194 203 $this->_addAndOptimise( 'unsubscriptions', $subs ); 195 if ($subs->matches('*')) { 204 if ( $subs->matches('*') ) { 205 196 206 # -* makes no sense and causes evaluation problems. 197 207 $this->_subtract( 'unsubscriptions', $subs ); 198 208 } 199 209 $this->_subtract( 'subscriptions', $subs ); 200 #TODO: should look at removing redundant exclusions ie a - SubScribe (2) when there is no positive subscription 201 210 211 #TODO: should look at removing redundant exclusions ie a - SubScribe (2) when there is no positive subscription 212 202 213 #if there are no subscriptions, there is no point luging around the unsubs 203 if ( scalar(@{$this->{'subscriptions'}}) == 0) {204 undef @{ $this->{'unsubscriptions'}};214 if ( scalar( @{ $this->{'subscriptions'} } ) == 0 ) { 215 undef @{ $this->{'unsubscriptions'} }; 205 216 } 206 217 } … … 217 228 218 229 sub isSubscribedTo { 219 my ( $this, $topic, $db ) = @_;220 221 foreach my $subscription ( @{$this->{subscriptions}} ) {222 if ( $subscription->matches( $topic, $db )) {223 return $subscription;224 }225 }226 227 return undef;230 my ( $this, $topic, $db ) = @_; 231 232 foreach my $subscription ( @{ $this->{subscriptions} } ) { 233 if ( $subscription->matches( $topic, $db ) ) { 234 return $subscription; 235 } 236 } 237 238 return; 228 239 } 229 240 … … 238 249 239 250 sub isUnsubscribedFrom { 240 my ( $this, $topic, $db ) = @_;241 242 foreach my $subscription ( @{$this->{unsubscriptions}} ) {243 if ( $subscription->matches( $topic, $db )) {244 return $subscription;245 }246 }247 248 return undef;251 my ( $this, $topic, $db ) = @_; 252 253 foreach my $subscription ( @{ $this->{unsubscriptions} } ) { 254 if ( $subscription->matches( $topic, $db ) ) { 255 return $subscription; 256 } 257 } 258 259 return; 249 260 } 250 261 … … 258 269 sub stringify { 259 270 my $this = shift; 260 my $subs = join( ' ', 261 map { $_->stringify(); } 262 @{$this->{subscriptions}} ); 263 my $unsubs = join( " - ", 264 map { $_->stringify(); } 265 @{$this->{unsubscriptions}} ); 271 my $subs = 272 join( ' ', map { $_->stringify(); } @{ $this->{subscriptions} } ); 273 my $unsubs = 274 join( " - ", map { $_->stringify(); } @{ $this->{unsubscriptions} } ); 266 275 $unsubs = " - $unsubs" if $unsubs; 267 276 268 277 my $name = $this->{name}; 269 if ( $name =~ /^$Foswiki::regex{wikiWordRegex}$/) {270 $name = '%USERSWEB%.' .$name;271 } elsif ($name !~ /^$Foswiki::cfg{MailerContrib}{EmailFilterIn}$/) {272 $name = $name =~ /'/ ? '"'.$name.'"' : "'$name'";273 }274 return " * " . $name . ": " .275 $subs . $unsubs;278 if ( $name =~ /^$Foswiki::regex{wikiWordRegex}$/ ) { 279 $name = '%USERSWEB%.' . $name; 280 } 281 elsif ( $name !~ /^$Foswiki::cfg{MailerContrib}{EmailFilterIn}$/ ) { 282 $name = $name =~ /'/ ? '"' . $name . '"' : "'$name'"; 283 } 284 return " * " . $name . ": " . $subs . $unsubs; 276 285 } 277 286 -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/Subscription.pm
r1340 r5269 42 42 my ( $class, $topics, $depth, $opts ) = @_; 43 43 44 ASSERT( defined($opts) && $opts =~ /^\d*$/) if DEBUG;44 ASSERT( defined($opts) && $opts =~ /^\d*$/ ) if DEBUG; 45 45 46 46 my $this = bless( {}, $class ); 47 47 48 $this->{topics} = $topics || '';49 $this->{depth} = $depth|| 0;50 $this->{options} = $opts || 0;48 $this->{topics} = $topics || ''; 49 $this->{depth} = $depth || 0; 50 $this->{options} = $opts || 0; 51 51 52 52 $topics =~ s/[^\w\*]//g; … … 65 65 66 66 sub stringify { 67 my $this = shift;67 my $this = shift; 68 68 my $record = $this->{topics}; 69 # convert RE back to wildcard 70 $record =~ s/\.\*\?/\*/; 69 70 # Protect non-alphanumerics in topic name 71 if ($record =~ /[^*\w.]/) { 72 if ($record =~ /'/) { 73 $record = "\"$record\""; 74 } else { 75 $record = "'$record'"; 76 } 77 } 71 78 $record .= $this->getMode(); 72 79 $record .= " ($this->{depth})" if ( $this->{depth} ); … … 93 100 return 1 if ( $topic =~ $this->{topicsRE} ); 94 101 95 $depth = $this->{depth} unless defined( $depth);102 $depth = $this->{depth} unless defined($depth); 96 103 $depth ||= 0; 97 104 98 if ( $depth && $db ) {99 my $parent = $db->getParent( $topic);105 if ( $depth && $db ) { 106 my $parent = $db->getParent($topic); 100 107 $parent =~ s/^.*\.//; 101 return $this->matches( $parent, $db, $depth - 1 ) if ( $parent);108 return $this->matches( $parent, $db, $depth - 1 ) if ($parent); 102 109 } 103 110 … … 119 126 120 127 sub covers { 121 my ( $this, $tother, $db ) = @_;122 128 my ( $this, $tother, $db ) = @_; 129 123 130 #* should win always. 124 return 1 if ( $this->{topics} eq '*');131 return 1 if ( $this->{topics} eq '*' ); 125 132 126 133 # Does the mode cover the other subscription? 127 return 0 unless 128 (($this->{options} & $tother->{options}) == $tother->{options}); 134 return 0 135 unless ( 136 ( $this->{options} & $tother->{options} ) == $tother->{options} ); 129 137 130 138 # do they match without taking into account the depth? 131 return 0 unless ( $this->matches($tother->{topics}, undef, 0) );139 return 0 unless ( $this->matches( $tother->{topics}, undef, 0 ) ); 132 140 133 141 # if we have a depth and they don't, that's already catered for … … 139 147 # if we have a depth and they have a depth, then there is coverage 140 148 # if our depth is >= their depth 141 return 0 unless ( $this->{depth} >= $tother->{depth} );149 return 0 unless ( $this->{depth} >= $tother->{depth} ); 142 150 143 151 return 1; … … 155 163 my $this = shift; 156 164 157 if ( $this->{options} & $MailerConst::FULL_TOPIC) {158 return '!' if ( $this->{options} & $MailerConst::ALWAYS);165 if ( $this->{options} & $MailerConst::FULL_TOPIC ) { 166 return '!' if ( $this->{options} & $MailerConst::ALWAYS ); 159 167 return '?'; 160 168 } … … 170 178 171 179 sub equals { 172 my ( $this, $tother ) = @_;173 return 0 unless ( $this->{options} eq $tother->{options});174 return 0 unless ( $this->{depth} == $tother->{depth});175 return 0 unless ( $this->{topics} eq $tother->{topics});180 my ( $this, $tother ) = @_; 181 return 0 unless ( $this->{options} eq $tother->{options} ); 182 return 0 unless ( $this->{depth} == $tother->{depth} ); 183 return 0 unless ( $this->{topics} eq $tother->{topics} ); 176 184 } 177 185 -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/TopicContext.pm
r1437 r5269 2 2 # by MailerContrib. 3 3 4 use strict; 5 4 6 sub Foswiki::Func::pushTopicContext { 5 my ( $web, $topic ) = @_;7 my ( $web, $topic ) = @_; 6 8 my $session = $Foswiki::Plugins::SESSION; 7 my ( $web, $topic ) = $session->normalizeWebTopicName( @_);9 my ( $web, $topic ) = $session->normalizeWebTopicName(@_); 8 10 my $old = { 9 web => $session->{webName},11 web => $session->{webName}, 10 12 topic => $session->{topicName}, 11 mark => $session->{prefs}->mark() }; 13 mark => $session->{prefs}->mark() 14 }; 12 15 13 push( @{ $session->{_FUNC_PREFS_STACK}}, $old );14 $session->{webName} = $web;16 push( @{ $session->{_FUNC_PREFS_STACK} }, $old ); 17 $session->{webName} = $web; 15 18 $session->{topicName} = $topic; 16 $session->{prefs}->pushWebPreferences( $web);19 $session->{prefs}->pushWebPreferences($web); 17 20 $session->{prefs}->pushPreferences( $web, $topic, 'TOPIC' ); 18 $session->{prefs}->pushPreferenceValues( 19 'SESSION',$session->{loginManager}->getSessionValues() );21 $session->{prefs}->pushPreferenceValues( 'SESSION', 22 $session->{loginManager}->getSessionValues() ); 20 23 } 21 24 22 25 sub Foswiki::Func::popTopicContext { 23 26 my $session = $Foswiki::Plugins::SESSION; 24 my $old = pop( @{$session->{_FUNC_PREFS_STACK}} );25 $session->{prefs}->restore( $old->{mark} );26 $session->{webName} = $old->{web};27 my $old = pop( @{ $session->{_FUNC_PREFS_STACK} } ); 28 $session->{prefs}->restore( $old->{mark} ); 29 $session->{webName} = $old->{web}; 27 30 $session->{topicName} = $old->{topic}; 28 31 } -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/UpData.pm
r1340 r5269 43 43 my ( $class, $session, $web ) = @_; 44 44 my $this = bless( {}, $class ); 45 $this->{web} = $web;45 $this->{web} = $web; 46 46 $this->{session} = $session; 47 47 return $this; … … 58 58 my ( $this, $topic ) = @_; 59 59 60 if ( ! defined( $this->{parent}{$topic} )) { 61 my( $meta, $text ) = 62 Foswiki::Func::readTopic( $this->{web}, $topic ); 60 if ( !defined( $this->{parent}{$topic} ) ) { 61 my ( $meta, $text ) = Foswiki::Func::readTopic( $this->{web}, $topic ); 63 62 my $parent = $meta->get('TOPICPARENT'); 64 63 $this->{parent}{$topic} = $parent->{name} if $parent; -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/WebNotify.pm
r3638 r5269 32 32 33 33 use strict; 34 use locale; # required for matching \w with international characters34 use locale; # required for matching \w with international characters 35 35 36 36 use Assert; … … 64 64 Foswiki::Contrib::MailerContrib::initContrib(); 65 65 66 $this->{web} = $web;67 $this->{topic} = $topic || $Foswiki::cfg{NotifyTopicName} || 'WebNotify';68 $this->{pretext} = '';66 $this->{web} = $web; 67 $this->{topic} = $topic || $Foswiki::cfg{NotifyTopicName} || 'WebNotify'; 68 $this->{pretext} = ''; 69 69 $this->{posttext} = ''; 70 $this->{session} = $session;70 $this->{session} = $session; 71 71 $this->{noexpandgroups} = $noexpandgroups; 72 72 73 if ( Foswiki::Func::topicExists( $web, $topic )) {73 if ( Foswiki::Func::topicExists( $web, $topic ) ) { 74 74 $this->_load(); 75 75 } … … 89 89 sub writeWebNotify { 90 90 my $this = shift; 91 Foswiki::Func::saveTopicText( 92 $this->{web}, 93 $this->{topic}, 94 $this->stringify(), 95 1, 1); 91 Foswiki::Func::saveTopicText( $this->{web}, $this->{topic}, 92 $this->stringify(), 1, 1 ); 96 93 } 97 94 … … 112 109 113 110 my $subscriber = $this->{subscribers}{$name}; 114 unless ( $noAdd || defined( $subscriber )) { 115 $subscriber = 116 new Foswiki::Contrib::MailerContrib::Subscriber( $name ); 111 unless ( $noAdd || defined($subscriber) ) { 112 $subscriber = new Foswiki::Contrib::MailerContrib::Subscriber($name); 117 113 $this->{subscribers}{$name} = $subscriber; 118 114 } … … 128 124 129 125 sub getSubscribers { 130 my ( $this) = @_;131 132 return keys %{ $this->{subscribers}};126 my ($this) = @_; 127 128 return keys %{ $this->{subscribers} }; 133 129 } 134 130 … … 147 143 my ( $this, $name, $topics, $depth, $opts ) = @_; 148 144 149 ASSERT( defined($opts) && $opts =~ /^\d*$/) if DEBUG;145 ASSERT( defined($opts) && $opts =~ /^\d*$/ ) if DEBUG; 150 146 151 147 my @names = ($name); 152 unless ( $this->{noexpandgroups}) {153 if ( defined &Foswiki::Func::eachGroupMember) {154 my $it = Foswiki::Func::eachGroupMember( $name);155 if ( $it) {148 unless ( $this->{noexpandgroups} ) { 149 if ( defined &Foswiki::Func::eachGroupMember ) { 150 my $it = Foswiki::Func::eachGroupMember($name); 151 if ($it) { 156 152 @names = (); 157 while ( $it->hasNext() ) {153 while ( $it->hasNext() ) { 158 154 my $member = $it->next(); 159 155 push( @names, $member ); 160 156 } 161 157 } 162 } else { 163 my $user = Foswiki::User->new($this->{session}, '', $name); 164 if ($user->isGroup) { 165 @names = map {$_->wikiName} @{$user->groupMembers}; 158 } 159 else { 160 my $user = Foswiki::User->new( $this->{session}, '', $name ); 161 if ( $user->isGroup ) { 162 @names = map { $_->wikiName } @{ $user->groupMembers }; 166 163 } 167 164 } … … 169 166 170 167 foreach my $n (@names) { 171 my $subscriber = $this->getSubscriber( $n ); 172 my $sub = new Foswiki::Contrib::MailerContrib::Subscription( 173 $topics, $depth, $opts ); 174 $subscriber->subscribe( $sub ); 168 my $subscriber = $this->getSubscriber($n); 169 my $sub = 170 new Foswiki::Contrib::MailerContrib::Subscription( $topics, $depth, 171 $opts ); 172 $subscriber->subscribe($sub); 175 173 } 176 174 } … … 191 189 my ( $this, $name, $topics, $depth ) = @_; 192 190 193 my @names = ( $name);194 unless ( $this->{noexpandgroups}) {195 if ( defined &Foswiki::Func::eachGroupMember) {196 my $it = Foswiki::Func::eachGroupMember( $name);197 if ( $it) {191 my @names = ($name); 192 unless ( $this->{noexpandgroups} ) { 193 if ( defined &Foswiki::Func::eachGroupMember ) { 194 my $it = Foswiki::Func::eachGroupMember($name); 195 if ($it) { 198 196 @names = (); 199 while ( $it->hasNext() ) {197 while ( $it->hasNext() ) { 200 198 my $member = $it->next(); 201 199 push( @names, $member ); 202 200 } 203 201 } 204 } else { 205 my $user = Foswiki::User->new($this->{session}, '', $name); 206 if ($user->isGroup) { 207 @names = map {$_->wikiName} @{$user->groupMembers}; 202 } 203 else { 204 my $user = Foswiki::User->new( $this->{session}, '', $name ); 205 if ( $user->isGroup ) { 206 @names = map { $_->wikiName } @{ $user->groupMembers }; 208 207 } 209 208 } … … 211 210 212 211 foreach my $n (@names) { 213 my $subscriber = $this->getSubscriber( $n ); 214 my $sub = new Foswiki::Contrib::MailerContrib::Subscription( 215 $topics, $depth, 0 ); 216 $subscriber->unsubscribe( $sub ); 212 my $subscriber = $this->getSubscriber($n); 213 my $sub = 214 new Foswiki::Contrib::MailerContrib::Subscription( $topics, $depth, 215 0 ); 216 $subscriber->unsubscribe($sub); 217 217 } 218 218 } … … 235 235 my $page = ''; 236 236 237 $page .= $this->{pretext} if ( !$subscribersOnly);238 foreach my $name ( sort keys %{ $this->{subscribers}} ) {237 $page .= $this->{pretext} if ( !$subscribersOnly ); 238 foreach my $name ( sort keys %{ $this->{subscribers} } ) { 239 239 my $subscriber = $this->{subscribers}{$name}; 240 240 $page .= $subscriber->stringify() . "\n"; 241 241 } 242 $page .= $this->{posttext} if ( !$subscribersOnly);242 $page .= $this->{posttext} if ( !$subscribersOnly ); 243 243 244 244 return $page; … … 262 262 my ( $this, $change, $db, $changeSet, $seenSet, $allSet ) = @_; 263 263 264 my $topic = $change->{TOPIC}; 265 my $web = $change->{WEB}; 266 my %authors = map { $_ => 1 } 267 @{Foswiki::Contrib::MailerContrib::Subscriber::getEmailAddressesForUser( 268 $change->{author})}; 269 270 foreach my $name ( keys %{$this->{subscribers}} ) { 264 my $topic = $change->{TOPIC}; 265 my $web = $change->{WEB}; 266 my %authors = map { $_ => 1 } @{ 267 Foswiki::Contrib::MailerContrib::Subscriber::getEmailAddressesForUser( 268 $change->{author} 269 ) 270 }; 271 272 foreach my $name ( keys %{ $this->{subscribers} } ) { 271 273 my $subscriber = $this->{subscribers}{$name}; 272 274 my $subs = $subscriber->isSubscribedTo( $topic, $db ); 273 if ($subs && !$subscriber->isUnsubscribedFrom( $topic, $db )) { 274 275 next unless Foswiki::Func::checkAccessPermission( 276 'VIEW', $name, undef, $topic, $this->{web}, undef ); 275 if ( $subs && !$subscriber->isUnsubscribedFrom( $topic, $db ) ) { 276 277 next 278 unless Foswiki::Func::checkAccessPermission( 'VIEW', $name, undef, 279 $topic, $this->{web}, undef ); 277 280 278 281 my $emails = $subscriber->getEmailAddresses(); 279 if( $emails && scalar( @$emails )) { 280 foreach my $email ( @$emails ) { 282 if ( $emails && scalar(@$emails) ) { 283 foreach my $email (@$emails) { 284 281 285 # Skip this change if the subscriber is the author 282 286 # of the change, and we are not always sending 283 next if (!($subs->{options} & $MailerConst::ALWAYS) 284 && $authors{$email}); 285 286 if ($subs->{options} & $MailerConst::FULL_TOPIC) { 287 push( @{$allSet->{$topic}}, $email ); 288 } else { 287 next 288 if ( !( $subs->{options} & $MailerConst::ALWAYS ) 289 && $authors{$email} ); 290 291 if ( $subs->{options} & $MailerConst::FULL_TOPIC ) { 292 push( @{ $allSet->{$topic} }, $email ); 293 } 294 else { 289 295 my $at = $seenSet->{$email}{$topic}; 290 if ( $at ) { 291 $changeSet->{$email}[$at - 1]->merge( $change ); 292 } else { 296 if ($at) { 297 $changeSet->{$email}[ $at - 1 ]->merge($change); 298 } 299 else { 293 300 $seenSet->{$email}{$topic} = 294 push( @{ $changeSet->{$email}}, $change );301 push( @{ $changeSet->{$email} }, $change ); 295 302 } 296 303 } 297 304 } 298 } else { 299 $this->_emailWarn($subscriber,$name,$web); 305 } 306 else { 307 $this->_emailWarn( $subscriber, $name, $web ); 300 308 } 301 309 } … … 313 321 314 322 sub processCompulsory { 315 my ( $this, $topic, $db, $allSet) = @_;316 317 foreach my $name ( keys %{ $this->{subscribers}} ) {323 my ( $this, $topic, $db, $allSet ) = @_; 324 325 foreach my $name ( keys %{ $this->{subscribers} } ) { 318 326 my $subscriber = $this->{subscribers}{$name}; 319 327 my $subs = $subscriber->isSubscribedTo( $topic, $db ); 320 328 next unless $subs; 321 next unless ( $subs->{options} & $MailerConst::ALWAYS);322 unless ( $subscriber->isUnsubscribedFrom( $topic, $db )) {329 next unless ( $subs->{options} & $MailerConst::ALWAYS ); 330 unless ( $subscriber->isUnsubscribedFrom( $topic, $db ) ) { 323 331 my $emails = $subscriber->getEmailAddresses(); 324 if ( $emails) {332 if ($emails) { 325 333 foreach my $address (@$emails) { 326 push( @{ $allSet->{$topic}}, $address );334 push( @{ $allSet->{$topic} }, $address ); 327 335 } 328 336 } … … 340 348 sub isEmpty { 341 349 my $this = shift; 342 return ( scalar( keys %{ $this->{subscribers}} ) == 0 );350 return ( scalar( keys %{ $this->{subscribers} } ) == 0 ); 343 351 } 344 352 … … 347 355 my $this = shift; 348 356 349 my ( $meta, $text ) = Foswiki::Func::readTopic(350 $this->{web}, $this->{topic} );357 my ( $meta, $text ) = 358 Foswiki::Func::readTopic( $this->{web}, $this->{topic} ); 351 359 my $in_pre = 1; 352 $this->{pretext} = '';360 $this->{pretext} = ''; 353 361 $this->{posttext} = ''; 354 $this->{meta} = $meta; 362 $this->{meta} = $meta; 363 355 364 # join \ terminated lines 356 365 $text =~ s/\\\r?\n//gs; 357 366 my $webRE = qr/(?:$Foswiki::cfg{UsersWebName}\.)?/o; 358 foreach my $baseline ( split ( /\r?\n/, $text )) { 359 my $line = Foswiki::Func::expandCommonVariables( 360 $baseline, $this->{topic}, $this->{web}, $meta); 361 if( $line =~ /^\s+\*\s$webRE($Foswiki::regex{wikiWordRegex})\s+\-\s+($Foswiki::cfg{MailerContrib}{EmailFilterIn}+)\s*$/o 362 && $1 ne $Foswiki::cfg{DefaultUserWikiName}) { 367 foreach my $baseline ( split( /\r?\n/, $text ) ) { 368 my $line = 369 Foswiki::Func::expandCommonVariables( $baseline, $this->{topic}, 370 $this->{web}, $meta ); 371 if ( $line =~ 372 /^\s+\*\s$webRE($Foswiki::regex{wikiWordRegex})\s+\-\s+($Foswiki::cfg{MailerContrib}{EmailFilterIn}+)\s*$/o 373 && $1 ne $Foswiki::cfg{DefaultUserWikiName} ) 374 { 375 363 376 # Main.WikiName - email@domain (legacy format) 364 377 $this->subscribe( $2, '*', 0, 0 ); 365 378 $in_pre = 0; 366 379 } 367 elsif ( $line =~ /^\s+\*\s$webRE($Foswiki::regex{wikiWordRegex}|'.*?'|".*?"|$Foswiki::cfg{MailerContrib}{EmailFilterIn})\s*(:.*)?$/o 368 && $1 ne $Foswiki::cfg{DefaultUserWikiName}) { 380 elsif ( $line =~ 381 /^\s+\*\s$webRE($Foswiki::regex{wikiWordRegex}|'.*?'|".*?"|$Foswiki::cfg{MailerContrib}{EmailFilterIn})\s*(:.*)?$/o 382 && $1 ne $Foswiki::cfg{DefaultUserWikiName} ) 383 { 369 384 my $subscriber = $1; 385 370 386 # Get the topic list from the last bracket matched. Have to do it 371 387 # this awkward way because the email filter may contain braces 372 388 my $topics = $+; 389 373 390 # email addresses can't start with : 374 $topics = undef unless ( $topics =~ s/^://);375 $subscriber =~ s/^(['"])(.*)\1$/$2/; # remove quotes391 $topics = undef unless ( $topics =~ s/^:// ); 392 $subscriber =~ s/^(['"])(.*)\1$/$2/; # remove quotes 376 393 if ($topics) { 377 394 $this->parsePageSubscriptions( $subscriber, $topics ); 378 } else { 379 $this->subscribe($subscriber, '*', 0, 0 ); 395 } 396 else { 397 $this->subscribe( $subscriber, '*', 0, 0 ); 380 398 } 381 399 $in_pre = 0; 382 400 } 383 401 else { 384 if ( $in_pre) {402 if ($in_pre) { 385 403 $this->{pretext} .= "$baseline\n"; 386 } else { 387 $this->{posttext} .= "$baseline\n"; 404 } 405 else { 406 $this->{posttext} .= "$baseline\n"; 388 407 } 389 408 } … … 395 414 sub parsePageSubscriptions { 396 415 my ( $this, $who, $spec, $unsubscribe ) = @_; 397 416 398 417 $this->{topicSub} = \&_subscribeTopic; 399 400 my $ret = Foswiki::Contrib::MailerContrib::parsePageList($this, $who, $spec, $unsubscribe); 418 419 my $ret = Foswiki::Contrib::MailerContrib::parsePageList( 420 $this, $who, $spec, $unsubscribe ); 401 421 if ( $ret =~ m/\S/ ) { 402 422 Foswiki::Func::writeWarning( 403 423 "Badly formatted page list at $who: $spec"); 404 return -1;424 return -1; 405 425 } 406 426 return; … … 409 429 sub _subscribeTopic { 410 430 my ( $this, $who, $unsubscribe, $webTopic, $options, $childDepth ) = @_; 411 412 my ($web, $topic) = Foswiki::Func::normalizeWebTopicName($this->{web}, $webTopic); 413 414 #print STDERR "_subscribeTopic($topic)\n"; 431 432 my ( $web, $topic ) = 433 Foswiki::Func::normalizeWebTopicName( $this->{web}, $webTopic ); 434 435 #print STDERR "_subscribeTopic($topic)\n"; 415 436 my $opts = 0; 416 437 if ($options) { 417 $opts |= $MailerConst::FULL_TOPIC;418 if ($options =~ /!/) {419 $opts |= $MailerConst::ALWAYS;420 }438 $opts |= $MailerConst::FULL_TOPIC; 439 if ( $options =~ /!/ ) { 440 $opts |= $MailerConst::ALWAYS; 441 } 421 442 } 422 443 my $kids = $childDepth or 0; 423 if ( $unsubscribe && $unsubscribe eq '-') { 424 $this->unsubscribe( $who, $topic, $kids ); 425 } else { 426 $this->subscribe( $who, $topic, $kids, $opts ); 427 } 444 if ( $unsubscribe && $unsubscribe eq '-' ) { 445 $this->unsubscribe( $who, $topic, $kids ); 446 } 447 else { 448 $this->subscribe( $who, $topic, $kids, $opts ); 449 } 450 428 451 #TODO: howto find & report errors? 429 452 return ''; … … 433 456 # for a subscriber. 434 457 sub _emailWarn { 435 my ( $this, $subscriber, $name, $web) = @_;458 my ( $this, $subscriber, $name, $web ) = @_; 436 459 437 460 # Make sure we only warn once. Don't want to see this for every 438 461 # Topic we are notifying on. 439 unless ( defined $this->{nomail}{$name}) {462 unless ( defined $this->{nomail}{$name} ) { 440 463 $this->{nomail}{$name} = 1; 441 Foswiki::Func::writeWarning( 442 "Failed to find permitted email for '".443 $subscriber->stringify()."' when processing web '$web'");464 Foswiki::Func::writeWarning( "Failed to find permitted email for '" 465 . $subscriber->stringify() 466 . "' when processing web '$web'" ); 444 467 } 445 468 } -
branches/Release01x00/MailerContrib/lib/Foswiki/Contrib/MailerContrib/build.pl
r1065 r5269 15 15 16 16 # Standard preamble 17 use strict; 18 17 19 BEGIN { 18 20 foreach my $pc (split(/:/, $ENV{FOSWIKI_LIBS})) { … … 30 32 sub new { 31 33 my $class = shift; 32 return bless( $class->SUPER::new( "MailerContrib" , "Mailer"), $class );34 return bless( $class->SUPER::new( "MailerContrib" ), $class ); 33 35 } 34 36 … … 44 46 45 47 # Create the build object 46 $build = new MailerBuild();48 my $build = new MailerBuild(); 47 49 48 50 # Mailer the target on the command line, or the default target -
branches/Release01x00/MailerContrib/tools/mailnotify
r1437 r5269 24 24 # search path for this script, so it can find the rest of Foswiki e.g. 25 25 # perl -I /usr/local/foswiki/bin /usr/local/foswiki/tools/mailnotify 26 27 use strict; 26 28 27 29 BEGIN {
Note: See TracChangeset
for help on using the changeset viewer.
