From 2afe376965daeefe4f8aafb0a01104098f192978 Mon Sep 17 00:00:00 2001
From: unknown
Date: Tue, 8 Oct 2002 04:12:24 +0000
Subject: [PATCH] This commit was manufactured by cvs2svn to create branch
'vogon'.
---
IcculusNews_daemon.pl | 1701 ---------------------------------------
IcculusNews_dotqmail.pl | 82 --
IcculusNews_post.pl | 125 ---
TODO | 5 -
4 files changed, 1913 deletions(-)
delete mode 100755 IcculusNews_daemon.pl
delete mode 100755 IcculusNews_dotqmail.pl
delete mode 100755 IcculusNews_post.pl
delete mode 100644 TODO
diff --git a/IcculusNews_daemon.pl b/IcculusNews_daemon.pl
deleted file mode 100755
index 7aa6662..0000000
--- a/IcculusNews_daemon.pl
+++ /dev/null
@@ -1,1701 +0,0 @@
-#!/usr/bin/perl -w -T
-#-----------------------------------------------------------------------------
-#
-# Copyright (C) 2000 Ryan C. Gordon (icculus@icculus.org)
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-#-----------------------------------------------------------------------------
-
-# !!! FIXME: Remove most of the "die()" calls.
-
-#-----------------------------------------------------------------------------
-# Revision history:
-#-----------------------------------------------------------------------------
-
-use strict; # don't touch this line, nootch.
-use warnings; # don't touch this line, either.
-use DBI; # or this. I guess. Maybe.
-#use Socket; # in fact, if it says "use", don't touch it.
-#use IO::Handle; # blow.
-
-# Version of IcculusNews. Change this if you are forking the code.
-my $version = "2.0.0beta";
-
-
-# Global rights constants.
-use constant canSeeAllQueues => 1 << 0;
-use constant canSeeAllDeleted => 1 << 1;
-use constant canSeeAllUnapproved => 1 << 2;
-use constant canDeleteAllItems => 1 << 3;
-use constant canPurgeAllItems => 1 << 4;
-use constant canApproveAllItems => 1 << 5;
-use constant canTweakUsers => 1 << 6;
-use constant canCreateQueues => 1 << 7;
-use constant canLockUsers => 1 << 8;
-use constant canLockAllQueues => 1 << 9;
-use constant canChangeOthersPasswords => 1 << 10;
-use constant canEditAllItems => 1 << 11;
-use constant canNotAuthorize => 1 << 12;
-use constant canAccessAllLockedQueues => 1 << 13;
-use constant canCreateUsers => 1 << 14;
-use constant canMoveAllItems => 1 << 15;
-
-# Queue rights constants.
-use constant canSeeInvisible => 1 << 0;
-use constant canSeeDeleted => 1 << 1;
-use constant canSeeUnapproved => 1 << 2;
-use constant canDeleteItems => 1 << 3;
-use constant canPurgeItems => 1 << 4;
-use constant canApproveItems => 1 << 5;
-use constant canEditItems => 1 << 6;
-use constant canMakeInvisible => 1 << 7;
-use constant canLockQueue => 1 << 8;
-use constant canAccessLocked => 1 << 9;
-use constant canMoveItems => 1 << 10;
-
-# Queue flags constants.
-use constant queueInvisible => 1 << 0;
-use constant queueLocked => 1 << 1;
-
-# syslog constants.
-use constant syslogNone => 0;
-use constant syslogError => 1;
-use constant syslogDaemon => 2;
-use constant syslogAuth => 3;
-use constant syslogCommand => 4;
-use constant syslogSuccess => 5;
-use constant syslogAll => 0xFFFFFFFF;
-
-#-----------------------------------------------------------------------------#
-# CONFIGURATION VARIABLES: Change to suit your needs... #
-#-----------------------------------------------------------------------------#
-
-# Set this to one to log just errors to the standard Unix syslog facility
-# (requires Sys::Syslog qw(:DEFAULT setlogsock) ...). Set it to two to also
-# log daemon start/stop info. Three logs all auth attempts. Set it to four to
-# also log all news commands sent by a client. Set it to zero to disable.
-# (see constants, above)
-my $use_syslog = syslogDaemon;
-
-# Set this to name of your site. Some daemon messages and forgotten password
-# emails will include it.
-my $sitename = 'icculus.org';
-
-# Set this to the email address for the guy that takes care of problems.
-# Some error messages will include it.
-my $admin_email = 'newsmaster@icculus.org';
-
-# Set this to the number of seconds you'd like to delay before responding to
-# an incorrect authentication. The longer the delay, the more you frustrate
-# crackers that are trying to brute-force their way into someone else's
-# login. Then again, the longer the delay, the more you frustrate your valid
-# users when they mistype their passwords. 2 seconds seems to be a good
-# compromise. This must be an integer value; no fractions, please.
-my $invalid_auth_delay = 2;
-
-# This is the maximum size, in bytes, that a command can be. This is
-# to prevent malicious clients from trying to fill all of system memory.
-my $max_command_size = 256;
-
-# This is the maximum size, in bytes, that a news entry can be when submitted
-# through this daemon. This is to prevent malicious clients from trying to
-# fill all of system memory. Make this big, though. Stuff in the database
-# is free game; there is no size limit on what is read back from there, since
-# we assume that data can be trusted.
-my $max_news_size = 64 * 1024;
-
-# This is the name of your anonymous account.
-my $anon = "anonymous hoser";
-
-# You can screw up your output with this, if you like.
-# (Not used at the moment, check syslog instead.)
-my $debug = 0;
-
-# The processes path is replaced with this string, for security reasons, and
-# to satisfy the requirements of Taint mode. Make this as simple as possible.
-my $safe_path = '/usr/bin:/usr/local/bin';
-
-# Turn the process into a daemon. This will handle creating/answering socket
-# connections, and forking off children to handle them. This flag can be
-# toggled via command line options (--daemonize, --no-daemonize, -d), but
-# this sets the default. Daemonizing tends to speed up processing (since the
-# script stays loaded/compiled), but may cause problems on systems that
-# don't have a functional fork() or IO::Socket::INET package. If you don't
-# daemonize, this program reads requests from stdin and writes results to
-# stdout, which makes it suitable for command line use or execution from
-# inetd and equivalents.
-my $daemonize = 0;
-
-# This is only used when daemonized. Specify the port on which to listen for
-# incoming connections. The randomly-chosen "official" IcculusNews port is
-# currently 263. Hopefully this won't have to change.
-my $server_port = 263;
-
-# Set this to immediately drop priveledges by setting uid and gid to these
-# values. Set to undef to not attempt to drop privs. You can keep the privs
-# by setting these to undef (risky!), if you really want to.
-#my $wanted_uid = undef;
-#my $wanted_gid = undef;
-my $wanted_uid = 1083; # (This is the uid of "iccnews" ON _MY_ SYSTEM.)
-my $wanted_gid = 1006; # (This is the gid of "iccnews" ON _MY_ SYSTEM.)
-
-# This is only used when daemonized. Specify the maximum number of clients
-# to service at once. A separate child process is fork()ed off for each
-# client, and if there are more simulatenous connections then this value, the
-# extra clients will be made to wait until some of the current requests are
-# serviced. 5 to 10 is usually a good number. Set it higher if you get a
-# massive amount of finger requests simultaneously.
-my $max_connects = 10;
-
-# This is how long, in seconds, before an idle connection will be summarily
-# dropped. This prevents abuse from people hogging a connection without
-# actually sending a request, without this, enough connections like this
-# will block legitimate ones. At worst, they can only block for this long
-# before being booted and thus freeing their connection slot for the next
-# guy in line. Setting this to undef lets people sit forever, but removes
-# reliance on the IO::Select package. Note that this timeout is how long
-# the user has to complete the read_from_client() function, so don't set
-# it so low that legitimate lag can kill them. The default is usually safe.
-my $read_timeout = 15;
-
-# This is the base directory for writing RDF files to. Make sure that this
-# process has write access and that there's a dir separator at the end!
-my $rdfbase = '/webspace/rdf/';
-
-# New users are assigned these rights by default. Refer to "Global rights
-# constants", above. If you want to lock out new accounts until you manually
-# approve them, "canNotAuthorize" is appropriate. If you want anyone to be
-# able to create personal news queues without running it by you first,
-# "canCreateQueues" is a good idea.
-my $default_user_rights = canCreateQueues | canCreateUsers;
-
-# This is the same as $default_user_rights, but for the anonymous account.
-# If you want to lock out new users altogether, don't set canCreateUsers
-# here; this way account creation has to go through users you have
-# authorized to create accounts, which is militant, but potentially useful.
-my $anonymous_user_rights = canCreateUsers;
-
-# Owners of a queue, when initially creating the queue, are assigned these
-# rights by default. Refer to "Queue rights constants", above. You probably
-# want to give them everything. These rights only apply to the queue creator
-# when interacting with her own queue.
-my $default_queue_owner_rights = canSeeInvisible | canSeeDeleted |
- canSeeUnapproved | canDeleteItems |
- canPurgeItems | canApproveItems |
- canEditItems | canMakeInvisible |
- canLockQueue | canAccessLocked;
-
-# New queues are assigned these flags by default. Refer to "Queue flags
-# constants", above. This should probably be left at zero, unless you want
-# to make queues globally invisible until the creator toggles them.
-my $default_queue_flags = 0;
-
-# Newly created users are assigned to this queue by default. The first queue
-# created is 1, so that's probably a good one, unless you've got some other
-# queue you prefer. Users can change to a different queue via the QUEUE
-# command, and assign a new default queue with the SETDEFAULTQUEUE command.
-# If the default queue is 0, the web interface takes users to the "post"
-# action by default, instead of the queue view.
-my $default_queue = 0;
-
-# This is the minimum number of characters that will be used when generating
-# a new password to replace a forgotten one. Eight is usually reasonable.
-my $forgotten_password_minsize = 8;
-
-# This is the maximum number of characters that will be used when generating
-# a new password to replace a forgotten one. Ten to twelve is usually
-# reasonable.
-my $forgotten_password_maxsize = 12;
-
-# Set this to the name of a device to read random data from. If you don't have
-# such a device (not on a Unix box or something), set it to undef to just
-# use the built-in rand() function.
-my $random_device = '/dev/urandom';
-
-# This is the host to connect to for database access.
-my $dbhost = 'localhost';
-
-# This is the username for the database connection.
-my $dbuser = 'newsmgr';
-
-# The database password can be entered in three ways: Either hardcode it into
-# $dbpass, (which is a security risk, but is faster if you have a completely
-# closed system), or leave $dbpass set to undef, in which case this script
-# will try to read the password from the file specified in $dbpassfile (which
-# means that this script and the database can be touched by anyone with read
-# access to that file), or leave both undef to have DBI get the password from
-# the DBI_PASS environment variable, which is the most secure, but least
-# convenient.
-my $dbpass = undef;
-my $dbpassfile = '/etc/IcculusNews_dbpass.txt';
-
-# The name of the database to use once connected to the database server.
-my $dbname = 'IcculusNews';
-
-# Names of database tables.
-my $dbtable_users = 'news_users';
-my $dbtable_queues = 'news_queues';
-my $dbtable_items = 'news_items';
-my $dbtable_queue_rights = 'news_queue_rights';
-
-
-#-----------------------------------------------------------------------------#
-# The rest is probably okay without you laying yer dirty mits on it. #
-#-----------------------------------------------------------------------------#
-
-my $link = undef; # link to database.
-my $auth_uid = undef; # authenticated user id.
-my $ipaddr = undef; # IP address of client.
-my $queue = 0;
-my $current_global_rights = 0;
-my $current_queue_rights = 0;
-my %commands;
-
-
-sub long2ip {
- my $l = shift;
- my $x1 = (($l & 0xFF000000) >> 24);
- my $x2 = (($l & 0x00FF0000) >> 16);
- my $x3 = (($l & 0x0000FF00) >> 8);
- my $x4 = (($l & 0x000000FF) >> 0);
- return("$x1.$x2.$x3.$x4");
-}
-
-
-sub do_log {
- my $level = shift;
- my $text = shift;
-
- if ($use_syslog >= $level) {
- syslog("info", "$text\n")
- or report_fatal("Couldn't write to syslog: $!");
- }
-}
-
-
-my $in_error_handler = 0;
-sub handle_error {
- my ($errmsg, $fatal) = @_;
-
- print "- $errmsg\012";
-
- if (not $in_error_handler) {
- $in_error_handler = 1;
- do_log(syslogError, "IcculusNews error: \"$errmsg\"");
- $in_error_handler = 0;
- }
-
- if ($fatal) {
- $link->disconnect() if defined $link;
- exit 42;
- }
-}
-
-
-sub report_error {
- handle_error($_[0], 0);
-}
-
-
-sub report_fatal {
- handle_error($_[0], 1);
-}
-
-
-sub report_success {
- my $errmsg = shift;
- do_log(syslogSuccess, "IcculusNews success: \"$errmsg\"");
- print "+ $errmsg\012";
-}
-
-
-sub new_crypt_salt {
- return(join('', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand(64), rand(64)]));
-}
-
-
-sub get_database_link {
- if (not defined $link) {
- if (not defined $dbpass) {
- if (defined $dbpassfile) {
- open(FH, $dbpassfile)
- or report_fatal("failed to open $dbpassfile: $!");
- $dbpass = ;
- chomp($dbpass);
- $dbpass =~ s/\A\s*//;
- $dbpass =~ s/\s*\Z//;
- close(FH);
- }
- }
-
- my $dsn = "DBI:mysql:database=$dbname;host=$dbhost";
- $link = DBI->connect($dsn, $dbuser, $dbpass)
- or report_fatal(DBI::errstr);
- }
-
- return($link);
-}
-
-
-sub read_from_client {
- my $max_chars = shift;
- my $retval = '';
- my $count = 0;
- my $s = undef;
- my $elapsed = undef;
- my $starttime = undef;
-
- if (defined $read_timeout) {
- $s = new IO::Select();
- $s->add(fileno(STDIN));
- $starttime = time();
- $elapsed = 0;
- }
-
- while (1) {
- if (defined $read_timeout) {
- my $ready = scalar($s->can_read($read_timeout - $elapsed));
- report_fatal("input timeout.") if (not $ready);
- $elapsed = (time() - $starttime);
- }
-
- my $ch;
- my $rc = sysread(STDIN, $ch, 1);
- report_fatal("unexpected EOF.") if ($rc != 1);
- if ($ch ne "\015") {
- return($retval) if ($ch eq "\012");
- $retval .= $ch;
- $count++;
- report_fatal("input overflow. chatter less.") if ($count >= $max_chars);
- }
- }
-
- return(undef); # shouldn't ever hit this.
-}
-
-
-sub process_command {
- my $req = shift;
- my $cmdstr = read_from_client($max_command_size);
- my ($cmd, $args) = $cmdstr =~ /\A\s*([a-zA-Z]+)\s*(.*)\Z/;
-
- $args = undef if ((defined $args) and ($args eq ''));
-
- if (not defined $cmd) {
- $cmd = '';
- } else {
- $cmd =~ tr/a-z/A-Z/;
- }
-
- report_fatal("Required $req") if ((defined $req) and ($req ne $cmd));
- report_success("Uh, okay."), return 1 if ($cmd eq ''); # blank line.
-
- do_log(syslogCommand, "IcculusNews command: \"$cmdstr\"");
-
- if (defined $commands{$cmd}) {
- return($commands{$cmd}->($args));
- }
-
- report_error("Unknown command \"$cmd\".");
- return(1);
-}
-
-sub update_queue_rights {
- $current_queue_rights = shift;
-
- if ($current_global_rights & canSeeAllDeleted) {
- $current_queue_rights |= canSeeDeleted;
- }
-
- if ($current_global_rights & canSeeAllUnapproved) {
- $current_queue_rights |= canSeeUnapproved;
- }
-
- if ($current_global_rights & canDeleteAllItems) {
- $current_queue_rights |= canDeleteItems;
- }
-
- if ($current_global_rights & canPurgeAllItems) {
- $current_queue_rights |= canPurgeItems;
- }
-
- if ($current_global_rights & canApproveAllItems) {
- $current_queue_rights |= canApproveItems;
- }
-
- if ($current_global_rights & canEditAllItems) {
- $current_queue_rights |= canEditItems;
- }
-
- if ($current_global_rights & canSeeAllQueues) {
- $current_queue_rights |= canSeeInvisible;
- }
-
- if ($current_global_rights & canLockAllQueues) {
- $current_queue_rights |= canLockQueue;
- }
-
- if ($current_global_rights & canAccessAllLockedQueues) {
- $current_queue_rights |= canAccessLocked;
- }
-
- if ($current_global_rights & canMoveAllItems) {
- $current_queue_rights |= canMoveItems;
- }
-}
-
-
-sub generate_rdf {
- my $qid = shift;
- my $max = shift;
-
- $qid = $queue if not defined $qid;
- return ('bogus queue id', undef, undef) if ($qid <= 0);
-
- my $sql;
- my $link = get_database_link();
- my @row = undef;
- my $sth = undef;
- $sql = "select name, description, itemarchiveurl, itemviewurl, rdffile," .
- " siteurl, rdfurl, rdfimageurl, rdfitemcount" .
- " from $dbtable_queues where id=$qid";
- $sth = $link->prepare($sql);
- $sth->execute() or die "can't execute the query: $sth->errstr";
- @row = $sth->fetchrow_array();
- $sth->finish();
- return ('failed to read queue attributes', undef, undef) if (not @row);
-
- my $queuename = $row[0];
- my $queuedesc = $row[1];
- my $itemarcurl = $row[2];
- my $itemviewurl = $row[3];
- my $rdffile = $row[4];
- my $siteurl = $row[5];
- my $rdfurl = $row[6];
- my $rdfimgurl = $row[7];
- $max = $row[8] if not defined $max;
-
- $sql = "select t1.author, t1.id, t1.title, t1.postdate, t2.name," .
- " t1.ip, t1.approved, t1.deleted" .
- " from $dbtable_items as t1" .
- " left outer join $dbtable_users as t2" .
- " on t1.author=t2.id" .
- " where t1.queueid=$queue" .
- " and t1.approved=1 and t1.deleted=0" .
- " order by postdate desc limit $max";
-
- $sth = $link->prepare($sql);
- $sth->execute() or die "can't execute the query: $sth->errstr";
-
- my $rdf = <<__EOF__;
-
-
-
-
-
- $queuename
- $siteurl
- $itemarcurl
- $queuedesc
-
-
-__EOF__
-
- if (defined $rdfimgurl) {
- $rdf .= <<__EOF__;
-
- $queuename
- $rdfimgurl
- $siteurl
-
-
-__EOF__
- }
-
- while (my @row = $sth->fetchrow_array()) {
- my $authorid = $row[0];
- my $itemid = $row[1];
- my $itemtitle = $row[2];
- my $itempostdate = $row[3];
- my $authorname = ((not defined $row[4]) ? $anon : $row[4]);
- my $ipaddr = long2ip($row[5]);
- my $approved = $row[6];
- my $deleted = $row[7];
- my $viewurl = $itemviewurl;
- 1 while ($viewurl =~ s/\%id/$itemid/);
-
- $rdf .= " \n";
- $rdf .= " $itemtitle\n";
- $rdf .= " $viewurl\n";
- $rdf .= " $authorname\n";
- $rdf .= " $authorid\n";
- $rdf .= " $itemid\n";
- $rdf .= " $itempostdate\n";
- $rdf .= " $ipaddr\n";
- $rdf .= " $approved\n";
- $rdf .= " $deleted\n";
- $rdf .= " \n";
- }
- $sth->finish();
-
- $rdf .= "\n\n";
- return(undef, $rdf, $rdffile);
-}
-
-
-sub update_rdf {
- my ($err, $rdf, $filename) = generate_rdf();
- do_log(syslogError, "RDF build failed: $err"), return 0 if (defined $err);
-
- $filename ="$rdfbase$filename";
- if (not open(RDF, '>', $filename)) {
- do_log(syslogError, "Failed to open $filename: $!");
- return 0;
- }
-
- print RDF $rdf;
- close(RDF);
- return 1;
-}
-
-
-sub toggle_approve {
- my $id = shift;
- my $newval = shift;
- if ((not defined $id) or ($id !~ /\A\d+\Z/)) {
- report_error('argument must be number.');
- return 1;
- }
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- if (!($current_queue_rights & canApproveItems)) {
- report_error("You don't have permission to do that.");
- return 1;
- }
-
- $newval = 1 if $newval; # make sure it's '1', as opposed to non-zero.
- my $otherval = (($newval) ? 0 : 1);
-
- my $link = get_database_link();
- my $sql = "update $dbtable_items set approved=$newval" .
- " where id=$id and queueid=$queue and" .
- " deleted=0 and approved=$otherval";
-
- my $rc = $link->do($sql);
- if (not defined $rc) {
- report_error("can't execute the query: $link->errstr");
- } elsif ($rc > 0) {
- report_success("Approve flag toggled.");
- update_rdf();
- } else {
- my $reason = "no idea why";
- $sql = "select approved, deleted from $dbtable_items" .
- " where id=$id and queueid=$queue";
- my $sth = $link->prepare($sql);
- $sth->execute() or die "can't execute the query: $sth->errstr";
- my @row = $sth->fetchrow_array();
- if (not @row) {
- $reason = "no such item";
- } else {
- if ($row[0] == $newval) {
- $reason = "already set like that";
- } elsif ($row[1]) {
- $reason = "item is flagged for deletion";
- }
- }
- $sth->finish();
- report_error("Failed to toggle approval flag: $reason.");
- }
- return(1);
-}
-
-
-sub toggle_delete {
- my $id = shift;
- my $newval = shift;
- if ((not defined $id) or ($id !~ /\A\d+\Z/)) {
- report_error('argument must be number.');
- return 1;
- }
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- if (!($current_queue_rights & canDeleteItems)) {
- report_error("You don't have permission to do that.");
- return(1);
- }
-
- $newval = 1 if $newval; # make sure it's '1', as opposed to non-zero.
- my $otherval = (($newval) ? 0 : 1);
-
- my $link = get_database_link();
- my $sql = "update $dbtable_items set deleted=$newval" .
- " where id=$id and queueid=$queue and deleted=$otherval";
-
- my $rc = $link->do($sql);
- if (not defined $rc) {
- report_error("can't execute: $link->errstr");
- } elsif ($rc > 0) {
- report_success("Deletion flag toggled.");
- update_rdf();
- } else {
- my $reason = "no idea why";
- $sql = "select deleted from $dbtable_items" .
- " where id=$id and queueid=$queue";
- my $sth = $link->prepare($sql);
- $sth->execute() or die "can't execute the query: $sth->errstr";
- my @row = $sth->fetchrow_array();
- if (not @row) {
- $reason = "no such item";
- } else {
- if ($row[0] == $otherval) {
- $reason = "already set like that";
- }
- }
- $sth->finish();
- report_error("Failed to toggle deletion flag: $reason.");
- }
- return(1);
-}
-
-
-sub queue_is_forbidden {
- my $queueflags = shift;
- my $userrights = shift;
- my $owner = shift;
-
- #return 0 if ((defined $owner) and ($owner == $auth_uid));
-
- if ($queueflags & queueInvisible) {
- if (!($current_global_rights & canSeeAllQueues)) {
- if (defined $userrights) {
- return 1 if (!($userrights & canSeeInvisible));
- }
- }
- }
-
- if ($queueflags & queueLocked) {
- if (!($current_global_rights & canAccessAllLockedQueues)) {
- if (defined $userrights) {
- return 1 if (!($userrights & canAccessLocked));
- }
- }
- }
-
- return 0; # it's kosher.
-}
-
-
-sub change_queue {
- my $args = shift;
-
- if ($args == 0) {
- $queue = 0;
- update_queue_rights(0);
- } else {
- my $link = get_database_link();
- my $sql = "select q.flags, r.rights, q.owner" .
- " from $dbtable_queues as q" .
- " left outer join $dbtable_queue_rights as r" .
- " on r.qid=q.id and r.uid=$auth_uid" .
- " where q.id=$args";
-
- my $sth = $link->prepare($sql);
- $sth->execute() or report_fatal("can't execute query: $sth->errstr");
- my @row = $sth->fetchrow_array();
- $sth->finish();
-
- $row[1] = 0 if ((@row) and (not defined $row[1]));
-
- if ((not @row) or (queue_is_forbidden($row[0], $row[1], $row[2]))) {
- return("Can't select that queue.");
- } else {
- update_queue_rights($row[1]);
- $queue = $args;
- }
- }
-
- return(undef); # no error.
-}
-
-
-sub can_change_queue {
- my $newqueue = shift;
-
- my $starting_queue = $queue;
- my $starting_queue_rights = $current_queue_rights;
- my $err = change_queue($newqueue);
-
- # set this directly back.
- $queue = $starting_queue;
- $current_queue_rights = $starting_queue_rights;
- return($err);
-}
-
-
-sub send_forgotten_password {
- my ($user, $email, $pword) = @_;
-
- $email = $1 if ($email =~ /\A(.*)\Z/); # untaint email address var.
-
- my $msg = <<__EOF__;
-From: $admin_email
-Reply-To: $admin_email
-To: $email
-Subject: Forgotten IcculusNews password.
-
-Hello, $user.
-
- This is the IcculusNews daemon at $sitename. Someone, possibly you, has
- told us that the account password associated with this email address has
- been forgotten. In response, we have chosen a new password for the account.
- If it wasn't you, don't worry; the smart-ass who entered the forgotten
- password request does not have your newly-generated password, unless they
- are reading this email.
-
- Please log in to IcculusNews with the following password and change it to
- something else. The sooner the better, too, since this email was probably
- sent unencrypted across the Internet, and we're paranoid about wiretaps and
- packet sniffers.
-
- Username : $user
- New Password : $pword
-
---The McManagement, $sitename.
- $admin_email
-
-
-__EOF__
-
- open(MAILH, '|/usr/sbin/sendmail -t') or
- return("Failed to run qmail-inject: $!");
-
- if ( (not print MAILH $msg) or (not close(MAILH)) ) {
- my $err = "Failed to write to qmail-inject pipe; $!";
- close(MAILH);
- return($err);
- }
-
- return(undef); # no error.
-}
-
-
-sub generate_pword {
- my $retval = '';
- my $diff = $forgotten_password_maxsize - $forgotten_password_minsize;
- my $pwordbytes = $forgotten_password_minsize + int(rand($diff + 1));
-
- my $dev = ((defined $random_device) and (open(RANDH, '<', $random_device)));
- while ($pwordbytes > 0) {
- my $idx = int((($dev) ? 62.0 * ord(getc(RANDH)) / 256.0 : rand(62)));
- $retval .= (0..9, 'A'..'Z', 'a'..'z')[$idx];
- $pwordbytes--;
- }
-
- close(RANDH) if ($dev);
- return($retval);
-}
-
-
-# The actual commands the daemon responds to...
-
-$commands{'AUTH'} = sub {
- my $args = shift;
- my $authuser;
-
- if ((defined $args) and ($args eq '-')) {
- $authuser = "anonymous account";
- $auth_uid = 0;
- $current_queue_rights = 0;
- $current_global_rights = $anonymous_user_rights;
- } else {
- my ($user, $pass) = (undef, undef);
- if (defined $args) {
- ($user, $pass) = $args =~ /\A\"(.+?)\"\s*\"(.+?)\"\Z/
- }
-
- if ((not defined $user) or (not defined $pass)) {
- report_error('USAGE: AUTH <"user"> <"password">');
- return(1);
- }
-
- $authuser = "\"$user\"";
-
- my $link = get_database_link();
-
- my $u = $link->quote($user);
- my $sql = "select id, password, globalrights, defaultqueue" .
- " from $dbtable_users where name=$u";
- my $sth = $link->prepare($sql);
- $sth->execute() or report_fatal("can't execute query: $sth->errstr");
-
- my @row = $sth->fetchrow_array();
- $sth->finish();
-
- if ((not @row) or (crypt($pass, $row[1]) ne $row[1])) {
- sleep($invalid_auth_delay);
- report_error("Authorization for $authuser failed.");
- return(1);
- }
-
- if ($row[2] & canNotAuthorize) {
- report_error("This account has been disabled.");
- return(1);
- }
-
- $auth_uid = $row[0];
- $current_global_rights = $row[2];
- my $err = change_queue($row[3]);
- if (defined $err) {
- report_error("Failed to select default queue: $err");
- return(1);
- }
- }
-
- do_log(syslogAuth, "IcculusNews auth: $authuser (id $auth_uid)");
-
- report_success("$auth_uid, $queue");
- return(1);
-};
-
-
-$commands{'USERINFO'} = sub {
- report_success("$auth_uid, $queue");
- return 1;
-};
-
-
-$commands{'QUEUEINFO'} = sub {
- my $id = shift;
- if ((not defined $id) or ($id !~ /\A\d+\Z/)) {
- report_error('argument must be number.');
- return 1;
- }
-
- my $link = get_database_link();
- my $sql = "select q.name, q.description, q.itemarchiveurl," .
- " q.itemviewurl, q.siteurl, q.rdfurl," .
- " q.created, q.owner, u.name, q.flags, r.rights" .
- " from $dbtable_queues as q, $dbtable_users as u" .
- " left outer join $dbtable_queue_rights as r" .
- " on r.qid=q.id and r.uid=$auth_uid" .
- " where q.id=$id and q.owner=u.id";
- my $sth = $link->prepare($sql);
- $sth->execute() or report_fatal("can't execute query: $sth->errstr");
- my @row = $sth->fetchrow_array();
- $sth->finish();
-
- $row[10] = 0 if ((@row) and (not defined $row[1]));
- if ((not @row) or (queue_is_forbidden($row[9], $row[10], $row[7]))) {
- report_error("Can't select that queue.");
- return 1;
- }
-
- report_success("Here comes ...");
- print("$row[0]\012");
- print("$row[1]\012");
- print("$row[2]\012");
- print("$row[3]\012");
- print("$row[4]\012");
- print("$row[5]\012");
- print("$row[6]\012");
- print("$row[7]\012");
- print("$row[8]\012");
- return 1;
-};
-
-
-$commands{'QUEUE'} = sub {
- my $args = shift;
- if ((not defined $args) or ($args !~ /\A\d+\Z/)) {
- report_error("Argument must be a number.");
- } else {
- my $err = change_queue($args);
- if (defined $err) {
- report_error($err);
- } else {
- report_success("Queue changed");
- }
- }
-
- return(1);
-};
-
-
-$commands{'ENUM'} = sub {
- my $args = shift;
- my $type = undef;
- my $link;
-
- ($type, $args) = $args =~ /\A(queues)\s*(.*)\Z/i if defined $args;
- if (not defined $type) {
- report_error("USAGE: ENUM ");
- return(1);
- }
-
- $link = get_database_link();
-
- $type =~ tr/A-Z/a-z/;
- if ($type eq "queues") {
- my $sql = "select q.id, q.name, q.flags, r.rights, q.owner" .
- " from $dbtable_queues as q" .
- " left outer join $dbtable_queue_rights as r" .
- " on r.qid=q.id and r.uid=$auth_uid";
-
- my $sth = $link->prepare($sql);
- $sth->execute() or report_fatal("can't execute query: $sth->errstr");
-
- report_success("Here comes...");
- while (my @row = $sth->fetchrow_array()) {
- $row[3] = 0 if (not defined $row[3]);
- next if (queue_is_forbidden($row[2], $row[3], $row[4]));
- print("$row[0]\012");
- print("$row[1]\012");
- }
- print(".\012");
- $sth->finish();
- }
-
- return(1);
-};
-
-
-$commands{'DIGEST'} = sub {
- my $max = shift;
- if ((not defined $max) or ($max !~ /\A\d+\Z/)) {
- report_error('argument must be number.');
- return 1;
- }
-
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- my $link = get_database_link();
- my $sql = "select i.id, i.title, i.postdate, i.author, u.name, i.ip," .
- " i.approved, i.deleted" .
- " from $dbtable_items as i" .
- " left outer join $dbtable_users as u" .
- " on i.author=u.id" .
- " where i.queueid=$queue";
-
- if (!($current_queue_rights & canSeeDeleted)) {
- $sql = $sql . ' and (i.deleted=0)';
- }
-
- if (!($current_queue_rights & canSeeUnapproved)) {
- $sql = $sql . ' and (i.approved=1)';
- }
-
- $sql .= " order by postdate desc limit $max";
-
- my $sth = $link->prepare($sql);
- $sth->execute() or die "can't execute the query: $sth->errstr";
- report_success("here comes ...");
- while (my @row = $sth->fetchrow_array()) {
- $row[4] = $anon if (not defined $row[4]);
- $row[5] = long2ip($row[5]);
- foreach (@row) {
- print("$_\012");
- }
- }
- print(".\012");
- $sth->finish();
-
- return(1);
-};
-
-
-$commands{'GET'} = sub {
- my $id = shift;
- if ((not defined $id) or ($id !~ /\A\d+\Z/)) {
- report_error('argument must be number.');
- return 1;
- }
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- my $link = get_database_link();
- my $sql = "select i.title, i.postdate, i.author, u.name, i.ip," .
- " i.approved, i.deleted, i.text" .
- " from $dbtable_items as i" .
- " left outer join $dbtable_users as u" .
- " on i.author=u.id" .
- " where i.id=$id and i.queueid=$queue";
-
- if (!($current_queue_rights & canSeeDeleted)) {
- $sql = $sql . ' and (i.deleted=0)';
- }
-
- if (!($current_queue_rights & canSeeUnapproved)) {
- $sql = $sql . ' and (i.approved=1)';
- }
-
- $sql = $sql . ' limit 1';
-
- #print("sql is [$sql].\n");
-
- my $sth = $link->prepare($sql);
- $sth->execute() or die "can't execute the query: $sth->errstr";
- my @row = $sth->fetchrow_array();
- if (not @row) {
- report_error('no such news item')
- } else {
- $row[3] = $anon if (not defined $row[3]);
- $row[4] = long2ip($row[4]);
- 1 while $row[7] =~ s/^\.$/../m;
- report_success('here comes ...');
- foreach (@row) {
- print("$_\012");
- }
- print(".\012");
- }
- $sth->finish();
-
- return(1);
-};
-
-
-$commands{'MOVEITEM'} = sub {
- my $args = shift;
- my $id;
- my $newqueue;
-
- ($id, $newqueue) = $args =~ /\A(\d+)\s+(\d+)\s*\Z/ if (defined $args);
- if ((not defined $id) or (not defined $newqueue)) {
- report_error('USAGE: MOVEITEM ');
- return 1;
- }
-
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- if (!($current_queue_rights & canMoveItems)) {
- report_error("You don't have permission to do that.");
- return(1);
- }
-
- my $err = can_change_queue($newqueue);
- report_error($err), return 1 if defined $err;
-
- my $link = get_database_link();
- my $sql = "update $dbtable_items" .
- " set queueid=$newqueue, deleted=0, approved=0" .
- " where id=$id and queueid=$queue";
-
- my $rc = $link->do($sql);
- if (not defined $rc) {
- report_error("can't execute: $link->errstr");
- } elsif ($rc > 0) {
- report_success("Moved.");
- } else {
- my $reason = "no idea why";
- $sql = "select id from $dbtable_items" .
- " where id=$id and queueid=$queue";
- my $sth = $link->prepare($sql);
- $sth->execute() or die "can't execute the query: $sth->errstr";
- my @row = $sth->fetchrow_array();
- if (not @row) {
- $reason = "no such item";
- }
- $sth->finish();
- report_error("Failed to move: $reason.");
- }
- return(1);
-};
-
-
-$commands{'POST'} = sub {
- my $title = shift;
- my $bytes_left = $max_news_size;
- my $text = '';
- my $input = '';
-
- report_error('Usage: POST '), return 1 if not defined $title;
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- report_success("You've got $bytes_left bytes; Go, hose.");
-
- while (1) {
- $input = read_from_client($bytes_left);
- last if $input eq '.';
- $input =~ s/\A\.\././;
- $text .= $input . "\012";
- $bytes_left -= (length($input) + 1);
- }
-
- my $link = get_database_link();
- $title = $link->quote($title);
- $text = $link->quote($text);
- my $sql = "insert into $dbtable_items" .
- " (queueid, ip, title, text, author, postdate)" .
- " values ($queue, $ipaddr, $title, $text, $auth_uid, NOW())";
-
- #print("sql is [$sql].\n");
-
- if (not defined $link->do($sql)) {
- report_error("can't execute the query: $link->errstr");
- } else {
- report_success("Posted, and awaiting approval.");
- update_rdf();
- }
- return(1);
-};
-
-
-$commands{'EDIT'} = sub {
- my $args = shift;
- my $bogus = 1;
- my $id;
- my $title;
-
- if (defined $args) {
- ($id, $title) = ($args =~ /\A\s*?(\d+)\s+(.+)\s*\Z/);
- $bogus = 0 if ((defined $id) and (defined $title));
- }
- report_error('Usage: EDIT '), return 1 if ($bogus);
-
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- if (!($current_queue_rights & canEditItems)) {
- report_error('permission denied.');
- return 1;
- }
-
- my $bytes_left = $max_news_size;
- my $text = '';
- my $input = '';
-
- report_success("You've got $bytes_left; Go, hose.");
-
- while (1) {
- $input = read_from_client($bytes_left);
- last if $input eq '.';
- $input =~ s/\A\.\././;
- $text .= $input . "\012";
- $bytes_left -= (length($input) + 1);
- }
-
- my $link = get_database_link();
- $title = $link->quote($title);
- $text = $link->quote($text);
- my $sql = "update $dbtable_items set title=$title, text=$text" .
- " where id=$id and queueid=$queue";
-
- if (!($current_queue_rights & canEditItems)) {
- $sql .= " and author=$auth_uid";
- }
-
- #print("sql is [$sql].\n");
-
- my $rc = $link->do($sql);
- if (not defined $rc) {
- report_error("can't execute the query: $link->errstr");
- } elsif ($rc > 0) {
- report_success("Edited.");
- update_rdf();
- } else {
- report_error("failed; maybe you don't own that item or it's missing?");
- }
- return(1);
-};
-
-$commands{'APPROVE'} = sub {
- my $id = shift;
- return(toggle_approve($id, 1));
-};
-
-
-$commands{'UNAPPROVE'} = sub {
- my $id = shift;
- return(toggle_approve($id, 0));
-};
-
-
-$commands{'DELETE'} = sub {
- my $id = shift;
- return(toggle_delete($id, 1));
-};
-
-
-$commands{'UNDELETE'} = sub {
- my $id = shift;
- return(toggle_delete($id, 0));
-};
-
-
-$commands{'PURGE'} = sub {
- my $id = shift;
- if ((not defined $id) or ($id !~ /\A\d+\Z/)) {
- report_error('argument must be number.');
- return 1;
- }
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- if (!($current_queue_rights & canPurgeItems)) {
- report_error("You don't have permission to do that.");
- return(1);
- }
-
- my $link = get_database_link();
- my $sql = "delete from $dbtable_items" .
- " where id=$id and queueid=$queue and deleted=1";
-
- my $rc = $link->do($sql);
- if (not defined $rc) {
- report_error("can't execute: $link->errstr");
- } elsif ($rc > 0) {
- report_success("Purged.");
- } else {
- my $reason = "no idea why";
- $sql = "select deleted from $dbtable_items" .
- " where id=$id and queueid=$queue";
- my $sth = $link->prepare($sql);
- $sth->execute() or die "can't execute the query: $sth->errstr";
- my @row = $sth->fetchrow_array();
- if (not @row) {
- $reason = "no such item";
- } else {
- if (!$row[0]) {
- $reason = "not flagged for deletion";
- }
- }
- $sth->finish();
- report_error("Failed to purge: $reason.");
- }
- return(1);
-};
-
-
-$commands{'PURGEALL'} = sub {
- report_error('no queue selected.'), return 1 if $queue == 0;
-
- my $link = get_database_link();
- my $sql = "delete from $dbtable_items where queueid=$queue and deleted=1";
- my $rc = $link->do($sql);
- if (not defined $rc) {
- report_error("can't execute: $link->errstr");
- } else {
- report_success("Purged $rc items.");
- }
-
- return(1);
-};
-
-
-$commands{'CREATEUSER'} = sub {
- my $args = shift;
- my $uname;
- my $email;
- my $pword;
-
- if ((defined $args) and ($args =~ /\A\"(.+?)\"\s*\"(.+?)\"\s*\"(.+?)\"\Z/)) {
- $uname = $1;
- $email = $2;
- $pword = $3;
- } else {
- report_error('Usage: <"username"> <"email"> <"password">');
- return(1);
- }
-
- # !!! FIXME: ?
- #if ($uname =~ /[^a-zA-Z0-9]/) {
- # report_error('Username may only contain letters and numbers');
- # return(1);
- #}
-
- if ($uname =~ /[%_<>&\t#]/) {
- report_error('Username has illegal characters');
- return(1);
- }
-
- if (($current_global_rights & canCreateUsers) == 0) {
- report_error('You are not permitted to create new user accounts.');
- return(1);
- }
-
- my $link = get_database_link();
-
- $uname = $link->quote($uname);
- my $sql = "select id from $dbtable_users where name like $uname";
- my $sth = $link->prepare($sql);
- if (not $sth->execute()) {
- report_error("can't execute the query: $sth->errstr");
- return(1);
- }
- my @row = $sth->fetchrow_array();
- $sth->finish();
- if (@row) {
- report_error("That username is taken.");
- return(1);
- }
-
- $email = $link->quote($email);
- $pword = $link->quote(crypt($pword, new_crypt_salt()));
- $sql = "insert into $dbtable_users" .
- " (name, password, globalrights, defaultqueue, email, created)" .
- " values ($uname, $pword, $default_user_rights," .
- " $default_queue, $email, NOW())";
- if (not $link->do($sql)) {
- report_error("can't add user: $link->errstr");
- } else {
- report_success("Added user.");
- }
-
- return(1);
-};
-
-
-$commands{'LOCKUSER'} = sub {
- my $uid = shift;
- if ((not defined $uid) or ($uid !~ /\A\d+\Z/)) {
- report_error('argument must be number.');
- return(1);
- }
-
- report_error("Can't lock anonymous account"), return 1 if ($uid == 0);
-
- if ($uid != $auth_uid) {
- if (!($current_global_rights & canLockUsers)) {
- report_error("You don't have permission to do that.");
- return(1);
- }
- }
-
- my $link = get_database_link();
- my $x = canNotAuthorize; # needed for interpolation.
- my $sql = "update $dbtable_users" .
- " set globalrights=(globalrights|$x)" .
- " where id=$uid";
-
- if (not defined $link->do($sql)) {
- report_error("can't lock user: $link->errstr");
- } else {
- report_success("Locked user id $uid.");
- if ($uid == $auth_uid) {
- $auth_uid = 0;
- $current_global_rights = $current_queue_rights = 0;
- }
- }
-
- return(1);
-};
-
-
-$commands{'NOOP'} = sub {
- report_success('epson the whole astroda');
- return(1);
-};
-
-
-$commands{'CREATEQUEUE'} = sub {
- # !!! FIXME: Implement this.
- my $args = shift;
- report_error('Not yet implemented');
- return(1);
-};
-
-
-$commands{'LOCKQUEUE'} = sub {
- # !!! FIXME: Implement this.
- my $args = shift;
- report_error('Not yet implemented.');
- return(1);
-};
-
-
-$commands{'HIDEQUEUE'} = sub {
- # !!! FIXME: Implement this.
- my $args = shift;
- report_error('Not yet implemented.');
- return(1);
-};
-
-
-$commands{'GETRDF'} = sub {
- my $max = shift; # it's okay for this to be undef'd.
- report_error('no queue selected.'), return 1 if $queue == 0;
- my ($err, $rdf, $filename) = generate_rdf($queue, $max);
- report_error($err), return 1 if (defined $err);
- report_success('here comes.');
- print("$rdf\012.\012");
- return(1);
-};
-
-
-$commands{'FORGOTPASSWORD'} = sub
-{
- my $args = shift;
- my ($user, $email) = (undef, undef);
- if (defined $args) {
- ($user, $email) = $args =~ /\A\"(.+?)\"\s*\"(.+?)\"\Z/
- }
-
- if ((not defined $user) or (not defined $email)) {
- report_error('USAGE: FORGOTPASSWORD <"user"> <"email">');
- return(1);
- }
-
- my $pword = generate_pword();
- my $err = undef;
- my $link = get_database_link();
- my $u = $link->quote($user);
- my $e = $link->quote($email);
- my $sql = "select id from $dbtable_users" .
- " where email like $e and name like $u";
- my $sth = $link->prepare($sql);
- if (not $sth->execute()) {
- report_error("can't execute the query: $sth->errstr");
- return(1);
- }
- my @row = $sth->fetchrow_array();
- $sth->finish();
- $err = "Can't find a matching user/email." if (not @row);
- $err = send_forgotten_password($user, $email, $pword) if (not defined $err);
- if (defined $err) {
- $err .= " Please talk to $admin_email for further assistance.";
- report_error($err);
- } else {
- my $id = $row[0];
- #print("id is [$id], pword is [$pword].\n");
- my $cryptedpw = $link->quote(crypt($pword, new_crypt_salt()));
- $sql = "update $dbtable_users set password=$cryptedpw where id=$id";
- $link->do($sql); # This has to work; we already sent the email. (*shrug*)
- report_success("Helpful Phriendly info sent to $email ...");
- }
-
- return(1);
-};
-
-
-$commands{'CHANGEPASSWORD'} = sub {
- my $newpass = shift;
- if (not defined $newpass) {
- report_error("Usage: CHANGEPASSWORD ");
- return(1);
- }
-
- report_error("Please log in first"), return 1 if ($auth_uid == 0);
-
- my $link = get_database_link();
- $newpass = $link->quote(crypt($newpass, new_crypt_salt()));
- my $sql = "update $dbtable_users set password=$newpass where id=$auth_uid";
- if (not defined $link->do($sql)) {
- report_error("can't change password: $link->errstr");
- } else {
- report_success("password changed.");
- }
-
- return(1);
-};
-
-
-$commands{'SETDEFAULTQUEUE'} = sub {
- my $qid = shift;
- if ((not defined $qid) or ($qid !~ /\A\d+\Z/)) {
- report_error('argument must be number.');
- return(1);
- }
-
- report_error("Please log in first"), return 1 if ($auth_uid == 0);
-
- if ($qid != 0) {
- my $sql = "select id from $dbtable_queues where id=$qid";
- my $sth = $link->prepare($sql);
- if (not $sth->execute()) {
- report_error("can't execute the query: $sth->errstr");
- return(1);
- }
- my @row = $sth->fetchrow_array();
- $sth->finish();
- if (not @row) {
- report_error("No such queue.");
- return(1);
- }
- }
-
- # !!! FIXME: Make sure user can select this queue before changing default!
-
- my $sql = "update $dbtable_users set defaultqueue=$qid where id=$auth_uid";
- if (not defined $link->do($sql)) {
- report_error("Failed to set default queue: $link->errstr");
- } else {
- report_success("default queue changed.");
- }
-
- return(1);
-};
-
-
-$commands{'QUIT'} = sub {
- report_success('kthxbye');
- return(0); # break command processing loop.
-};
-
-
-$commands{'EXIT'} = $commands{'QUIT'}; # just an alias.
-$commands{'Q'} = $commands{'QUIT'}; # just another alias.
-
-
-sub news_mainline {
- autoflush STDOUT, 1;
-
- if (not defined $ENV{'TCPREMOTEIP'}) {
- report_fatal('TCPREMOTEIP is not set. Daemon is misconfigured. Aborting.');
- }
-
- $ipaddr = unpack('N', inet_aton($ENV{'TCPREMOTEIP'}));
-
- report_success("IcculusNews daemon $version");
- process_command('AUTH') while (not defined $auth_uid);
- 1 while (process_command());
- $link->disconnect() if defined $link;
- return 0;
-}
-
-
-sub syslog_and_die {
- my $err = shift;
- do_log(syslogError, $err);
- die($err);
-}
-
-
-sub go_to_background {
- use POSIX 'setsid';
- chdir('/') or syslog_and_die("Can't chdir to '/': $!");
- open STDIN,'/dev/null' or syslog_and_die("Can't read '/dev/null': $!");
- open STDOUT,'>/dev/null' or syslog_and_die("Can't write '/dev/null': $!");
- defined(my $pid=fork()) or syslog_and_die("Can't fork: $!");
- exit if $pid;
- setsid or syslog_and_die("Can't start new session: $!");
- open STDERR,'>&STDOUT' or syslog_and_die("Can't duplicate stdout: $!");
- do_log(syslogDaemon, "Daemon process is now detached");
-}
-
-
-sub drop_privileges {
- delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
- $ENV{'PATH'} = $safe_path;
- $) = $wanted_gid if (defined $wanted_gid);
- $> = $wanted_uid if (defined $wanted_uid);
-}
-
-sub signal_catcher {
- my $sig = shift;
- do_log(syslogDaemon, "Got signal $sig. Shutting down.");
- exit 0;
-}
-
-
-my @kids;
-use POSIX ":sys_wait_h";
-sub reap_kids {
- my $i = 0;
- my $x = scalar(@kids);
- while ($i < scalar(@kids)) {
- my $rc = waitpid($kids[$i], &WNOHANG);
- if ($rc != 0) { # reaped a zombie.
- splice(@kids, $i, 1); # take it out of the array.
- } else { # still alive, try next one.
- $i++;
- }
- }
-
- $SIG{CHLD} = \&reap_kids; # make sure this works on crappy SysV systems.
-}
-
-
-
-# Mainline.
-
-if (defined $read_timeout) {
- use IO::Select;
-}
-
-foreach (@ARGV) {
- $daemonize = 1, next if $_ eq '--daemonize';
- $daemonize = 1, next if $_ eq '-d';
- $daemonize = 0, next if $_ eq '--no-daemonize';
- die("Unknown command line \"$_\".\n");
-}
-
-if ($use_syslog) {
- use Sys::Syslog qw(:DEFAULT setlogsock);
- setlogsock('unix');
- openlog('newsd', 'user') or report_fatal("Couldn't open syslog: $!");
-}
-
-
-my $retval = 0;
-if (not $daemonize) {
- drop_privileges();
- $retval = news_mainline();
-} else {
- do_log(syslogDaemon, "IcculusNews daemon $version starting up...");
- go_to_background();
-
- $SIG{CHLD} = \&reap_kids;
- $SIG{TERM} = \&signal_catcher;
- $SIG{INT} = \&signal_catcher;
-
- use IO::Socket::INET;
- my $listensock = IO::Socket::INET->new(LocalPort => $server_port,
- Type => SOCK_STREAM,
- ReuseAddr => 1,
- Listen => $max_connects);
-
- syslog_and_die("couldn't create listen socket: $!") if (not $listensock);
-
- drop_privileges();
-
- do_log(syslogDaemon, "Now accepting connections (max $max_connects" .
- " simultaneous on port $server_port).");
-
- while (1)
- {
- # prevent connection floods.
- sleep(1) while (scalar(@kids) >= $max_connects);
-
- my $client = $listensock->accept();
- syslog_and_die("accept() failed: $!") if (not $client);
-
- my $ip = $client->peerhost();
- syslog("info", "connection from $ip") if ($use_syslog);
-
- $ENV{'TCPREMOTEIP'} = $ip;
-
- my $kidpid = fork();
- syslog_and_die("fork() failed: $!") if (not defined $kidpid);
-
- if ($kidpid) { # this is the parent process.
- close($client); # parent has no use for client socket.
- push @kids, $kidpid;
- } else {
- close($listensock); # child has no use for listen socket.
- local *FH = $client;
- open(STDIN, "<&FH") or syslog_and_die("no STDIN reassign: $!");
- open(STDERR, ">&FH") or syslog_and_die("no STDERR reassign: $!");
- open(STDOUT, ">&FH") or syslog_and_die("no STDOUT reassign: $!");
- my $retval = news_mainline();
- close($client);
- exit $retval; # kill child.
- }
- }
-
- close($listensock); # shouldn't ever hit this.
-}
-
-exit $retval;
-
-# end of IcculusNews_daemon.pl ...
-
diff --git a/IcculusNews_dotqmail.pl b/IcculusNews_dotqmail.pl
deleted file mode 100755
index d0c550c..0000000
--- a/IcculusNews_dotqmail.pl
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use warnings;
-
-# The ever important debug-spew-enabler...
-my $debug = 0;
-
-# most of these can be altered at runtime with command line options.
-my $newshost = 'localhost';
-my $newsauthor = 'postmaster';
-my $postingagent = '/usr/local/bin/IcculusNews_post.pl';
-my $queuenum = 1;
-my $newspass = undef;
-my $newspassfile = '/etc/IcculusNews_mailgatewaypass.txt';
-my $portnum = 263;
-my $newssubj = undef;
-
-#-----------------------------------------------------------------------------#
-# The rest is probably okay without you laying yer dirty mits on it. #
-#-----------------------------------------------------------------------------#
-
-# the mainline.
-
-if ((not defined $newspass) && (not defined $ENV{'ICCNEWS_POST_PASS'})) {
- if (defined $newspassfile) {
- open(FH, $newspassfile) or die("failed to open $newspassfile: $!\n");
- $newspass = ;
- chomp($newspass);
- $newspass =~ s/\A\s*//;
- $newspass =~ s/\s*\Z//;
- close(FH);
- }
-}
-
-
-for (my $i = 0; $i < scalar(@ARGV); $i++) {
- my $arg = $ARGV[$i];
- $debug = 1, next if ($arg eq '--debug');
- $newshost = $ARGV[++$i], next if ($arg eq '--host');
- $queuenum = $ARGV[++$i], next if ($arg eq '--queue');
- $portnum = $ARGV[++$i], print("!!! FIXME: --port is ignored right now.\n"), next if ($arg eq '--port');
- $newsauthor = $ARGV[++$i], next if ($arg eq '--user');
- $newssubj = $ARGV[++$i], next if ($arg eq '--subj');
- $postingagent = $ARGV[++$i], next if ($arg eq '--agent');
-
- #$username = $arg, next if (not defined $username);
- #$subject = $arg, next if (not defined $subject);
- #$text = $arg, next if (not defined $text);
- #etc.
-
- print("Unknown argument \"$arg\".\n");
-}
-
-print(" reading from STDIN...\n") if $debug;
-my $t = '';
-$t .= $_ while ();
-
-if (not defined $newssubj) {
- if ($t =~ /^Subject:\s?(.*?)$/m) {
- $newssubj = $1;
- }
-}
-
-$newssubj = "Posting to IcculusNews mail gateway" if (not defined $newssubj);
-
-print(" posting to IcculusNews's submission queue...\n") if $debug;
-$ENV{'ICCNEWS_POST_PASS'} = $newspass if defined $newspass;
-my $rc = open(PH, "|'$postingagent' '$newshost' '$newsauthor' '$queuenum' '$newssubj' -");
-if (not $rc) {
- print(" No pipe to IcculusNews: $!\n");
-} else {
- print PH "$ENV{'SENDER'} sent us the following email:" .
- "\n
\n
$t
\n
\n";
- close(PH);
- print(" posted to submission queue.\n") if $debug;
-}
-
-exit 99; # prevent further qmail delivery with successful status.
-
-# end of IcculusNews_dotqmail.pl ...
-
diff --git a/IcculusNews_post.pl b/IcculusNews_post.pl
deleted file mode 100755
index a8709d5..0000000
--- a/IcculusNews_post.pl
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use Sys::Hostname;
-use IO::Socket::INET;
-
-my $version = "v2.0.0beta";
-
-# The ever important debug-spew-enabler...
-my $debug = 0;
-
-#----------------------------------------------------------------------------#
-# End of setup vars. The rest is probably okay without you touching it. #
-#----------------------------------------------------------------------------#
-
-sub usage {
- print STDERR <<__EOF__;
-
-IcculusNews_post $version
-USAGE: $0
- if is '-', the Anonymous account is used.
- You will be prompted for a password if needed. You can
- avoid the prompt if you set the ICCNEWS_POST_PASS
- environment variable.
- if is '-', news is read from stdin.
-
-__EOF__
-
- exit 10;
-}
-
-
-sub okay_or_die {
- my ($sock, $sect) = @_;
- print "checking server response for: $sect\n" if $debug;
- my $response = <$sock>;
- chomp($response);
- print "server said: \"$response\".\n" if $debug;
- if ($response !~ /\A\+/) {
- print $sock "QUIT\012"; # just in case.
- close($sock);
- die("Error reported during $sect: \"$response\".\n");
- }
-}
-
-
-# the mainline.
-
-my $user = undef;
-my $host = undef;
-my $pass = undef;
-my $subj = undef;
-my $text = undef;
-my $qid = undef;
-
-foreach (@ARGV) {
- usage() if ($_ eq '--help');
- $debug = 1, next if ($_ eq '--debug');
- $host = $_, next if (not defined $host);
- $user = $_, next if (not defined $user);
- $qid = $_, next if (not defined $qid);
- $subj = $_, next if (not defined $subj);
- $text = $_, next if (not defined $text);
-}
-
-usage() if ((!defined $user) or (!defined $host) or (!defined $subj) or (!defined $text));
-
-$text =~ s/\A\s*//;
-$text =~ s/\s*\Z//;
-if ($text eq '-') {
- $text = '';
- while () {
- $text .= $_;
- }
-}
-
-$user =~ s/\A\s*//;
-$user =~ s/\s*\Z//;
-
-my $authstr = undef;
-if ($user eq '-') {
- $authstr = '-';
-} else {
- $pass = $ENV{'ICCNEWS_POST_PASS'};
- if (not defined $pass) {
- print("!!! FIXME: Prompt for a password here. export ICCNEWS_POST_PASS for now.\n");
- exit(42);
- }
-
- $authstr = "\"$user\" \"$pass\"";
-}
-
-1 while ($text =~ s/\015\012/\012/s);
-1 while ($text =~ s/\015/\012/s);
-$text =~ s/^\.\012/..\012/sm;
-1 while ($text =~ s/\012\.\012/\012..\012/s);
-
-print "Connecting to news server..." if $debug;
-my $sock = IO::Socket::INET->new(PeerAddr => $host,
- PeerPort => 263,
- Type => SOCK_STREAM,
- Proto => 'tcp');
-
-die("Failed to connect to news server: $!\n") if not defined $sock;
-
-print "connected.\n" if $debug;
-
-okay_or_die($sock, 'initial welcome');
-print $sock "AUTH $authstr\012";
-okay_or_die($sock, 'user authorization');
-print $sock "QUEUE $qid\012";
-okay_or_die($sock, 'queue selection');
-print $sock "POST $subj\012";
-okay_or_die($sock, 'post command');
-print $sock "$text\012.\012";
-okay_or_die($sock, 'text posting');
-print $sock "QUIT\012";
-okay_or_die($sock, 'disconnection');
-close($sock);
-
-print("News item successfully posted.\n") if $debug;
-exit 0;
-
-# end of IcculusNews_post.pl ...
-
diff --git a/TODO b/TODO
deleted file mode 100644
index 91bc246..0000000
--- a/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-- User interface to CHANGEPASSWORD (including emailing forgotten passwords).
-- Have IcculusNews_post.pl prompt for a password.
-- CREATEQUEUE.
-- Shitloads more.
-