home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / FAQ / discus_admin_1357211388 / source / adm-tpc.pl < prev    next >
Text File  |  2009-11-06  |  32KB  |  906 lines

  1. # FILE: adm-tpc.pl
  2. # DESCRIPTION: Topic Manager Interface and Functions
  3. #-------------------------------------------------------------------------------
  4. # DISCUS COPYRIGHT NOTICE
  5. #
  6. # Discus is copyright (c) 2002 by DiscusWare, LLC, all rights reserved.
  7. # The use of Discus is governed by the Discus License Agreement which is
  8. # available from the Discus WWW site at:
  9. #    http://www.discusware.com/discus/license
  10. #
  11. # Pursuant to the Discus License Agreement, this copyright notice may not be
  12. # removed or altered in any way.
  13. #-------------------------------------------------------------------------------
  14.  
  15. use strict;
  16. use vars qw($GLOBAL_OPTIONS $DCONF $PARAMS);
  17.  
  18. ###
  19. ### TOPIC_admin
  20. ###
  21. ### Handles all Topic Manager actions
  22. ###
  23.  
  24. sub TOPIC_admin {
  25.     my ($FORMref) = @_;
  26.     my $result = check_password($FORMref->{username}, undef, { type_required => 'moderator' }, $FORMref->{'COOKIE'});
  27.     bad_login( { bad_username => 1 } ) if scalar(@{ $result }) == 0;
  28.     bad_login( { superuser_required => 1 } ) if $result->[0]->{user} ne $DCONF->{superuser};
  29.     my $subst = {};
  30.     if ($FORMref->{'action'} eq "topic_prop") {
  31.         my $arg = topic_properties_handle(board_topics(), $FORMref);
  32.         topic_management_handler($FORMref, $result->[0]->{user}, "p", { what => ( set_topic_properties($arg) == 1 ? 1 : 0 ) }, $arg->{number});
  33.         topic_manager($FORMref, $result->[0]->{user}, { what => 6 });
  34.     }
  35.     if ($FORMref->{'action'} eq "topic_catprop") {
  36.         my $arg = topic_category_properties_handle(board_topics(), $FORMref);
  37.         topic_management_handler($FORMref, $result->[0]->{user}, "p", { what => ( defined set_category_properties($arg) ? 2 : 0 ) }, $arg->{number});
  38.     }
  39.     if ($FORMref->{'action'} eq "topic_mgmt") {
  40.         topic_management_handler($FORMref, $result->[0]->{user}, $FORMref->{'SELECTION'}, undef);
  41.     }
  42.     if ($FORMref->{'action'} eq "topic_mod") {
  43.         topic_privileges_save($FORMref->{'affect'}, $FORMref->{'mod'});
  44.         topic_manager($FORMref, $result->[0]->{user}, { what => 2 });
  45.     }
  46.     if ($FORMref->{'action'} eq "topic_mgr") {
  47.         topic_manager($FORMref, $result->[0]->{user}, undef);
  48.     }
  49.     if ($FORMref->{'action'} eq "topic_add") {
  50.         topic_add_topic_handler($FORMref, $result->[0]->{user});
  51.     }
  52.     if ($FORMref->{'action'} eq "topic_cat_add") {
  53.         topic_add_category_handler($FORMref, $result->[0]->{user});
  54.     }
  55.     if ($FORMref->{'action'} eq "topic_rename") {
  56.         topic_rename_handler($FORMref, $result->[0]->{user});
  57.         topic_manager($FORMref, $result->[0]->{user}, { what => 7 });
  58.     }
  59.     if ($FORMref->{'action'} eq "topic_meta") {
  60.         topic_meta_tag_handler($FORMref, $result->[0]->{user});
  61.     }
  62.     error_message("Fell through topic admin subroutine");
  63. }
  64.  
  65. ###
  66. ### add_topic
  67. ###
  68. ### Creates a topic and underlying data structure with these inputs:
  69. ###     number =>        Topic number to use (if 0, gets unique #)
  70. ###        name =>            Topic name
  71. ###        descr =>        Topic description (optional)
  72. ###        postpriv =>        Posting privileges (0=public, 1=user+moderator, 2=moderator, 3=off)
  73. ###        readpriv =>        Reading privileges (same arguments as for posting)
  74. ###        content =>        Content (0=private index,1=public index)
  75. ###        place =>        Placement (0=bottom, 1=top)
  76. ###
  77.  
  78. sub add_topic {
  79.     my ($arg, $FORMref) = @_;
  80.     if (! -e "$DCONF->{admin_dir}/data/serial.txt") {
  81.         open (FILE, "> $DCONF->{admin_dir}/data/serial.txt");
  82.         print FILE join(".", $PARAMS->{'serial'}, time), "\n";
  83.         close (FILE);
  84.     }
  85.     undef my $param;
  86.     $param->{number} = ( defined($arg->{number}) ? $arg->{number} : get_number() );
  87.     $param->{name} = ( defined($arg->{name}) ? $arg->{name} : "Untitled Topic" );
  88.     $param->{descr} = ( defined($arg->{descr}) ? $arg->{descr} : "");
  89.     $param->{postpriv} = ( $arg->{postpriv} > 0 ? $arg->{postpriv} : 0);
  90.     $param->{readpriv} = ( $arg->{readpriv} > 0 ? $arg->{readpriv} : 0);
  91.     $param->{content} = ( $arg->{content} == 1 ? 1 : 0 );
  92.     $param->{place} = ( defined($arg->{place}) ? $arg->{place} : 0 );
  93.     $param->{param} = ( $param->{content} == 1 ? "Sublist" : "SublistCreate" );
  94.     $param->{icon} = ( $param->{readpriv} >= 1 ? "tree_o" : "tree_n" );
  95.     if (my $x = topic_error_touch("$DCONF->{admin_dir}/msg_index/$param->{number}-log.txt")) {
  96.         error_message("Create Topic Error", "Could not create log file for topic: $x", 0, 1);
  97.     }
  98.     if (my $x = topic_error_touch("$DCONF->{admin_dir}/msg_index/$param->{number}-search.txt")) {
  99.         error_message("Create Topic Error", "Could not create search file for topic: $x", 0, 1);
  100.     }
  101.     dreq("fcn-logs");
  102.     create_blank_mini_logs($param->{number});
  103.     undef my $tree_hash;
  104.     $tree_hash->{'topic'} = $param->{number};
  105.     $tree_hash->{'page'} = $param->{number};
  106.     $tree_hash->{'name'} = $param->{name};
  107.     $tree_hash->{'param'} = $param->{param};
  108.     $tree_hash->{'subs'} = 1;
  109.     $tree_hash->{'properties'} = "icon=$param->{icon}";
  110.     my ($tree_line, $tree_h) = generate_tree_line($tree_hash);
  111.     if (open(FILE, "> $DCONF->{admin_dir}/msg_index/$param->{number}-tree.txt")) {
  112.         print FILE $tree_line;
  113.         close (FILE);
  114.     } else {
  115.         error_message("Create Topic Error", "Could not create tree file for topic!");
  116.     }
  117.     chmod(oct($DCONF->{'perms0666'}), "$DCONF->{admin_dir}/msg_index/$param->{number}-tree.txt");
  118.     my $array = readfile("$DCONF->{admin_dir}/tree.txt", "add_topic", { ok_zero => 1, no_unlock => 1 });
  119.     unshift(@{$array}, $tree_line) if $param->{place} == 1;
  120.     push(@{$array}, $tree_line) if $param->{place} != 1;
  121.     writefile("$DCONF->{admin_dir}/tree.txt", $array, "add_topic",    { no_lock => 1 });
  122.     undef my $dir;
  123.     $dir = ( $arg->{readpriv} == 0 ? "$DCONF->{message_dir}/$param->{number}" : "$DCONF->{secdir}/$param->{number}" );
  124.     if (! mkdir($dir,oct($DCONF->{'perms0777'})) ) {
  125.         error_message("Create Directory Error", "Could not create directory for topic [$param->{number}]!");
  126.     }
  127.     chmod (oct($DCONF->{'perms0777'}), $dir);
  128.     topic_error_touch("$dir/index.html");
  129.     undef my $newhash;
  130.     $newhash->{number} = $param->{number};
  131.     $newhash->{name} = $param->{name};
  132.     $newhash->{descr} = $param->{descr};
  133.     $newhash->{subs} = 1;
  134.     $newhash->{posts} = 0;
  135.     $newhash->{originator} = " ";
  136.     $newhash->{last_poster} = " ";
  137.     $newhash->{lastmod} = time;
  138.     $newhash->{url} = join("", ( $param->{readpriv} == 1 ? "$DCONF->{authorize_reader}?file=" : "$DCONF->{message_url}" ), "/$param->{number}/$param->{number}.$DCONF->{ext}");
  139.     $newhash->{url} .= "?$newhash->{lastmod}" if ($DCONF->{noqm} == 0 && $param->{readpriv} == 0);
  140.     $newhash->{url} .= "&lm=$newhash->{lastmod}" if $param->{readpriv} == 1;
  141.     $newhash->{type} = 1;
  142.     $newhash->{icon} = "$param->{icon}";
  143.     dreq("topic-pg");
  144.     my $tref = read_topic_page( { lock => 1 } );
  145.     unshift (@{ $tref->{'topics'} }, $newhash) if $param->{place} == 1;
  146.     push (@{ $tref->{'topics'} }, $newhash) if $param->{place} != 1;
  147.     $tref->{unlock} = 1;
  148.     write_topic_page( $tref );
  149.     undef my $newpage;
  150.     $newpage->{me_name} = $param->{name};
  151.     $newpage->{me_number} = $param->{number};
  152.     $newpage->{topic_name} = $param->{name};
  153.     $newpage->{topic_number} = $param->{number};
  154.     $newpage->{param} = $param->{param};
  155.     $newpage->{parent} = $param->{number};
  156.     dreq("fcn-pgad");
  157.     my $subst = create_new_page( $newpage );
  158.     @{ $subst->{head}->{levels} } = ();
  159.     SetPage($subst);
  160.     undef my @actions;
  161.     if ($DCONF->{pro}) { # Reading Privileges
  162.         my $hashref = { action => "add_topic", topic => $param->{number}, type => "r" };
  163.         if ($arg->{readpriv} == 0) {
  164.             $hashref->{ip} = "*";
  165.         } elsif ($arg->{readpriv} == 1) {
  166.             $hashref->{moderator} = "*"; $hashref->{user} = "*";
  167.         } elsif ($arg->{readpriv} == 2) {
  168.             $hashref->{moderator} = "*";
  169.         }
  170.         push (@actions, $hashref);
  171.         if ($DCONF->{pro} && $arg->{readpriv} <= 2 && defined $FORMref) {
  172.             dreq("authwrap-PRO");
  173.             acs_add_additional_topics_to_token(undef, $param->{number}, $FORMref);
  174.         }
  175.     }
  176.     { # Posting Privileges
  177.         my $hashref = { action => "add_topic", topic => $param->{number}, type => "p" };
  178.         if ($arg->{postpriv} == 0) {
  179.             $hashref->{ip} = "*";
  180.         } elsif ($arg->{postpriv} == 1) {
  181.             $hashref->{moderator} = "*"; $hashref->{user} = "*";
  182.         } elsif ($arg->{postpriv} == 2) {
  183.             $hashref->{moderator} = "*";
  184.         }
  185.         push (@actions, $hashref);
  186.     }
  187.     { # Post Options
  188.         my $hashref = { action => "add_topic", topic => $param->{number}, type => "o" };
  189.         push (@actions, $hashref);
  190.     }
  191.     if ($DCONF->{pro}) { # Queue Privileges
  192.         my $hashref = { action => "add_topic", topic => $param->{number}, type => "q" };
  193.         push (@actions, $hashref);
  194.     }
  195.     dreq("fcn-usrp"); write_topic_privilege_file(\@actions);
  196.     dreq("fcn-priv"); write_privilege_file([ { action => 'add_topic', topic => $param->{number}, moderator => $DCONF->{superuser} }]);
  197.     return $param->{number};
  198. }
  199.  
  200. ###
  201. ### add_category
  202. ###
  203. ### Creates a category with these inputs:
  204. ###        text =>            Category text (essentially its name)
  205. ###        descr =>        Category description (optional)
  206. ###        bgcolor =>        Background color (if skin supports it)
  207. ###        place =>        Placement (0=bottom, 1=top)
  208. ###
  209.  
  210. sub add_category {
  211.     my ($arg) = @_;
  212.     if (! -e "$DCONF->{admin_dir}/data/serial.txt") {
  213.         open (FILE, "> $DCONF->{admin_dir}/data/serial.txt");
  214.         print FILE join(".", $PARAMS->{'serial'}, time), "\n";
  215.         close (FILE);
  216.     }
  217.     dreq("topic-pg");
  218.     undef my $argument;
  219.     my $new_num = get_number();
  220.     my $input = read_topic_page( { lock => 1} );
  221.     my @topics = @{ $input->{topics} };
  222.     undef my $catref;
  223.     $catref->{text} = ( defined($arg->{text}) ? $arg->{text} : " " );
  224.     $catref->{descr} = ( defined($arg->{descr}) ? $arg->{descr} : "" );
  225.     $catref->{bgcolor} = ( defined($arg->{bgcolor}) ? $arg->{bgcolor} : "#ffffcc" );
  226.     $catref->{number} = $new_num;
  227.     my $place = ( defined($arg->{place}) ? $arg->{place} : 0 );
  228.     push (@topics, $catref) if $place == 0;
  229.     unshift (@topics, $catref) if $place == 1;
  230.     $input->{topics} = \@topics;
  231.     $input->{unlock} = 1;
  232.     my $hashref = { action => "set_equal", topic => $new_num, type => "cr" };
  233.     dreq("fcn-usrp");
  234.     my @actions = ($hashref);
  235.     my $m1 = read_topic_privilege_file(1);
  236.     write_topic_privilege_file(\@actions);
  237.     return write_topic_page($input);
  238. }
  239.  
  240. ###
  241. ### delete_topic
  242. ###
  243. ### Deletes one or more topics and their supporting data structures.
  244. ###
  245. ### Input is $remove_list, a hash reference.  To delete a topic or category, the
  246. ### topic or category number is a key and its value is 1.
  247. ###
  248.  
  249. sub delete_topic {
  250.     my ($remove_list) = @_;
  251.     dreq("topic-pg");
  252.     my $topic_page = read_topic_page( { lock => 1 } );
  253.     undef my @new_array;
  254.     undef my @removes;
  255.     while (my $x = shift(@{ $topic_page->{'topics'} })) {
  256.         push (@new_array, $x) if ! $remove_list->{ $x->{number} };
  257.         push (@removes, $x->{number}) if $remove_list->{ $x->{number} } && $x->{type} == 1;
  258.     }
  259.     $topic_page->{'topics'} = \@new_array;
  260.     $topic_page->{'unlock'} = 1;
  261.     write_topic_page($topic_page);
  262.     undef my %nuked;
  263.     dreq("fcn-logs");
  264.     foreach my $key (@removes) {
  265.         undef my $dir;
  266.         if (-e "$DCONF->{message_dir}/$key") {
  267.             $dir = "$DCONF->{message_dir}/$key";
  268.         } else {
  269.             $dir = "$DCONF->{secdir}/$key";
  270.         }
  271.         if (opendir(DIR, $dir)) {
  272.             while (my $f = readdir(DIR)) {
  273.                 if ($f !~ m|^(\d+)\.$DCONF->{ext}$|) {
  274.                     $nuked{$f} = 1;
  275.                 }
  276.                 unlink ("$dir/$f");
  277.             }
  278.             closedir(DIR);
  279.             rmdir("$dir") || log_error("adm-tpc.pl", "delete_topic", "Could not remove directory [$dir/$key] : [$!]");
  280.         }
  281.         $dir = "$DCONF->{admin_dir}/msg_index/$key";
  282.         if (-e $dir) {    # Might be here from older versions
  283.             opendir(DIR, "$dir");
  284.             while (my $f = readdir(DIR)) {
  285.                 unlink ("$dir/$f");
  286.             }
  287.             closedir(DIR);
  288.             rmdir("$DCONF->{admin_dir}/msg_index/$key");
  289.         }
  290.         unlink("$DCONF->{admin_dir}/msg_index/$key-tree.txt");
  291.         unlink("$DCONF->{admin_dir}/msg_index/$key-search.txt");
  292.         unlink("$DCONF->{admin_dir}/msg_index/$key-log.txt");
  293.         my $mini = get_mini_logs();
  294.         if (ref $mini eq 'ARRAY' && scalar @{$mini}) {
  295.             foreach my $m (@{$mini}) {
  296.                 unlink("$DCONF->{admin_dir}/msg_index/$key-log-$m.txt");
  297.             }
  298.         }
  299.         if ($GLOBAL_OPTIONS->{'database'} && $DCONF->{pro}) {
  300.             dreq("dbint");
  301.             my $dbh = db_connect();
  302.             db_query("DELETE FROM $PARAMS->{db_prefix}log WHERE posttopic = $key;", $dbh);
  303.             db_query("DELETE FROM $PARAMS->{db_prefix}search WHERE posttopic = $key;", $dbh);
  304.         }
  305.     }
  306.     dreq("fcn-usrp"); write_topic_privilege_file([ { action => "del_topic", type => "p,r,o,q", topic => join(",", keys(%{ $remove_list })) } ]);
  307.     dreq("fcn-priv"); write_privilege_file([ { action => "del_topic", topic => join(",", keys(%{ $remove_list })) } ]);
  308.     undef my @new_tree;
  309.     my $treeref = readfile("$DCONF->{admin_dir}/tree.txt", "delete_topic", { no_unlock => 1, zero_ok => 1 });
  310.     foreach my $treeline (@{$treeref}) {
  311.         my @c = split(/\t/, $treeline, 3);
  312.         if (! $remove_list->{ $c[1] }) {
  313.             push (@new_tree, $treeline);
  314.         }
  315.     }
  316.     writefile("$DCONF->{admin_dir}/tree.txt", \@new_tree, "delete_topic", { no_lock => 1 });
  317.     return 1;
  318. }
  319.  
  320. ###
  321. ### topic_rename_handler
  322. ###
  323. ### Handles form input to rename a topic
  324. ###
  325.  
  326. sub topic_rename_handler {
  327.     my ($FORMref, $username) = @_;
  328.     dreq("webtags");
  329.     my ($l, $n) = webtags($FORMref->{topic_name}, 1, 1, 1);
  330.     error_message("Rename Topic - Problem With Name", $n, 0, 1) if $l eq "!Error";
  331.     my $bt = board_topics();
  332.     error_message("Rename Topic - Error", "Topic does not exist!") if ! grep($_->{number} == $FORMref->{topic}, @{$bt});
  333.     rename_topic($FORMref->{topic}, $n, $username, $bt);
  334.  
  335. }
  336.  
  337. ###
  338. ### rename_topic
  339. ###
  340. ### Gives a topic a new name that you specify
  341. ###
  342.  
  343. sub rename_topic {
  344.     my ($topic, $new_name, $user, $bt_cache) = @_;
  345.     dreq("fcn-regn", "fcn-tree", "topic-pg");
  346.     my $tree = read_tree($topic, { no_unlock => 1 });
  347.     my $H = tree_record_update($tree, undef, { topic => $topic, page => $topic, name => $new_name }, 1);
  348.     $tree = $H->{tree}; my $cat = $H->{cat};
  349.     write_tree($topic, $tree, { no_lock => 1 });
  350.     topic_tree_to_main($tree);
  351.     regenerate_topic_page();
  352.     my $Q = GetPage($topic, $topic, { lock => 1 });
  353.     $Q->{head}->{topic_name} = $new_name;
  354.     $Q->{head}->{me_name} = $new_name;
  355.     SetPage($Q, { unlock => 1 });
  356.     my $chgfile = regeneration_create_change_process_file("regen_topic_name_change", $new_name);
  357.     my $Z = { $topic => 1 };
  358.     my $hold = regeneration_create_hold({ topic => $topic, action => 'rename' });
  359.     regenerate_board({ topic => $Z, hold => $hold, action => "regen5", username => $user, changefile => $chgfile, operation => 7, description => 701 });
  360. }
  361.  
  362. ###
  363. ### topic_meta_tag_handler
  364. ###
  365. ### Handles form input to set up META tags
  366. ###
  367.  
  368. sub topic_meta_tag_handler {
  369.     my ($FORMref, $username) = @_;
  370.     my $d = defined $FORMref->{meta_description} ? $FORMref->{meta_description} : ""; $d =~ s/["\n]//g;
  371.     my $k = defined $FORMref->{meta_keywords} ? $FORMref->{meta_keywords} : ""; $k =~ s/["\n]//g;
  372.     my $r = "";
  373.     if ($FORMref->{meta_robots} == 1) {
  374.         $r = "NOINDEX,NOFOLLOW";
  375.     } elsif ($FORMref->{meta_robots} == 2) {
  376.         $r = "INDEX,FOLLOW";
  377.     } elsif ($FORMref->{meta_robots} == 3) {
  378.         $r = $FORMref->{meta_robots_text}; $r =~ s/["\n]//g;
  379.     }
  380.     dreq("fcn-regn");
  381.     my $hold = regeneration_create_hold({ topic => $FORMref->{topic}, action => 'meta' });
  382.     save_meta_tags($FORMref->{topic}, $username, $d, $k, $r, $hold);
  383.     my $q = GetPage($FORMref->{topic}, $FORMref->{topic}, { lock => 1 });
  384.     $q->{meta_description} = $d;
  385.     $q->{meta_keywords} = $k;
  386.     $q->{meta_robots} = $r;
  387.     SetPage($q, { unlock => 1 });
  388.     topic_management_handler($FORMref, $username, "p", undef, $FORMref->{topic});
  389. }
  390.  
  391. ###
  392. ### save_meta_tags
  393. ###
  394. ### Sets META tags in the topic
  395. ###
  396.  
  397. sub save_meta_tags {
  398.     my ($topic, $user, $descr, $keyword, $robot, $hold) = @_;
  399.     dreq("fcn-regn");
  400.     my $chgfile = regeneration_create_change_process_file("regen_meta_tag_change", $descr, $keyword, $robot);
  401.     my %z = map { $_ , 1 } split(/,/, $topic);
  402.     regenerate_board({ topic => \%z, hold => $hold, action => "regen5", username => $user, changefile => $chgfile, operation => 8, description => 801 });
  403. }
  404.  
  405. ###
  406. ### reorder_topics
  407. ###
  408. ### Puts the topics in whatever order you specify.
  409. ###
  410.  
  411. sub reorder_topics {
  412.     my ($order) = @_;
  413.     dreq("topic-pg");
  414.     my $topic_page = read_topic_page( { lock => 1 } );
  415.     my @topic_sort = sort {$order->{ $a->{number} } <=> $order->{ $b->{number} } } @{ $topic_page->{topics} };
  416.     $topic_page->{topics} = \@topic_sort;
  417.     $topic_page->{'unlock'} = 1;
  418.     write_topic_page($topic_page);
  419.     undef my @new_tree;
  420.     undef my $tree_line;
  421.     my $treeref = readfile("$DCONF->{admin_dir}/tree.txt", "reorder_topics", { no_unlock => 1 });
  422.     foreach my $treeline (@{$treeref}) {
  423.         my @c = split(/\t/, $treeline, 3);
  424.         $tree_line->{ $c[1] } = $treeline;
  425.     }
  426.     foreach my $ts (@topic_sort) {
  427.         push (@new_tree, $tree_line->{ $ts->{number} });
  428.     }
  429.     writefile("$DCONF->{admin_dir}/tree.txt", \@new_tree, "reorder_topics", { no_lock => 1 });
  430. }
  431.  
  432. ###
  433. ### set_category_properties
  434. ###
  435. ### Saves changes to category properties (name, background color, description).
  436. ###
  437.  
  438. sub set_category_properties {
  439.     my ($arg) = @_;
  440.     dreq("topic-pg");
  441.     my $input = read_topic_page( { lock => 1} );
  442.     my $number = $arg->{number};
  443.     if (defined($arg->{editor})) {
  444.         my $m = (@{ $input->{topics} })[ $arg->{editor} ];
  445.         undef my $hashref;
  446.         $hashref->{'text'} = (defined($arg->{text}) ? $arg->{text} : $m->{'text'});
  447.         $hashref->{'bgcolor'} = (defined($arg->{bgcolor}) ? $arg->{bgcolor} : $m->{'bgcolor'});
  448.         $hashref->{'descr'} = (defined($arg->{descr}) ? $arg->{descr} : $m->{'descr'});
  449.         $hashref->{'number'} = $number;
  450.         $input->{topics}[ $arg->{editor} ] = $hashref;
  451.     } else {
  452.         foreach my $x (@{ $input->{topics} }) {
  453.             if ($x->{number} == $number) {
  454.                 $x->{'text'} = (defined($arg->{text}) ? $arg->{text} : $x->{'text'});
  455.                 $x->{'bgcolor'} = (defined($arg->{bgcolor}) ? $arg->{bgcolor} : $x->{'bgcolor'});
  456.                 $x->{'descr'} = (defined($arg->{descr}) ? $arg->{descr} : $x->{'descr'});
  457.                 last;
  458.             }
  459.         }
  460.     }
  461.     $input->{unlock} = 1;
  462.     return write_topic_page($input);
  463. }
  464.  
  465. ###
  466. ### set_topic_properties
  467. ###
  468. ### Saves topic properties (hidden/visible, name, icon, etc.)
  469. ###
  470.  
  471. sub set_topic_properties {
  472.     my ($arg) = @_;
  473.     my %z = map {$_, 1} split(/,/, $arg->{topic_number});
  474.     my $regeneration = 0;
  475. #    if ($arg->{topic_name} ne $arg->{orig}->{topic_name} || $arg->{icon} ne $arg->{orig}->{icon} || $arg->{hidden} != $arg->{orig}->{hidden}) {
  476.     if (1) {
  477.         my %tl = undef;
  478.         my $tree_main = readfile("$DCONF->{admin_dir}/tree.txt", "set_topic_properties", { no_unlock => 1 } );
  479.         my $save_properties = "";
  480.         foreach my $x (@{ $tree_main }) {
  481.             my $y = tree_line_as_hash($x);
  482.             $tl{$y->{topic}} = $y;
  483.             if ($z{$y->{topic}}) {
  484.                 $tl{$y->{topic}}->{name} = $arg->{topic_name} if defined $arg->{topic_name};
  485.                 $tl{$y->{topic}}->{props} = $arg->{orig}->{props};
  486.                 $tl{$y->{topic}}->{props}->{hidden} = 0 + $arg->{hidden};
  487.                 $tl{$y->{topic}}->{props}->{icon} = $arg->{icon} if $arg->{icon} ne "";
  488.                 undef $tl{$y->{topic}}->{properties};
  489.                 $x = (generate_tree_line($tl{$y->{topic}}))[0];
  490.                 $save_properties = (split(/\t/, $x))[8];
  491.             }
  492.             $tl{$y->{topic}} = $x;
  493.         }
  494.         writefile("$DCONF->{admin_dir}/tree.txt", $tree_main, "set_topic_properties", { no_lock => 1 } );
  495.         foreach my $num (keys(%z)) {
  496.             my $tree_tpc = readfile("$DCONF->{admin_dir}/msg_index/$num-tree.txt", "set_topic_properties", { no_unlock => 1 } );
  497.             $tree_tpc->[0] = $tl{$num};
  498.             writefile("$DCONF->{admin_dir}/msg_index/$num-tree.txt", $tree_tpc, "set_topic_properties", { no_lock => 1 } );
  499.             my $topic_file = GetPage($num,$num,{lock => 1});
  500.             $topic_file->{pginfo}->{headers_asstring} = "";
  501.             $topic_file->{headers_asstring} = "";
  502.             $topic_file->{head}->{topic_name} = $arg->{topic_name} if defined $arg->{topic_name};
  503.             $topic_file->{head}->{me_name} = $arg->{topic_name} if defined $arg->{topic_name};
  504.             $topic_file->{head}->{properties} = $save_properties;
  505.             SetPage($topic_file, { unlock => 1 });
  506.             $regeneration = 1 if (defined $arg->{topic_name} && scalar(@{ $topic_file->{sublist} }) > 0 && $arg->{topic_name} ne $arg->{orig}->{topic_name});
  507.         }
  508.     }
  509.     dreq("topic-pg");
  510.     my $input = read_topic_page( { lock => 1 } );
  511.     foreach my $x (@{ $input->{topics} }) {
  512.         if ($z{$x->{number}}) {
  513.             $x->{'descr'} = (defined($arg->{descr}) ? $arg->{descr} : $x->{'descr'});
  514.         }
  515.     }
  516.     $input->{unlock} = 1;
  517.     write_topic_page($input);
  518.     return 1;
  519. }
  520.  
  521. #######################################################################
  522. # INTERNAL FUNCTIONS                                                  #
  523. #                                                                     #
  524. # These functions are used internally by the program and are not      #
  525. # designed to be called independently from any other scripts.         #
  526. #######################################################################
  527.  
  528. ###
  529. ### topic_add_category_handler
  530. ###
  531. ### Handles form input to add a new category
  532. ###
  533.  
  534. sub topic_add_category_handler {
  535.     my ($FORMref, $username) = @_;
  536.     undef my $arg;
  537.     $arg->{'bgcolor'} = $FORMref->{bgcolor};
  538.     dreq("webtags");
  539.     my ($messages, $formatted) = webtags($FORMref->{cat_text}, 3, 1, 1, 1);
  540.     if ($messages eq "!Error") {
  541.         error_message("Add Category Error - Problem with Text", $formatted, 0, 1);
  542.     } else {
  543.         $arg->{'text'} = $formatted;
  544.     }
  545.     if ($FORMref->{cat_descr}) {
  546.         ($messages, $formatted) = webtags($FORMref->{cat_descr}, 3, 1, 1, 1);
  547.         if ($messages eq "!Error") {
  548.             error_message("Add Category Error - Problem with Description", $formatted, 0, 1);
  549.         } else {
  550.             $arg->{'descr'} = $formatted;
  551.         }
  552.     } else {
  553.         $arg->{'descr'} = undef;
  554.     }
  555.     $arg->{'bgcolor'} =~ s/[^#\w\s]//g;
  556.     $arg->{'place'} = $FORMref->{place};
  557.     add_category($arg);
  558.     topic_manager($FORMref, $username, { menu => 2, what => 5 });
  559. }
  560.  
  561. ###
  562. ### topic_add_topic_handler
  563. ###
  564. ### Handles form input to add a new topic
  565. ###
  566.  
  567. sub topic_add_topic_handler {
  568.     my ($FORMref, $username) = @_;
  569.     my $arg = {};
  570.     dreq("webtags");
  571.     my ($messages, $formatted) = webtags($FORMref->{topic_name}, 3, 1, 1, 1);
  572.     if ($messages eq "!Error") {
  573.         error_message("Add Topic Error - Problem with Text", $formatted, 0, 1);
  574.     } else {
  575.         $arg->{'name'} = $formatted;
  576.     }
  577.     if ($FORMref->{descr}) {
  578.         ($messages, $formatted) = webtags($FORMref->{descr}, 3, 1, 1, 1);
  579.         if ($messages eq "!Error") {
  580.             error_message("Add Category Error - Problem with Description", $formatted, 0, 1);
  581.         } else {
  582.             $arg->{'descr'} = $formatted;
  583.         }
  584.     } else {
  585.         $arg->{'descr'} = undef;
  586.     }
  587.     foreach my $x ('readpriv', 'postpriv', 'content', 'place') {
  588.         $arg->{$x} = 0 + $FORMref->{$x};
  589.     }
  590.     add_topic($arg, $FORMref);
  591.     topic_manager($FORMref, $username, { menu => 1, what => 4 });
  592. }
  593.  
  594. ###
  595. ### topic_management_handler
  596. ###
  597. ### Handles form input from actions on the topics list
  598. ###
  599.  
  600. sub topic_management_handler {
  601.     my ($FORMref, $username, $selection, $stuff, $number) = @_;
  602.     my $subst = {};
  603.     $subst->{topics} = board_topics();
  604.     $subst->{stuff} = $stuff;
  605.     $selection = $FORMref->{SELECTION_action} if $selection eq "";
  606.     $number = $FORMref->{SELECTION_who} if $number eq "";
  607.     my %p = $number eq '*' ? map { $_, 1 } split(/,/, $FORMref->{MARK}) : map { $_, 1 } split(/,/, $number);
  608.     my $type = {};
  609.     foreach my $topic (@{ $subst->{topics} }) {
  610.         $type->{ $topic->{number} } = $topic->{type};
  611.     }
  612.     if ($selection eq "d") {
  613.         my $count = 0;
  614.         undef my $J;
  615.         foreach my $K (keys(%p)) {
  616.             $J->{$K} = 1 if $type->{$K} == 1 || $type->{$K} == 2;
  617.             $subst->{'delete'}->{'error'} = 1 if ! defined($J->{$K});
  618.         }
  619.         $count += delete_topic($J) if defined($J);
  620.         topic_manager($FORMref, $username, { what => 1, count => $count });
  621.     } elsif ($selection eq "a") {
  622.         my @q = grep ($type->{$_} == 1, keys(%p));
  623.         error_message("Topic Privilege Assign Error", "You must select at least one topic to assign privileges (categories don't have privileges).", 0, 1) if scalar(@q) == 0;
  624.         topic_privileges_screen(join(",", @q), $username);
  625.     } elsif ($selection eq "p") {
  626.         my @z = grep ($p{$_->{number}} == 1, @{$subst->{topics}});
  627.         error_message("Property Screen Error", "You did not check any of the topics on the list!", 0, 1) if scalar(@z) == 0;
  628.         if (scalar(@z) > 1) {
  629.             @z = grep ($_->{type} == 1, @z);
  630.             error_message("Property Screen Error", "No properties can be set simultaneously for multiple categories!", 0, 1) if scalar(@z) == 0;
  631.         }
  632.         $subst->{stuff}->{what} = 4 if $FORMref->{renamed};
  633.         $subst->{stuff}->{what} = 3 if $FORMref->{metasave};
  634.         if (scalar(@z) > 1) {
  635.             $subst->{general}->{multiple} = 1;
  636.             $subst->{'seltopic'} = $z[0];
  637.             $subst->{general}->{username} = $username;
  638.             $subst->{general}->{topics} = join(",", map { $_->{number} } @z);
  639.             $subst->{'meta'}->{'meta_description'} = undef;
  640.             $subst->{'meta'}->{'meta_keywords'} = undef;
  641.             $subst->{'meta'}->{'meta_robots'} = undef;
  642.             $subst->{'props'} = {};
  643.             foreach my $q (@z) {
  644.                 my $href = GetPage($q->{number}, $q->{number});
  645.                 foreach my $mt ('meta_description', 'meta_keywords', 'meta_robots') {
  646.                     if (defined $subst->{'meta'}->{$mt} && $href->{$mt} =~ /\S/) {
  647.                         if ($href->{$mt} ne $subst->{'meta'}->{$mt}) {
  648.                             $subst->{'meta'}->{$mt} = "";
  649.                         }
  650.                     } elsif ($href->{$mt} =~ /\S/) {
  651.                         $subst->{'meta'}->{$mt} = $href->{$mt};
  652.                     }
  653.                 }
  654.                 foreach my $pr ('hidden', 'icon') {
  655.                     if (defined $subst->{'props'}->{$pr} && $q->{$pr} =~ /\S/) {
  656.                         if ($q->{$pr} ne $subst->{props}->{$pr}) {
  657.                             $subst->{'props'}->{$pr} = "";
  658.                         }
  659.                     } elsif ($q->{$pr} =~ /\S/) {
  660.                         $subst->{'props'}->{$pr} = $q->{$pr};
  661.                     }
  662.                 }
  663.             }
  664.         } else {
  665.             $subst->{'seltopic'} = $z[0];
  666.             $number = $z[0]->{number};
  667.             $subst->{general}->{username} = $username;
  668.             error_message("Property Screen Error", "Topic/Category not found on topics page!", 0, 1) if ! defined $subst->{'seltopic'};
  669.             dreq("webtags");
  670.             if ($subst->{seltopic}->{type} == 2) {
  671.                 $subst->{'edit'}->{'cat_text'} = inverse_webtags($subst->{seltopic}->{text}, undef, 1);
  672.                 $subst->{'edit'}->{'cat_descr'} = inverse_webtags($subst->{seltopic}->{descr}, undef, 1);
  673.             } else {
  674.                 my $href = GetPage($number, $number);
  675.                 $subst->{'edit'}->{'topic_name'} = inverse_webtags($subst->{seltopic}->{name}, undef, 1);
  676.                 $subst->{'edit'}->{'descr'} = inverse_webtags($subst->{seltopic}->{descr}, undef, 1);
  677.                 foreach my $pr ('hidden', 'icon') {
  678.                     $subst->{'props'}->{$pr} = $subst->{'seltopic'}->{$pr};
  679.                 }
  680.                 $subst->{'meta'}->{'meta_description'} = $href->{'meta_description'};
  681.                 $subst->{'meta'}->{'meta_keywords'} = $href->{'meta_keywords'};
  682.                 $subst->{'meta'}->{'meta_robots'} = $href->{'meta_robots'};
  683.             }
  684.         }
  685.         if (defined $subst->{'meta'}->{'meta_robots'}) {
  686.             my $s = $subst->{'meta'}->{'meta_robots'};
  687.             if ($s !~ /\S/) {
  688.                 $subst->{'meta'}->{'meta_robots'} = 0;
  689.             } elsif ($s =~ /^noindex,nofollow/i) {
  690.                 $subst->{'meta'}->{'meta_robots'} = 1;
  691.             } elsif ($s =~ /^index,follow/i) {
  692.                 $subst->{'meta'}->{'meta_robots'} = 2;
  693.             } else {
  694.                 $subst->{'meta'}->{'meta_robots'} = 3;
  695.                 $subst->{'meta'}->{'meta_robots_text'} = $s;
  696.             }
  697.         }
  698.         screen_out("tpcprops", $subst);
  699.     } elsif ($selection eq 'r') {
  700.         my $order = {};
  701.         foreach my $x (keys(%{ $FORMref })) {
  702.             next if $x !~ m|^ORDER(\d+)|;
  703.             $order->{$1} = $FORMref->{$x};
  704.         }
  705.         reorder_topics($order);
  706.         topic_manager($FORMref, $username, { what => 3 });
  707.     }
  708. }
  709.  
  710. ###
  711. ### topic_manager
  712. ###
  713. ### Displays the Topic Manager
  714. ###
  715.  
  716. sub topic_manager {
  717.     my ($FORMref, $username, $stuff) = @_;
  718.     my $subst = {};
  719.     $subst->{stuff} = $stuff;
  720.     $subst->{'general'}->{'url'} = "$PARAMS->{cgiurl}?username=$FORMref->{username}&action=topic_mgr";
  721.     $subst->{'general'}->{'menu'} = (defined $stuff->{menu} ? $stuff->{menu} : $FORMref->{menu});
  722.     $subst->{'topics'} = board_topics(undef, undef, undef, undef, 1);
  723.     $subst->{'general'}->{'username'} = $username;
  724.     my @a2z = sort { $a->{name} cmp $b->{name} } @{ $subst->{topics} };
  725.     $subst->{general}->{menu} = 1 if $FORMref->{menu} eq "" && scalar @a2z == 0;
  726.     undef my @a2z_js;
  727.     foreach my $x (@a2z) {
  728.         undef my $hashref;
  729.         $hashref->{text} = "document.tf.ORDER$x->{number}.value";
  730.         $hashref->{numonly} = $x->{number};
  731.         push (@a2z_js, $hashref);
  732.     }
  733.     $subst->{'a2z_js'} = \@a2z_js;
  734.     my @by_date = sort { $b->{lastmod} <=> $a->{lastmod} } @{ $subst->{topics} };
  735.     undef my @by_date_js;
  736.     foreach my $xb (@by_date) {
  737.         undef my $hashref;
  738.         $hashref->{text} = "document.tf.ORDER$xb->{number}.value";
  739.         $hashref->{numonly} = $xb->{number};
  740.         push (@by_date_js, $hashref);
  741.     }
  742.     $subst->{'date_js'} = \@by_date_js;
  743.     header();
  744.     print templ_int("topicmgr", $subst);
  745.     program_exit(0);
  746. }
  747.  
  748. ###
  749. ### topic_privileges_save
  750. ###
  751. ### Saves topic editing privileges
  752. ###
  753.  
  754. sub topic_privileges_save {
  755.     my ($topics, $moderators) = @_;
  756.     dreq("fcn-priv");
  757.     my @actions = ({ topic => $topics, moderator => $moderators, action => 'set_equal' });
  758.     write_privilege_file(\@actions);
  759. }
  760.  
  761. ###
  762. ### topic_category_properties_handle
  763. ###
  764. ### Handle form input to save topic categories
  765. ###
  766.  
  767. sub topic_category_properties_handle {
  768.     my ($topics, $FORMref) = @_;
  769.     my $number = $FORMref->{topic};
  770.     undef my $this_line;
  771.     my $ctr = 0;
  772.     foreach my $x ( @{ $topics } ) {
  773.         if ($x->{number} eq $number) {
  774.             $this_line = $x;
  775.             last;
  776.         }
  777.         $ctr++;
  778.     }
  779.     error_message("Edit Category Error", "Category does not exist!", 0, 1) if $this_line->{type} != 2;
  780.     undef my $arg;
  781.     dreq("webtags");
  782.     my ($messages, $formatted) = webtags($FORMref->{cat_text}, 3, 1, 1, 1);
  783.     if ($messages eq "!Error") {
  784.         error_message("Edit Category Error - Problem with Text", $formatted, 0, 1);
  785.     } else {
  786.         $arg->{'text'} = $formatted;
  787.     }
  788.     if (defined $FORMref->{cat_descr}) {
  789.         ($messages, $formatted) = webtags($FORMref->{cat_descr}, 1, 1, 1, 1);
  790.         if ($messages eq "!Error") {
  791.             error_message("Edit Category Error - Problem with Description", $formatted, 0, 1);
  792.         } else {
  793.             $arg->{'descr'} = $formatted;
  794.         }
  795.     } else {
  796.         $arg->{'descr'} = undef;
  797.     }
  798.     $arg->{'editor'} = $ctr;
  799.     $arg->{'bgcolor'} = $FORMref->{'bgcolor'};
  800.     $arg->{'bgcolor'} =~ s/[^#\w\s]//g;
  801.     $arg->{'number'} = $number;
  802.     return $arg;
  803. }
  804.  
  805. ###
  806. ### topic_properties_handle
  807. ###
  808. ### Handle form input to save topic privileges
  809. ###
  810.  
  811. sub topic_properties_handle {
  812.     my ($topics, $FORMref) = @_;
  813.     my @z = grep ($_->{type} == 1, @{$topics});
  814.     my %z = map { $_, 1 } split(/,/, $FORMref->{topic});
  815.     my @t = grep ( $z{ $_->{number} } == 1, @z);
  816.     error_message("Invalid Topic Number", "Requested topic does not exist [tph1]!", 0, 1) if scalar(@t) == 0;
  817.     my $param = {};
  818.     my $tx = {};
  819.     if (scalar(@t) == 1) {
  820.         dreq("webtags");
  821.         if ($FORMref->{topic_name} ne "") {
  822.             my ($messages, $formatted) = webtags($FORMref->{topic_name}, 3, 1, 1, 1);
  823.             if ($messages eq "!Error") {
  824.                 error_message("Topic Name Error - Problem with Text", $formatted, 0, 1);
  825.             } else {
  826.                 $param->{'topic_name'} = $formatted;
  827.             }
  828.         } else {
  829.             $param->{'topic_name'} = $tx->{name};
  830.         }
  831.         if ($FORMref->{descr} ne "") {
  832.             my ($messages, $formatted) = webtags($FORMref->{descr}, 1, 1, 1, 1);
  833.             if ($messages eq "!Error") {
  834.                 error_message("Topic Description Error - Problem with Text", $formatted, 0, 1);
  835.             } else {
  836.                 $param->{'descr'} = $formatted;
  837.             }
  838.         } else {
  839.             $param->{'descr'} = "";
  840.         }
  841.     }
  842.     $param->{'hidden'} = 0 + $FORMref->{'hide'};
  843.     $param->{'icon'} = $FORMref->{'icon'};
  844.     $param->{'topic_number'} = $FORMref->{topic};
  845.     $param->{'number'} = $FORMref->{topic};
  846.     $param->{'orig'} = $tx;
  847.     return $param;
  848. }
  849.  
  850. ###
  851. ### topic_privileges_screen
  852. ###
  853. ### Assign moderator editing privilegs
  854. ###
  855.  
  856. sub topic_privileges_screen {
  857.     my ($topics, $username) = @_;
  858.     dreq("fcn-priv");
  859.     my $filecache = read_privilege_file();
  860.     my $subst = {};
  861.     my $mod = read_account_file("passwd", undef, { returnformat => 'single_array' });
  862.     my @mod = ();
  863.     my @gs = split(/,/, $topics);
  864.     foreach my $x (@{ $mod }) {
  865.         undef my $i;
  866.         $i->{user} = $x->{user};
  867.         $i->{name} = $x->{fullname};
  868.         my $c = 0;
  869.         foreach my $g (@gs) {
  870.             $c += check_topic_authorization($x->{user}, $g, $filecache);
  871.         }
  872.         $i->{checked} = ($c >= scalar(@gs) ? 1 : 0);
  873.         push (@mod, $i);
  874.     }
  875.     @mod = sort { $a->{user} cmp $b->{user} } @mod;
  876.     $subst->{moderators} = \@mod;
  877.     $subst->{general}->{mods} = scalar(split(/,/, $topics));
  878.     $subst->{general}->{screen} = 1;
  879.     $subst->{general}->{username} = $username;
  880.     $subst->{general}->{affect} = $topics;
  881.     if ($topics =~ /^\d+$/) {
  882.         my $href = GetPage($topics, $topics);
  883.         $subst->{general}->{thistopic_name} = $href->{head}->{topic_name};
  884.     }
  885.     screen_out("grpmodas", $subst);
  886. }
  887.  
  888. ###
  889. ### topic_error_touch
  890. ###
  891. ### Initializes a file (and returns an error code if it could not)
  892. ###
  893.  
  894. sub topic_error_touch {
  895.     my ($filename) = @_;
  896.     if (open(FILE, "> $filename")) {
  897.         close (FILE);
  898.         chmod(oct($DCONF->{'perms0666'}), $filename);
  899.         return undef;
  900.     } else {
  901.         return $!;
  902.     }
  903. }
  904.  
  905. 1;
  906.