2 # This is a module with functions for HTML output.
4 # I separate it from the main STUMP stuff because these functions are
5 # bulky and not very interesting.
10 use CGI qw/escapeHTML/;
13 my $title = pop( @_ );
15 "Content-Type: text/html\n\n
21 print "<B> You are operating in demonstration mode. User actions will have no effect.</B><HR>\n";
27 print "\n<HR>Thank you for using <A HREF=$STUMP_URL>STUMP Robomoderator</A>.
29 Click <A HREF=$base_address>here</A> to return to WebSTUMP. -->
33 # prints a link to help
34 # accepts topic id and topic name.
37 my $topic_name = pop( @_ );
38 my $topic = pop( @_ );
40 #&print_image( "help.gif", "" );
42 print "<A HREF=$base_address?action=help&topic=$topic TARGET=new>Click here for help on $topic_name</A>\n";
46 # prints image and an alt text
48 sub print_image { # image_file, alt_text
52 print "<IMG SRC=$base_address_for_files/images/$file ALT=\"$alt\" ALIGN=BOTTOMP>\n";
55 # prints the welcome page and login screen.
56 sub html_welcome_page {
57 &begin_html( "Welcome to WebSTUMP" );
61 "Welcome to WebSTUMP, the moderators' front end for <A
62 HREF=http://www.algebra.com/~ichudov/stump>STUMP</A> users -- USENET newsgroup
63 moderators. Only authorized users are allowed to log into this
68 my $motd_file = "$webstump_home/config/motd";
70 if( -f $motd_file && -r $motd_file ){
71 open( MOTD, $motd_file );
72 print "<B>Message of the Day:</B><BR><PRE>\n";
73 print while( <MOTD> );
79 Newsgroups Status:<BR>
82 for( sort @newsgroups_array ) {
85 my $count = &get_article_count( $_ );
87 print " <A HREF=$base_address?action=login_screen\&newsgroup=$_>$_</A>";
88 &print_image( "smiley.gif", "" ) if $count;
92 print "<TD>$count messages in queue<BR></TD>";
93 # print "<TD><A HREF=$base_address?action=init_request_newsgroup_creation\&newsgroup=$_>Request creation</A></TD>\n";
97 print "<HR>Note: click on the newsgroup to login in as moderator.
98 <!-- Click on 'Request Creation' to ask a sysadmin at a specific domain
99 to carry your newsgroup. -->\n<HR>
100 <A HREF=$base_address?action=admin_login>Click here to administer this WebSTUMP installation</A>
105 # prints the login screen for newsgroup.
106 sub html_login_screen {
107 my $newsgroup = $request{'newsgroup'} || &error( "newsgroup not defined" );
109 my $count = &get_article_count( $newsgroup );
113 &begin_html( "$count articles in queue for $newsgroup" );
115 &begin_html( "Empty Queue for $newsgroup" );
119 " Welcome to the Moderation Center for $newsgroup. Please bookmark
123 my $color = "", $end_color = "";
126 $color = "<font color=red>";
127 $end_color = "<font color=black>";
131 "<FORM METHOD=$request_method action=$base_address>
132 <INPUT NAME=action VALUE=moderation_screen TYPE=hidden>
135 &print_image( "new_tiny2.gif", "new" ) if $count;
137 print " articles available)<BR> $end_color
138 Login: <INPUT NAME=moderator VALUE=\"\" SIZE=20>
140 Password: <INPUT NAME=password TYPE=password VALUE=\"\" SIZE=20>
142 <INPUT TYPE=submit VALUE=\"Proceed with Login\">
143 <INPUT TYPE=reset VALUE=\"Reset\">
144 <INPUT NAME=newsgroup VALUE=\"$newsgroup\" TYPE=hidden>
146 Please log into $newsgroup. You can only log in if you know your login id
147 and know the secret password. You should not give your password to any
148 unauthorized user. Your login id and password are NOT case sentitive,
150 for example, \"xyzzy\" and \"XyZZY\" are equally valid.<P>
154 # Log in as \"admin\" if you want to
156 # <LI> edit filtering lists.";
158 # &link_to_help( "filter-lists", "Filter Lists" );
161 # <LI> add/delete users or change their passwords.
162 # <LI> First Time Users: You have to log in as admin and add a moderator user
163 # who will be able to moderate the newsgroup. Then log in again as that
164 # user. If you are a new user, you have to have your admin password assigned to
165 # you by the administrator.
172 # prints the login screen for newsgroup.
173 sub admin_login_screen {
174 &begin_html( "Administrative login" );
178 Attention: this page is only for the maintainer of the whole WebSTUMP
179 installation. Please return to the main page if you are not the maintainer
180 of this installation. <HR>
184 "<FORM METHOD=$request_method action=$base_address>
185 <INPUT NAME=action VALUE=webstump_admin_screen TYPE=hidden>
186 Password: <INPUT NAME=password TYPE=password VALUE=\"\" SIZE=20>
188 <INPUT TYPE=submit VALUE=\"Proceed with Login\">
189 <INPUT TYPE=reset VALUE=\"Reset\">
196 # main moderation page -- single-article version
197 sub html_moderate_article {
198 my $newsgroup = &required_parameter( 'newsgroup' );
199 my $moderator = $request{'moderator'};
200 my $password = $request{'password'};
201 my $file = shift @_ || &required_parameter('file');
203 &begin_html( "Main Moderation Screen: $newsgroup" );
206 &read_rejection_reasons;
208 my $dir = "$queues_dir/$newsgroup";
210 if( -d "$dir/$file" && open( TEXT_FILES, "$dir/$file/text.files.lst" ) ) {
212 print "<HR>\n" if &print_article_warning( $file );
214 print "<pre style=\"white-space: pre-wrap\">\n";
217 while( $filename = <TEXT_FILES> ) {
218 open( ARTICLE, "$dir/$file/$filename" );
220 $embolden= m/^(?:from|subject)\s*\:/i;
224 $_= "<strong>$_</strong>" if $embolden;
226 $inhead= 0 unless m/\S/;
232 print "\n</PRE>\n\n";
234 &print_images( $newsgroup, "$dir/$file", $file);
237 print "This message ($dir/$file) no longer exists -- maybe it was " .
238 "approved or rejected by another moderator.";
242 <FORM NAME=decision METHOD=$request_method action=$base_address>
246 <INPUT NAME=action VALUE=approval_decision TYPE=hidden>";
247 &html_print_credentials;
248 print "<SELECT NAME=\"decision_$file\">
249 <OPTION VALUE=\"approve\">Approve</OPTION>
250 <OPTION VALUE=\"skip\" SELECTED>Leave</OPTION>
251 <OPTION VALUE=\"leave\">Back of queue</OPTION>
254 foreach (@short_rejection_reasons) {
255 print "<OPTION VALUE=\"reject $_\">Reject \u$_</OPTION>\n";
257 print "</SELECT> <BR> Comment (to poster, in rejection message): <INPUT NAME=comment VALUE=\"\" SIZE=80><BR>";
260 <INPUT TYPE=radio NAME=poster_decision VALUE=nothing CHECKED>Don't change poster's status</INPUT>
261 <INPUT TYPE=radio NAME=poster_decision VALUE=preapprove
262 >White-list poster</INPUT>
263 <INPUT TYPE=radio NAME=poster_decision VALUE=suspicious>
264 Add poster to watch list</INPUT>
268 NOTE: Decisions to watchlist and whitelist posters can be reversed by
269 editing the respective lists of whitelisted and watchlisted posters.
272 &link_to_help( "filter-lists", "automatic filtering and filter lists, blacklisting and preapproved threads." );
274 print "</I>You may also wish to read the <A href=\"http://www.chiark.greenend.org.uk/~webstump/g.ulm/rrtable.html\" target=\"_blank\">summary of rejection reasons</a> (opens in a new window).\n<BR><BR>
276 <INPUT TYPE=radio NAME=next_screen VALUE=single CHECKED>
277 Review ONE article in next screen
278 <INPUT TYPE=radio NAME=next_screen VALUE=multiple>
279 Review multiple articles in next screen
282 <INPUT TYPE=submit VALUE=\"Submit\">
283 <INPUT TYPE=submit NAME=skip_submit VALUE=\"Skip\">
284 <INPUT TYPE=reset VALUE=\"Reset\">
288 print "<FORM METHOD=$request_method action=$base_address>";
289 &html_print_credentials;
290 print "<INPUT NAME=action VALUE=moderator_admin TYPE=hidden>
291 <INPUT TYPE=submit VALUE=\"Go to Management Page Instead of Moderating This Post\">
293 print "<BR><A HREF=$base_address?action=change_password&newsgroup=$newsgroup&" .
294 "moderator=$moderator&password=$password>Change Password</A>";
300 # WebSTUMP administrative screen
301 sub webstump_admin_screen {
303 &verify_admin_password;
305 my $password = $request{'password'};
307 &begin_html( "WebSTUMP Administration" );
309 <FORM METHOD=$request_method action=$base_address>
310 <INPUT NAME=action VALUE=admin_add_newsgroup TYPE=hidden>
311 <INPUT NAME=password VALUE=\"$password\" TYPE=hidden>\n";
316 Create a new newsgroup on the server:<BR>
318 Newsgroup:<BR> <INPUT NAME=newsgroup_name VALUE=\"\" SIZE=50><BR>
319 Address to send approved/rejected messages <BR>
320 <INPUT NAME=newsgroup_approved_address VALUE=\"\" SIZE=30><BR>
321 Admin Password For this group:<BR> <INPUT NAME=newsgroup_password VALUE=\"\" SIZE=10><BR>
322 <INPUT TYPE=submit VALUE=\"Submit\">
323 <INPUT TYPE=reset VALUE=\"Reset\"><HR>
326 print "</FORM>\n\n<PRE>\n";
331 # WebSTUMP "add newsgroup" function
332 sub admin_add_newsgroup {
334 &verify_admin_password;
336 my $newsgroup = &required_parameter( 'newsgroup_name' );
338 $newsgroup =~ s/\///g;
339 $newsgroup = &untaint( $newsgroup );
341 my $address = &required_parameter( 'newsgroup_approved_address' );
342 my $password = &required_parameter( 'newsgroup_password' );
344 &user_error( "Newsgroup $newsgroup already exists" )
345 if defined $newsgroups_index{$newsgroup};
347 &user_error( "Password may only contain letters and digits" )
348 if( ! ($password =~ /^[a-zA-Z0-9]+$/ ) );
350 &begin_html( "WebSTUMP Administration: Newsgroup created" );
354 print "Adding $newsgroup to $webstump_home/config/newsgroups.lst...";
355 mkdir "$webstump_home/queues/$newsgroup", 0755;
358 $dir = "$webstump_home/config/newsgroups/$newsgroup";
360 print "Creating $dir...";
364 print "Creating files in $dir...";
366 &append_to_file( "$dir/address.txt", "$address\n" );
367 &append_to_file( "$dir/moderators", "ADMIN \U$password\n" );
368 &append_to_file( "$dir/rejection-reasons",
369 "offtopic::a blatantly offtopic article, spam
370 harassing::message of harassing content
371 charter::message poorly formatted
384 $web_subdir = pop( @_ );
386 $newsgroup = pop( @_ );
388 opendir( SUBDIR, $subdir );
392 while( $_ = readdir( SUBDIR ) ) {
393 my $file = "$subdir/$_";
394 next if( ! -f $file || ! -r $file );
395 my $extension = $file;
396 $extension =~ s/^.*\.//;
397 $extension = "\L$extension";
399 if( $extension eq "gif" || $extension eq "jpg" || $extension eq "jpeg" ) {
400 print "<CENTER> <IMG SRC=$base_address_for_files/queues/$newsgroup/$web_subdir/$_></CENTER><HR>\n";
404 $filename =~ s/^.*\///;
405 next if $filename eq "skeleton.skeleton"
406 || $filename eq "headers.txt"
407 || $filename eq "full_message.txt"
408 || $filename eq "text.files.lst"
409 || $filename eq "stump-prolog.txt"
410 || $filename eq "stump-warning.txt"
411 || $filename =~ /msg-.*\.doc/;
413 &print_image( "no_image.gif", "security warning" );
414 print "<B>Non-image attachment:</B><CODE>$filename</CODE> NOT SHOWN for security reasons.<BR>\n";
420 # prints warning if there is warning stored about the article
421 sub print_article_warning { # short-subdir
422 my $file = pop( @_ );
424 my $warning_file = &article_file_name( $file ) . "/stump-warning.txt";
426 if( -r $warning_file ) {
427 open( WARNING, $warning_file );
428 while ($warning = <WARNING>) {
429 next unless $warning =~ m/\S/;
430 $warning =~ s/\&/&/g;
431 $warning =~ s/</</g;
432 $warning =~ s/>/>/g;
433 &print_image( "star.gif", "warning" );
434 print "<FONT COLOR=red>$warning</FONT><br>\n";
443 sub get_queue_list ($) {
444 my ($newsgroup) = @_;
445 my $dir = "$queues_dir/$newsgroup";
448 opendir(QUEUED, $dir) or &error("could not open directory $dir");
452 my $subdir= scalar readdir(QUEUED);
453 last unless defined $subdir;
455 my $subpath= "$dir/$subdir";
456 next if $subdir =~ /^\.+/;
457 next unless -d $subpath;
459 if (!stat "$subpath/stump-warning.txt") {
460 $!==&ENOENT or die "$subpath $!";
463 $sortkey= (stat _)[9];
465 $sortkeys{$subdir}= $sortkey;
468 my @articles= sort { $sortkeys{$a} <=> $sortkeys{$b} } keys %sortkeys;
469 return ($dir, @articles);
472 # main moderation page -- multiple-articles version
473 sub html_moderation_screen {
474 my $newsgroup = &required_parameter( 'newsgroup' );
475 my $moderator = $request{'moderator'};
476 my $password = $request{'password'};
479 if( $request{'next_screen'} eq 'single' ) {
480 # we show a single article if the user so requested.
481 # just get the first article from the queue if any, otherwise show
482 # an empty main screen.
484 my ($dir, @articles)= get_queue_list($newsgroup);
487 for ($i=0; $i<@articles; $i++) {
488 my $subdir= shift @articles;
489 push @articles, $subdir;
490 last if $request{"decision_$subdir"};
493 while( $subdir = shift @articles ) {
494 if( -d "$dir/$subdir" && !($subdir =~ /^\.+/)
495 && open( PROLOG, "$dir/$subdir/stump-prolog.txt" ) ) {
496 &html_moderate_article( $subdir );
501 # otherwise just show the moderator an empty main screen.
504 &begin_html( "Main Moderation Screen: $newsgroup" );
505 print "Welcome to the main moderation screen. Its main purpose is to
506 help you process most messages extremely quickly. For every message, it
507 presents you who sent it, as well as the first three non-blank lines.
508 For those messages where the decision is obvious, simply select your
509 decision (approve/reject etc) and click submit. For those messages which
510 you would like to review in more details, do not select anything and
511 use Review/Comment function from this screen or from a subsequent screen.
512 Remember that if you do not make any decision, the article would stay in the
513 queue. See also the <A href=\"http://www.chiark.greenend.org.uk/~webstump/g.ulm/rrtable.html\" target=\"_blank\">summary of rejection reasons</a> (opens in a new window).\n";
515 &read_rejection_reasons;
517 my ($dir, @articles)= get_queue_list($newsgroup);
520 <FORM METHOD=$request_method action=$base_address>
521 <INPUT NAME=action VALUE=approval_decision TYPE=hidden>";
522 &html_print_credentials;
524 print "<HR> <INPUT TYPE=submit VALUE=Submit>
525 <INPUT TYPE=reset VALUE=Reset>
528 my $file, $subject = "No Subject", $from = "From nobody";
529 my $form_not_empty = "";
530 my $article_count = 0;
532 while( ($subdir = shift @articles) && $article_count++ < 40 ) {
534 if( -d "$dir/$subdir" && !($subdir =~ /^\.+/)
535 && open( PROLOG, "$dir/$subdir/stump-prolog.txt" ) ) {
538 if( /^Real-Subject: /i ) {
542 s/^Real-Subject: //g;
543 $subject = substr( $_, 0, 50 );
544 } elsif( /^From: /i ){
548 $from = substr( $_, 0, 50 );
554 print "<HR><B>$from: $subject</B>(";
555 print "<A HREF=$base_address?action=moderate_article&newsgroup=$newsgroup&" .
556 "moderator=$moderator&password=$password&file=$subdir>Review/Comment/Whitelist</A>)<BR>\n";
557 print "<INPUT TYPE=radio NAME=\"decision_$file\" VALUE=approve>Approve\n";
558 print "<INPUT TYPE=radio NAME=\"decision_$file\" VALUE=skip>Leave\n";
559 print "<INPUT TYPE=radio NAME=\"decision_$file\" VALUE=leave>Back of queue\n";
560 foreach (@short_rejection_reasons) {
561 print "<INPUT TYPE=radio NAME=\"decision_$file\" VALUE=\"reject $_\">Reject \u$_\n";
566 &print_article_warning( $file );
572 while( ($_ = <PROLOG>) && $i < 8 ) {
579 print "] " . substr( $_, 0, 75 ) . "\n";
585 $form_not_empty = "yes";
587 $article_count += &print_images( $newsgroup, "$dir/$subdir", $subdir );
591 if( $form_not_empty ) {
592 print "<HR> <INPUT TYPE=submit VALUE=Submit>
593 <INPUT TYPE=reset VALUE=Reset>
598 No articles present in the queue
599 <INPUT TYPE=submit VALUE=Refresh>
603 print "<A HREF=$base_address?action=change_password&newsgroup=$newsgroup&" .
604 "moderator=$moderator&password=$password>Change Password</A>";
608 print "<FORM METHOD=$request_method action=$base_address>";
609 &html_print_credentials;
610 print "<INPUT NAME=action VALUE=moderator_admin TYPE=hidden>
611 <INPUT TYPE=submit VALUE=\"Management\">
617 # prints hidden fields -- credentials
618 sub html_print_credentials {
619 my $newsgroup = $request{'newsgroup'};
620 my $moderator = $request{'moderator'};
621 my $password = $request{'password'};
624 <INPUT NAME=newsgroup VALUE=\"$newsgroup\" TYPE=hidden>
625 <INPUT NAME=moderator VALUE=\"$moderator\" TYPE=hidden>
626 <INPUT NAME=password VALUE=\"$password\" TYPE=hidden>\n";
632 my ($forwards, $gotr, $callback) = @_;
633 my $dir= "$webstump_home/..";
634 opendir LOGSDIR, "$dir" or die "$dir $!";
639 m/^errs\.(\d+)(?:\.gz$)$/ ? ($1+2) :
644 sort { $num->($a) <=> $num->($b) }
648 my $file= "$dir/$leaf";
649 if ($file =~ m/\/errs.*\.gz$/) {
650 open LOGFILE, "zcat $file | tac |" or die "zcat $file | tac $!";
651 } elsif ($file =~ /errs/) {
652 open LOGFILE, "tac $file |" or die "tac $file $!";
654 die "Unexpected filename in scanlogs: $file";
657 my $tgot= $callback->();
659 $$gotr= $tgot if $tgot > $$gotr;
662 $!=0; $?=0; close LOGFILE or die "$file $? $!";
665 closedir LOGSDIR or die "$dir $!";
668 sub html_search_logs {
669 &begin_html("Search logs for $request{'newsgroup'}");
673 if ($request{'download_logs'}) {
674 print "<h2>Complete log download</h2>\n";
676 } elsif ($request{'messagenum'} =~ m/^\s*(\d+)\s*$/) {
680 print "<h2>Log entry for single message $reqnum</h2>\n";
682 print "<h2>Log lookup - bad reference</h2>
683 Please supply the numerical reference as found in the \"recent activity\"
684 log or message headers. Reference numbers consist entirely of digits,
685 and are often quoted in message headers in [square brackets].<p>
690 if ($mod_log_access < $min) {
691 print "Not permitted [$mod_log_access<$min]. Consult administrator.\n";
697 &scanlogs($forwards, \$sofar, sub {
698 return 0 unless chomp;
699 return 0 unless m/^DECISION: /;
700 my @vals = split / \| /, $';
701 return 0 unless @vals >= 5;
703 my ($group,$dir,$act,$reason,$timet) = @vals;
704 my $date= $timet ? (strftime "%Y-%m-%d %H:%M:%S GMT", gmtime $timet)
706 return 0 unless $group eq $request{'newsgroup'};
707 return 0 unless $subj =~ m,/(\d+)$,;
709 return 0 if defined($reqnum) and $treqnum ne $reqnum;
710 print "<table rules=all><tr><th>Date<th>Reference<th>Disposal<th>Reason</tr>\n"
712 print "<tr>", (map { "<td>".escapeHTML($_) }
713 $date,$treqnum,$act,$reason);
715 return defined($reqnum) ? 2 : 1;
718 print "</table>" if $sofar;
721 print "Reference not found.".
722 " (Perhaps message has expired, or is still in the queue?)";
727 # newsgroup admin page
728 sub html_newsgroup_management {
729 &begin_html( "Administer $request{'newsgroup'}" );
731 print "All usernames and passwords are not case sensitive.\n";
732 print "<HR>Use this form to add new moderators or change passwords:<BR>
733 <FORM METHOD=$request_method action=$base_address>
734 <INPUT NAME=action VALUE=add_user TYPE=hidden>";
735 &html_print_credentials;
737 Username: <INPUT NAME=user VALUE=\"\" SIZE=20>
739 Password: <INPUT NAME=new_password VALUE=\"\" SIZE=20>
741 <INPUT TYPE=submit VALUE=\"Add/Change\">
742 <INPUT TYPE=reset VALUE=Reset>
746 print "<HR>Use this form to delete moderators:<BR>
747 <FORM METHOD=$request_method action=$base_address>
748 <INPUT NAME=action VALUE=delete_user TYPE=hidden>";
749 &html_print_credentials;
751 Username: <INPUT NAME=user VALUE=\"\" SIZE=20>
753 <INPUT TYPE=submit VALUE=\"Delete Moderator\">
754 <INPUT TYPE=reset VALUE=Reset>
757 <FORM METHOD=$request_method action=$base_address>
758 <INPUT NAME=action VALUE=edit_list TYPE=hidden>";
759 &html_print_credentials;
761 Configuration List: <SELECT NAME=list_to_edit>
763 <OPTION VALUE=good.posters.list>Good Posters List
764 <OPTION VALUE=watch.posters.list>Suspicious Posters List
765 <OPTION VALUE=watch.words.list>Suspicious Words List
768 <INPUT TYPE=submit VALUE=\"Edit\">
769 <INPUT TYPE=reset VALUE=Reset>";
771 &link_to_help( "filter-lists", "filtering lists" );
775 if ($mod_log_access) {
777 Use this form to search logs of past moderation decisions:
779 <form method=$request_method action=$base_address>
780 <input name=action value=search_logs type=hidden>";
782 &html_print_credentials;
785 Reference number: <input name=messagenum size=30>
786 <input type=submit value=\"Lookup\">";
789 <input type=submit value=\"Download all logs\" name=\"download_logs\">"
790 if $mod_log_access >= 2;
792 print "</form><hr>\n";
797 List of current moderators:<P>
801 foreach (keys %moderators) {
807 print "<HR>See the <A href=\"http://www.chiark.greenend.org.uk/~webstump/g.ulm/rrtable.html\" target=\"_blank\">summary of rejection reasons</a> (opens in a new window).\n";
809 print "<HR><FORM METHOD=$request_method action=$base_address>";
810 &html_print_credentials;
811 print "<INPUT NAME=action VALUE=moderation_screen TYPE=hidden>
812 <INPUT TYPE=submit VALUE=\"Go to moderation screen\">
820 sub edit_configuration_list {
822 my $list_to_edit = &required_parameter( 'list_to_edit' );
824 $list_to_edit = &check_config_list( $list_to_edit );
826 my $list_file = &full_config_file_name( $list_to_edit );
828 my $list_content = "";
830 if( open( LIST, $list_file ) ) {
831 $list_content .= $_ while( <LIST> );
835 $list_content =~ s/\&/&/g;
836 $list_content =~ s/</</g;
837 $list_content =~ s/>/>/g;
839 &begin_html( "Edit $list_to_edit" );
842 " <FORM METHOD=$request_method action=$base_address>
843 <INPUT NAME=action VALUE=set_config_list TYPE=hidden>
844 <INPUT NAME=list_to_edit VALUE=$list_to_edit TYPE=hidden>";
845 &html_print_credentials;
846 &link_to_help( $list_to_edit, "$list_to_edit" );
849 <TEXTAREA NAME=list rows=20 COLS=50>
850 $list_content</TEXTAREA>
853 <INPUT TYPE=submit VALUE=\"Set\">
860 # password change page
861 sub html_change_password{
862 &begin_html( "Change Password" );
864 print "All usernames and passwords are not case sensitive.\n";
865 print "<HR>Use this form to change your password:<BR>
866 <FORM METHOD=$request_method action=$base_address>
867 <INPUT NAME=action VALUE=validate_change_password TYPE=hidden>";
868 &html_print_credentials;
871 New Password: <INPUT NAME=new_password VALUE=\"\" SIZE=20>
873 <INPUT TYPE=submit VALUE=Submit>
874 <INPUT TYPE=reset VALUE=Reset>
882 # newsgroup creation form
883 sub init_request_newsgroup_creation{
884 my $newsgroup = &required_parameter( 'newsgroup' );
886 &begin_html( "Request Creation of $newsgroup" );
888 print "This page helps you ask the system administrator of your domain
889 to create <B>$newsgroup</B> on your server. Type in your domain name and
890 click SUBMIT. An email will be sent to news\@domain and usenet\@domain
891 and postmaster\@domain
892 asking them to create your newsgroup. Please do NOT abuse this system.
893 NOTE: You can give the URL of this page to your group readers so that
894 they could request creation of their newsgroups by themselves.\n";
897 <FORM METHOD=$request_method action=$base_address>
898 <INPUT NAME=action VALUE=complete_newsgroup_creation_request TYPE=hidden>\n";
899 &html_print_credentials;
902 Domain Name ONLY: <INPUT NAME=domain_name VALUE=\"\" SIZE=40>
904 <INPUT TYPE=submit VALUE=Submit>
905 <INPUT TYPE=reset VALUE=Reset>
913 # newsgroup creation completion
914 sub complete_newsgroup_creation_request{
915 my $newsgroup = &required_parameter( 'newsgroup' );
916 my $domain_name = &required_parameter( 'domain_name' );
918 if( !($domain_name =~ /(^[a-zA-Z0-9\.-_]+$)/) ) {
919 &user_error( "invalid domain name" );
925 my $request = "To: news\@$domain_name, usenet\@$domain_name, postmaster\@$domain_name
926 Subject: Please create $newsgroup (Moderated)
927 From: devnull\@algebra.com ($newsgroup Moderator)
928 Organization: stump.algebra.com
930 Dear News Administrator:
932 A user of $domain_name has requested that you create a newsgroup
934 $newsgroup (Moderated)
936 on your server. $newsgroup
937 is a legitimately created moderated newsgroup that is available worldwide.
939 Thank you very much for your help and cooperation.
943 - Moderator of $newsgroup.
947 &email_message( $request, "news\@$domain_name" );
948 &email_message( $request, "usenet\@$domain_name" );
949 &email_message( $request, "postmaster\@$domain_name" );
951 &begin_html( "Request to create $newsgroup sent" );
953 print "The following request has been sent:<HR><PRE>\n";
955 print "$request</PRE>\n";
962 my $topic_name = &required_parameter( "topic" );
964 $topic_name =~ s/\///g;
965 $topic_name =~ s/\.\.//g;
966 $topic_name = &untaint( $topic_name );
968 my $file = "$webstump_home/doc/help/$topic_name.html";
970 &error( "Topic $topic_name not found in $file." )
973 open( FILE, "$file" );
975 $help .= $_ while( <FILE> );
978 $help =~ s/##/$base_address?action=help&topic=/g;
980 &begin_html( "$topic_name" );