Update of /cvs/scoop/scoop/struct
In directory sodium.sabren.com:/tmp/cvs-serv5844/struct

Modified Files:
	scoop.sql 
Log Message:

New flexible user preferences stuff.

-janra



Index: scoop.sql
===================================================================
RCS file: /cvs/scoop/scoop/struct/scoop.sql,v
retrieving revision 1.198
retrieving revision 1.199
diff -C2 -d -r1.198 -r1.199
*** scoop.sql	18 Jul 2004 19:45:49 -0000	1.198
--- scoop.sql	4 Aug 2004 21:49:48 -0000	1.199
***************
*** 155,158 ****
--- 155,159 ----
  INSERT INTO admin_tools VALUES ('macros',20,'Macros','Macros','edit_macros','edit_macros',0);
  INSERT INTO admin_tools VALUES ('search',50,'Search Admin Tools','Search Admin Tools','admin_search','admin_search',1);
+ INSERT INTO admin_tools VALUES ('prefs',21,'User Preferences','User Preferences','edit_prefs','edit_prefs',0);
  
  #
***************
*** 255,259 ****
  INSERT INTO blocks VALUES ('spell_err','<font color=\"red\">','1','<P>This block is used to format misspelled words if the spellchecking system is installed and active. It should be a complete opening font tag or other formatting tag. It should match its closing tag set in the block <B>spell_err_end</B>.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('spell_err_end','</font>','1','<P>This block is used to format misspelled words if the spellchecking system is installed and active. It should be a closing tag for whatever is in the block <B>spell_err</B>.</P>','Fonts','default','en');
! INSERT INTO blocks VALUES ('new_user_html','%%title_font%%Create New User Account%%title_font_end%%\r\n<H3><CENTER>%%error_font%%%%error%%%%error_font_end%%</CENTER></H3>\r\n\r\n<P>%%norm_font%%In order to create an account (which is free), fill out this form. You will receive an email containing your username and autogenerated password, at the address you provide here. Use this data to login. It\'s that easy.%%norm_font_end%%</P>\r\n\r\n<P>%%norm_font%%Why is the password autogenerated? First, random passwords are typically more secure than non-random ones. Second, by requiring you to log in using a password we send you, we can make sure that the email address is valid. This makes it harder for malicious users to abuse the account creation system by creating an arbitrary number of accounts and spamming the site with stories or comments. If you do not like your autogenerated password, you can easily change it after logging in.%%norm_font_end%%</P>\r\n\r\n<P>%%norm_font%%Ag!
 ain, your password will be mailed to the email address you enter here, so it <B>must</B> work. Do NOT enter a spam-protected or fake email address.%%norm_font_end%%</P>\r\n\r\n<P>%%norm_font%%If you are concerned about privacy, this email does not have to be in any way traceable to you. We will never use the email you provide here for anything else, ever. All it needs to be is working, and accessible to you, at the time the account is created.%%norm_font_end%%</P>\r\n\r\n<P>%%norm_font%%Now get started, and we hope you enjoy %%sitename%%!%%norm_font_end%%</P>\r\n\r\n<FORM NAME=\"adduser\" METHOD=\"post\" ACTION=\"%%rootdir%%/\">\r\n  <INPUT TYPE=\"hidden\" name=\"tool\" VALUE=\"writeuser\">\r\n  <INPUT TYPE=\"hidden\" name=\"op\" VALUE=\"newuser\">\r\n  <INPUT TYPE=\"hidden\" name=\"formkey\" VALUE=\"%%formkey%%\">\r\n\r\n<TABLE>\r\n  <TR>\r\n   <TD>%%norm_font%%Please enter your desired username:</TD>\r\n   <TD>%%norm_font%%<INPUT TYPE=\"text\" NAME=\"nickname\" SIZE=30 VA!
 LUE=\"%%uname%%\">%%norm_font_end%%</TD>\r\n  </TR>\r\n\r\n  <TR>\r\n 
  <TD COLSPAN=2>%%smallfont%%(Legal characters: a-z, A-Z, 0-9, space. Names may not start or end with a space, and may not contain more than one space in a row.)%%smallfont_end%%</TD>\r\n  </TR>\r\n\r\n  <TR>\r\n   <TD>%%norm_font%%and a working email (this will never be made public!):\r\n     <BR><B><FONT COLOR=\"#FF0000\">Check this for typos!</FONT></B>%%norm_font_end%%</TD>\r\n   <TD>%%norm_font%%<INPUT TYPE=\"text\" NAME=\"email\" VALUE=\"%%email%%\" SIZE=30>%%norm_font_end%%</TD>\r\n  </TR>\r\n  <tr>\r\n   <td colspan=2 align=\"right\">%%norm_font%%<input type=\"submit\" value=\"Create Account!\" size=\"30\" />%%norm_font_end%%</td>\r\n  </tr>\r\n</table>\r\n</form>\r\n','1','<P>This block contains the explanation of the account creation process as well as the form the user fills in to create an account. It should be reasonably self-contained.  It must contain the following form elements:</P>\n<DL>\n <DT>FORM</DT>\n  <DD>The form should post to your site\'s rootdir.</D!
 D>\n <DT>op</DT>\n  <DD>This should be a hidden field with a value of \"newuser\".</DD>\n <DT>tool</DT>\n  <DD>This should be a hidden field with a value of \"writeuser\".</DD>\n <DT>formkey</DT>\n  <DD>This should be a hidden field with a value of \"|formkey|\" (see special keys, below).</DD>\n <DT>nickname</DT>\n  <DD>This should be a text field with a default value of \"|uname|\" (see special keys, below).</DD>\n <DT>email</DT>\n  <DD>This should be a text field with a default value of \"|email|\" (see special keys, below).</DD>\n <DT>button</DT>\n  <DD>A submit button to send the fields in.</DD>\n</DL>\n<P>The following special keys are recognized:</P>\n<DL>\n <DT>error</DT>\n  <DD>Any error messages (such as invalid characters in the nickname field).</DD>\n <DT>uname</DT>\n  <DD>Usually blank; if there is an error with the email field, this is the nickname entered by the user.</DD>\n <DT>email</DT>\n  <DD>Usually blank; if there is an error with the nickname field, thi!
 s is the email address entered by the user.</DD>\n <DT>formkey</DT>\n 
 <DD>A code-generated formkey used to hinder scripts trying to make large numbers of accounts.</DD>\n</DL>','General','default','en');
  INSERT INTO blocks VALUES ('new_advertiser_html','%%title_font%%Upgrade to an Advertiser Account%%title_font_end%%\r\n<H3><CENTER>%%error_font%%%%error%%%%error_font_end%%</CENTER></H3>\r\n\r\n<P>%%norm_font%%Since you have expressed an interest in advertising on this site, I\'ll be needing a bit more information about you, for billing purposes.%%norm_font_end%%</P>\r\n<P>%%norm_font%% %%advertising_account_disclaimer%% %%norm_font_end%%</P>\r\n\r\n<form name=\"adduser\" method=\"post\" action=\"%%rootdir%%\">\r\n<input type=\"hidden\" name=\"tool\" value=\"writeuser\">\r\n<input type=\"hidden\" name=\"op\" value=\"newuser\">\r\n<input type=\"hidden\" name=\"formkey\" value=\"%%formkey%%\">\r\n<input type=\"hidden\" name=\"advertiser\" value=\"1\">\r\n\r\n<TABLE>\r\n <TR>\r\n  <TD align=\"right\">%%norm_font%%Your Name:%%norm_font_end%%</TD>\r\n  <TD align=\"left\"><input type=\"text\" name=\"realname\" value=\"%%yourname%%\" size=\"30\"></TD>\r\n </TR>\r\n <TR>\r\n  <TD a!
 lign=\"right\">%%norm_font%%Business name:%%norm_font_end%%</TD>\r\n  <TD align=\"left\"><input type=\"text\" name=\"bizname\" value=\"%%bizname%%\" size=\"40\"></TD>\r\n </TR>\r\n <TR>\r\n  <TD align=\"right\">%%norm_font%%Contact phone number:%%norm_font_end%%</TD>\r\n  <TD align=\"left\"><input type=\"text\" name=\"bizphone\" value=\"%%bizphone%%\" size=\"12\"></TD>\r\n </TR>\r\n <TR>\r\n  <TD align=\"right\">%%norm_font%%Mailing Address:%%norm_font_end%%</TD>\r\n  <TD align=\"left\"><textarea cols=\"30\" rows=\"5\" name=\"snailmail\" value=\"%%snailmail%%\"></textarea></TD>\r\n </TR>\r\n <tr>\r\n  <td colspan=2 align=\"right\">%%norm_font%%<input type=\"submit\" value=\"Create Account!\" size=\"30\">\r\n%%norm_font_end%%</td>\r\n </tr>\r\n</table>\r\n</form>','1','<P>This block is displayed on the account signup page if the user is creating an advertising account. This is yet another unimplemented ad feature. Advertising accounts are only partly implemented; for now, th!
 ere is no automated way to collect extra information from advertisers.
</P>','Ads','default','en');
  INSERT INTO blocks VALUES ('advertising_account_disclaimer','<P>Please remember the following with your new advertising account.</P>\r\n\r\n<P><b>Any stories posted to this site for purely advertising purposes will void your contract with us.</b> The articles and diaries on this site are <b>not for advertising purposes</b>.  This account entitles you to submit ads for posting in specified places on the page only.  If you are caught abusing this account, you\'re ads will be disabled, no money will be refunded, and your account will be disabled.  If you have any questions about this send mail to %%local_email%%.\r\n</P>\r\n\r\n<P>Thank you for your understanding.</P>','1','<P>This block is displayed in the form that collects extra information from advertisers when they create an \"advertiser account\".  It is only relevant if the variable <B>req_extra_advertiser_info</B> is set to 1.  It should contain whatever extra terms your site requires of an advertising account, if the!
 y are distinguished from regular accounts.  There are no special keys.</P>','Ads','default','en');
--- 256,260 ----
  INSERT INTO blocks VALUES ('spell_err','<font color=\"red\">','1','<P>This block is used to format misspelled words if the spellchecking system is installed and active. It should be a complete opening font tag or other formatting tag. It should match its closing tag set in the block <B>spell_err_end</B>.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('spell_err_end','</font>','1','<P>This block is used to format misspelled words if the spellchecking system is installed and active. It should be a closing tag for whatever is in the block <B>spell_err</B>.</P>','Fonts','default','en');
! INSERT INTO blocks VALUES ('new_user_html','%%title_font%%Create New User Account%%title_font_end%%\r\n<H3><CENTER>%%error_font%%%%error%%%%error_font_end%%</CENTER></H3>\r\n\r\n<P>%%norm_font%%In order to create an account (which is free), fill out this form. You will receive an email containing your username and autogenerated password, at the address you provide here. Use this data to login. It\'s that easy.%%norm_font_end%%</P>\r\n\r\n<P>%%norm_font%%Why is the password autogenerated? First, random passwords are typically more secure than non-random ones. Second, by requiring you to log in using a password we send you, we can make sure that the email address is valid. This makes it harder for malicious users to abuse the account creation system by creating an arbitrary number of accounts and spamming the site with stories or comments. If you do not like your autogenerated password, you can easily change it after logging in.%%norm_font_end%%</P>\r\n\r\n<P>%%norm_font%%Ag!
 ain, your password will be mailed to the email address you enter here, so it <B>must</B> work. Do NOT enter a spam-protected or fake email address.%%norm_font_end%%</P>\r\n\r\n<P>%%norm_font%%If you are concerned about privacy, this email does not have to be in any way traceable to you. We will never use the email you provide here for anything else, ever. All it needs to be is working, and accessible to you, at the time the account is created.%%norm_font_end%%</P>\r\n\r\n<P>%%norm_font%%Now get started, and we hope you enjoy %%sitename%%!%%norm_font_end%%</P>\r\n\r\n<FORM NAME=\"adduser\" METHOD=\"post\" ACTION=\"%%rootdir%%/\">\r\n  <INPUT TYPE=\"hidden\" name=\"tool\" VALUE=\"writeuser\">\r\n  <INPUT TYPE=\"hidden\" name=\"op\" VALUE=\"newuser\">\r\n  <INPUT TYPE=\"hidden\" name=\"formkey\" VALUE=\"%%formkey%%\">\r\n\r\n<TABLE>\r\n  <TR>\r\n   <TD>%%norm_font%%Please enter your desired username:</TD>\r\n   <TD>%%norm_font%%<INPUT TYPE=\"text\" NAME=\"nickname\" SIZE=30 VA!
 LUE=\"%%uname%%\">%%norm_font_end%%</TD>\r\n  </TR>\r\n\r\n  <TR>\r\n 
  <TD COLSPAN=2>%%smallfont%%(Legal characters: a-z, A-Z, 0-9, space. Names may not start or end with a space, and may not contain more than one space in a row.)%%smallfont_end%%</TD>\r\n  </TR>\r\n\r\n  <TR>\r\n   <TD>%%norm_font%%and a working email (this will never be made public!):\r\n     <BR><B><FONT COLOR=\"#FF0000\">Check this for typos!</FONT></B>%%norm_font_end%%</TD>\r\n   <TD>%%norm_font%%<INPUT TYPE=\"text\" NAME=\"email\" VALUE=\"%%email%%\" SIZE=30>%%norm_font_end%%</TD>\r\n  </TR>\r\n  <tr>\r\n   <td colspan=2 align=\"right\">%%norm_font%%%%required_prefs%%<br><input type=\"submit\" value=\"Create Account!\" size=\"30\" />%%norm_font_end%%</td>\r\n  </tr>\r\n</table>\r\n</form>\r\n','1','<P>This block contains the explanation of the account creation process as well as the form the user fills in to create an account. It should be reasonably self-contained.  It must contain the following form elements:</P>\n<DL>\n <DT>FORM</DT>\n  <DD>The form should post to yo!
 ur site\'s rootdir.</DD>\n <DT>op</DT>\n  <DD>This should be a hidden field with a value of \"newuser\".</DD>\n <DT>tool</DT>\n  <DD>This should be a hidden field with a value of \"writeuser\".</DD>\n <DT>formkey</DT>\n  <DD>This should be a hidden field with a value of \"|formkey|\" (see special keys, below).</DD>\n <DT>nickname</DT>\n  <DD>This should be a text field with a default value of \"|uname|\" (see special keys, below).</DD>\n <DT>email</DT>\n  <DD>This should be a text field with a default value of \"|email|\" (see special keys, below).</DD>\n <DT>button</DT>\n  <DD>A submit button to send the fields in.</DD>\n</DL>\n<P>The following special keys are recognized:</P>\n<DL>\n <DT>error</DT>\n  <DD>Any error messages (such as invalid characters in the nickname field).</DD>\n <DT>uname</DT>\n  <DD>Usually blank; if there is an error with the email field, this is the nickname entered by the user.</DD>\n <DT>email</DT>\n  <DD>Usually blank; if there is an error with t!
 he nickname field, this is the email address entered by the user.</DD>
\n <DT>formkey</DT>\n  <DD>A code-generated formkey used to hinder scripts trying to make large numbers of accounts.</DD>\n</DL>','General','default','en');
  INSERT INTO blocks VALUES ('new_advertiser_html','%%title_font%%Upgrade to an Advertiser Account%%title_font_end%%\r\n<H3><CENTER>%%error_font%%%%error%%%%error_font_end%%</CENTER></H3>\r\n\r\n<P>%%norm_font%%Since you have expressed an interest in advertising on this site, I\'ll be needing a bit more information about you, for billing purposes.%%norm_font_end%%</P>\r\n<P>%%norm_font%% %%advertising_account_disclaimer%% %%norm_font_end%%</P>\r\n\r\n<form name=\"adduser\" method=\"post\" action=\"%%rootdir%%\">\r\n<input type=\"hidden\" name=\"tool\" value=\"writeuser\">\r\n<input type=\"hidden\" name=\"op\" value=\"newuser\">\r\n<input type=\"hidden\" name=\"formkey\" value=\"%%formkey%%\">\r\n<input type=\"hidden\" name=\"advertiser\" value=\"1\">\r\n\r\n<TABLE>\r\n <TR>\r\n  <TD align=\"right\">%%norm_font%%Your Name:%%norm_font_end%%</TD>\r\n  <TD align=\"left\"><input type=\"text\" name=\"realname\" value=\"%%yourname%%\" size=\"30\"></TD>\r\n </TR>\r\n <TR>\r\n  <TD a!
 lign=\"right\">%%norm_font%%Business name:%%norm_font_end%%</TD>\r\n  <TD align=\"left\"><input type=\"text\" name=\"bizname\" value=\"%%bizname%%\" size=\"40\"></TD>\r\n </TR>\r\n <TR>\r\n  <TD align=\"right\">%%norm_font%%Contact phone number:%%norm_font_end%%</TD>\r\n  <TD align=\"left\"><input type=\"text\" name=\"bizphone\" value=\"%%bizphone%%\" size=\"12\"></TD>\r\n </TR>\r\n <TR>\r\n  <TD align=\"right\">%%norm_font%%Mailing Address:%%norm_font_end%%</TD>\r\n  <TD align=\"left\"><textarea cols=\"30\" rows=\"5\" name=\"snailmail\" value=\"%%snailmail%%\"></textarea></TD>\r\n </TR>\r\n <tr>\r\n  <td colspan=2 align=\"right\">%%norm_font%%<input type=\"submit\" value=\"Create Account!\" size=\"30\">\r\n%%norm_font_end%%</td>\r\n </tr>\r\n</table>\r\n</form>','1','<P>This block is displayed on the account signup page if the user is creating an advertising account. This is yet another unimplemented ad feature. Advertising accounts are only partly implemented; for now, th!
 ere is no automated way to collect extra information from advertisers.
</P>','Ads','default','en');
  INSERT INTO blocks VALUES ('advertising_account_disclaimer','<P>Please remember the following with your new advertising account.</P>\r\n\r\n<P><b>Any stories posted to this site for purely advertising purposes will void your contract with us.</b> The articles and diaries on this site are <b>not for advertising purposes</b>.  This account entitles you to submit ads for posting in specified places on the page only.  If you are caught abusing this account, you\'re ads will be disabled, no money will be refunded, and your account will be disabled.  If you have any questions about this send mail to %%local_email%%.\r\n</P>\r\n\r\n<P>Thank you for your understanding.</P>','1','<P>This block is displayed in the form that collects extra information from advertisers when they create an \"advertiser account\".  It is only relevant if the variable <B>req_extra_advertiser_info</B> is set to 1.  It should contain whatever extra terms your site requires of an advertising account, if the!
 y are distinguished from regular accounts.  There are no special keys.</P>','Ads','default','en');
***************
*** 340,348 ****
  INSERT INTO blocks VALUES ('box_title_font','<H2>',NULL,'<P>This block is used in box templates before the box title.  It should be a complete opening font or text style indicator, such as a font or b tag.  It must be properly closed by the contents of the block <B>box_title_font_end</B>.  There are no special keys.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('title_font_end','</H1>',NULL,'<P>This block is used to format titles. It should be a closing font or other formatting tag. It must match the opening tags in the block <B>title_font</B>.</P>','Fonts','default','en');
- INSERT INTO blocks VALUES ('norm_font_face','verdana, arial, helvetica, sans-serif',NULL,'<P>The default font face used in a user\'s display preferences.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('title_font','<H1>',NULL,'<P>This block is used to format titles. It should be a complete opening font or other formatting tag. It must match the closing tags in the block <B>title_font_end</B>.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('box_title_font_end','</H2>',NULL,'<P>This block is used in box templates after the box title.  It should be a complete closing font or text style indicator, such as a closing font or b tag.  It must properly close the tags opened in the block <B>box_title_font</B>.  There are no special keys.</P>','Fonts','default','en');
! INSERT INTO blocks VALUES ('norm_font_size','2',NULL,'<P>The default font size used in a user\'s display preferences.</P>','Fonts','default','en');
! INSERT INTO blocks VALUES ('norm_font','<FONT FACE=\"verdana, arial, helvetica, sans-serif\" SIZE=2>',NULL,'<P>This block is used extensively in the default install. It should be a complete opening FONT tag. It must match the closing tag set in the block <B>norm_font_end</B>. If it is not a FONT tag, the user-selected font size and face from the display preferences page will not work properly.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('poll_img','pollbar.gif',NULL,'<P>This is the name of the file to use when building the poll image. The file should be in the images directory. The value of this block should not have any path information. The image is stretched horizontally to the desired width, so it should not have any horizontal detail that may be deformed.</P>','Polls','default','en');
  INSERT INTO blocks VALUES ('slogan','Collaborative Media for the Masses',NULL,'<P>This block is used in the browser\'s title bar. It should contain a witty saying that describes your site and should not contain the name of the site or any HTML formatting commands. It is only used on the site\'s index pages.</P>','General','default','en');
--- 341,347 ----
  INSERT INTO blocks VALUES ('box_title_font','<H2>',NULL,'<P>This block is used in box templates before the box title.  It should be a complete opening font or text style indicator, such as a font or b tag.  It must be properly closed by the contents of the block <B>box_title_font_end</B>.  There are no special keys.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('title_font_end','</H1>',NULL,'<P>This block is used to format titles. It should be a closing font or other formatting tag. It must match the opening tags in the block <B>title_font</B>.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('title_font','<H1>',NULL,'<P>This block is used to format titles. It should be a complete opening font or other formatting tag. It must match the closing tags in the block <B>title_font_end</B>.</P>','Fonts','default','en');
  INSERT INTO blocks VALUES ('box_title_font_end','</H2>',NULL,'<P>This block is used in box templates after the box title.  It should be a complete closing font or text style indicator, such as a closing font or b tag.  It must properly close the tags opened in the block <B>box_title_font</B>.  There are no special keys.</P>','Fonts','default','en');
! INSERT INTO blocks VALUES ('norm_font','<FONT FACE=\"verdana, arial, helvetica, sans-serif\" SIZE=2>',NULL,'<P>This block is used extensively in the default install. It should be a complete opening tag, or blank. It must match the closing tag set in the block <B>norm_font_end</b>. The following special keys are recognised:</p>\n<DL>\n <DT>norm_font_face</DT>\n  <DD>The font face specification set in a user\'s prefs or, if not set, the default value for that preference as set in the User Preferences Admin Tool.</DD>\n <DT>norm_font_size</DT>\n  <DD>The font size specification set in a user\'s prefs or, if not set, the default value for that preference as set in the User Preferences Admin Tool.</DD>\n</DL>','Fonts','default','en');
  INSERT INTO blocks VALUES ('poll_img','pollbar.gif',NULL,'<P>This is the name of the file to use when building the poll image. The file should be in the images directory. The value of this block should not have any path information. The image is stretched horizontally to the desired width, so it should not have any horizontal detail that may be deformed.</P>','Polls','default','en');
  INSERT INTO blocks VALUES ('slogan','Collaborative Media for the Masses',NULL,'<P>This block is used in the browser\'s title bar. It should contain a witty saying that describes your site and should not contain the name of the site or any HTML formatting commands. It is only used on the site\'s index pages.</P>','General','default','en');
***************
*** 372,375 ****
--- 371,388 ----
  INSERT INTO blocks VALUES ('comment_preview_msg','%%title_font%%<A NAME=\"here\">Preview Comment</A>%%title_font_end%%','1','<P>This is the \"Preview Comment\" title bar. Make sure it has an anchor named \"here\" in it. There are no special keys.</P>','Comments','default','en');
  INSERT INTO blocks VALUES ('spellcheck_form_item','%%norm_font%%Spellcheck text (will force \"Preview\"): <INPUT TYPE=\"checkbox\" NAME=\"spellcheck\" VALUE=\"on\"%%checked%%>%%norm_font_end%%','1','<P>This is the form element displayed when spellcheck is available. There is one special key, checked, which makes the checkbox pre-checked or not, depending on user action or preferences.</P>','Comments','default','en');
+ INSERT INTO blocks VALUES ('invalid_user_msg','Sorry, I can\'t seem to find that user','1','<P>The error message displayed when somebody requests a page for a user that doesn\'t exist</P>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('selectbox_pref','<DIV class=\"item\">\r\n<P><B>%%required%%%%title%%:</B> %%control%%\r\n<BR>%%description%%</P>\r\n</DIV>','1','<P>The preference item template generally used for selectboxes. This should be a self-contained bit of HTML as it is used to display a single user preference, both on the user info page and the preferences edit forms. The following special keys are recognised:</P>\n<DL>\n <DT>required</DT>\n  <DD>If the preference is required, the contents of <B>required_pref_marker</B>, otherwise blank</DD>\n <DT>title</DT>\n  <DD>The displayed title of the preference, as set in the User Preferences Admin Tool</DD>\n <DT>control</DT>\n  <DD>On the preferences edit form, this is the form field required for the preference, as set in the User Preferences Admin Tool. On the user info page, this is the value of the preference</DD>\n <DT>description</DT>\n  <DD>On the preferences edit form, this is the description as entered in the User Pre!
 ferences Admin Tool. On the user info page, this is not displayed.</DD>\n <DT>allowed_html</DT>\n  <DD>If the preference supports HTML, displays the \"Allowed HTML\" string.</DD>\n</DL>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('text_pref','<DIV class=\"item\">\r\n<P><B>%%required%%%%title%%:</B> %%description%%\r\n<BR>%%allowed_html%%\r\n<BR>%%control%%</P>\r\n</DIV>','1','<P>The preference item template generally used for text boxes. This should be a self-contained bit of HTML as it is used to display a single user preference, both on the user info page and the preferences edit forms. The following special keys are recognised:</P>\n<DL>\n <DT>required</DT>\n  <DD>If the preference is required, the contents of <B>required_pref_marker</B>, otherwise blank</DD>\n <DT>title</DT>\n  <DD>The displayed title of the preference, as set in the User Preferences Admin Tool</DD>\n <DT>control</DT>\n  <DD>On the preferences edit form, this is the form field required for the preference, as set in the User Preferences Admin Tool. On the user info page, this is the value of the preference</DD>\n <DT>description</DT>\n  <DD>On the preferences edit form, this is the description as enter!
 ed in the User Preferences Admin Tool. On the user info page, this is not displayed.</DD>\n <DT>allowed_html</DT>\n  <DD>If the preference supports HTML, displays the \"Allowed HTML\" string.</DD>\n</DL>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('user_admin','<DIV class=\"admin_prefs\">\r\n<P><B>Nickname:</B> <INPUT type=\"text\" length=\"30\" name=\"nickname\" value=\"%%nickname%%\">\r\n</P>\r\n<P><B>User ID:</B> %%uid%%</P>\r\n<P><B>User group:</B> %%BOX,user_group_box,%%perm_group%%%%</P>\r\n<P><B>Original Email:</B> %%origemail%%</P>\r\n<P><B>Created At:</B> %%creation_time%%</P>\r\n<P><B>Original IP:</B> %%creation_ip%%</P>\r\n<P><B>User\'s current mojo:</B> %%mojo%%</P>\r\n</DIV>','1','<P>This block displays admin-only user info on the Protected user preference page. This should be a self-contained block of HTML. It is displayed just above the real email and password fields on the Protected user preference page for users with the <B>edit_user</B> perm only. The following special keys are recognised:</P>\n<DL>\n <DT>nickname</DT>\n  <DD>The nickname of the user being edited</DD>\n <DT>perm_group</DT>\n  <DD>The current group of the user being edited</DD>\n <DT>origemail</DT>\n  <DD>!
 The email address used when the account was created</DD>\n <DT>creation_time</DT>\n  <DD>The date and time the account was created</DD>\n <DT>creation_ip</DT>\n  <DD>The IP address the account was created from</DD>\n <DT>mojo</DT>\n  <DD>The user\'s current mojo</DD>\n</DL>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('user_pass','<DIV class=\"prefs\">\r\n<P><B><font color=\"#ff0000\">Protected settings</font></B>\r\n%%passwd%%\r\n<P><B>Real Email:</B> <INPUT type=\"text\" name=\"realemail\" value=\"%%realemail%%\">\r\n<BR>This is the address that will be used to email forgotten passwords. It will not be shown anywhere. Please do not insert any kind of spam protection here, or you will not be able to get a new password!</P>\r\n\r\n<P><B>New Password:</B> Leave both fields blank for no change. This is asked twice to detect typos.\r\n<BR>New Password: <INPUT TYPE=\"password\" SIZE=\"30\" NAME=\"pass1\">\r\n<BR>Confirm: <INPUT TYPE=\"password\" SIZE=\"30\" NAME=\"pass2\">\r\n</DIV>','1','<P>This block displays the user portion of the Protected user preferences page. The following special keys are recognised:</P>\n<DL>\n <DT>passwd</DT>\n  <DD>The entire form field for password entry. If it is a user\'s first login, the form field is hidden.</DD>\n <DT>realemail</!
 DT>\n  <DD>The current value of the user\'s real email</DD>\n</DL>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('user_info_page','%%title_font%%User Info%%title_font_end%%\r\n%%BOX,userpref_menu%%\r\n<DIV>\r\n%%trusted_msg%%\r\n%%BOX,subscriber%%\r\n%%itemlist%%\r\n</DIV>','1','<P>This block contains the content column template for the displayed user info page. It should be self-contained HTML and contain the page title (the title bar most pages have, just under the header). The following special keys are recognised:</P>\n<DL>\n <DT>trusted_msg</DT>\n  <DD>If the user is trusted and viewing his own user info page, the contents of the block <B>trusted_info_message</B> are displayed.</DD>\n <DT>itemlist</DT>\n  <DD>Those user preferences which are visible and have some value, each formatted by their pref template</DD>\n</DL>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('user_pref_page','%%title_font%%User Preferences: %%page%%%%title_font_end%%\r\n%%BOX,userpref_menu%%\r\n%%message%%\r\n<DIV>\r\n<FORM action=\"%%rootdir%%/user/%%nick%%/prefs/%%page%%\" method=\"post\">\r\n%%formkey%%\r\n\r\n%%itemlist%%\r\n\r\n<INPUT type=\"submit\" name=\"write\" value=\"Save Preferences\">\r\n%%userpref_reset%%\r\n</FORM>\r\n</DIV>','1','<P>This block contains the content column template for the user preference edit pages. It should be self-contained HTML and contain the page title (the title bar most pages have, just under the header). The following special keys are recognised:</P>\n<DL>\n <DT>page</DT>\n  <DD>The name of the preference page currently being edited</DD>\n <DT>nick</DT>\n  <DD>The nickname of the user currently being edited</DD>\n <DT>formkey</DT>\n  <DD>A formkey, for a bit of security (mostly against double-clicks on the save button)</DD>\n <DT>message</DT>\n  <DD>Any status or error messages generated by an!
  attempt to save or reset the preferences</DD>\n <DT>itemlist</DT>\n  <DD>The preferences for this page, formatted by their pref item templates</DD>\n <DT>userpref_reset</DT>\n  <DD>The contents of the block <B>userpref_reset</B> (a reset button) if the current page is anything other than Protected; the Protected page has no reset button.</DD>\n</DL>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('firstlogin_message','<p><b>Welcome to %%sitename%%!</b> As this is your first login, you probably want to change your password below or some of the settings on the other preference pages. None of these changes are required, but we do recommend at least changing your password. Enjoy your stay.</p>\r\n<p>If you don\'t want to make any changes, you can <a href=\"%%rootdir%%/\">go to the front page</a>.</p>','1','<P>This block is displayed at the top of the Protected settings page the first time a user logs in, if the variable <B>show_prefs_on_first_login</B> is on. It should be self-contained HTML that encourages the new user to change his password and explore the other preference pages. There are no special keys.</P>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('formkey_err','Invalid form key. You probably tried to save your settings more than once. Do not hit \"BACK\"! If you are certain that your settings have not been saved, try to save them from this screen.','1','<P>The error message displayed if there is a formkey error, such as a user double-clicking a button or going too long between loading the form and submitting it.</P>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('edit_prefs','%%title_font%%Edit User Preferences%%title_font_end%%\r\n\r\n<P>%%err_font%%%%update_msg%%%%err_font_end%%</P>\r\n\r\n<FORM action=\"%%rootdir%%/admin/prefs\" method=\"post\">\r\n<INPUT type=\"submit\" name=\"save\" value=\"Save\">\r\n<INPUT type=\"submit\" name=\"get\" value=\"Get\">\r\n\r\n<TABLE border=\"0\">\r\n  <TR>\r\n    <TD><B>Select Preference:</B></TD>\r\n    <TD>%%pref_selectbox%%</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD colspan=\"2\"><B>Delete:</B> <INPUT type=\"checkbox\" name=\"delete\" value=\"1\"> Many prefs should be disabled (not deleted) if you want to prevent users from changing them, as Scoop requires their default values in order to run correctly.</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Name:</B></TD>\r\n    <TD><INPUT type=\"text\" size=\"20\" maxlength=\"32\" name=\"prefname\" value=\"%%pref_name%%\"> <B>Enabled:</B><INPUT type=\"checkbox\" name=\"enabled\" value=\"1\"%%pref_enabled%%> <B>Required:</B><INPUT typ!
 e=\"checkbox\" name=\"required\" value=\"1\"%%pref_required%%></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Title:</B></TD>\r\n    <TD><INPUT type=\"text\" size=\"50\" maxlength=\"50\" name=\"title\" value=\"%%pref_title%%\"></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Description:</B>\r\n      <BR>The description may contain any HTML or normal block reference.</TD>\r\n    <TD><TEXTAREA rows=\"%%rows%%\" cols=\"%%cols%%\" name=\"description\">%%pref_desc%%</TEXTAREA></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Default Value:</B></TD>\r\n    <TD><INPUT type=\"text\" size=\"30\" name=\"default_value\" value=\"%%pref_default%%\"></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD colspan=\"2\">&nbsp;</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD colspan=\"2\"><B>Preference Display Settings</B></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Preferences page:</B></TD>\r\n    <TD><INPUT type=\"text\" size=\"20\" maxlength=\"50\" name=\"page\" value=\"%%pref_page%%\"></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Order on page:<!
 /B></TD>\r\n    <TD><INPUT type=\"text\" size=\"5\" maxlength=\"5\" na
me=\"display_order\" value=\"%%pref_order%%\"></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Control to display:</B>\r\n      <BR>Special key <I>value</I> is the current value of the preference</TD>\r\n    <TD><INPUT type=\"text\" size=\"50\" name=\"field\" value=\"%%pref_field%%\"></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Template:</B></TD>\r\n    <TD>%%pref_template%%</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Visible on public user info page?</B></TD>\r\n    <TD><INPUT type=\"checkbox\" name=\"visible\" value=\"1\"%%pref_visible%%></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Formatting to apply to value</B></TD>\r\n    <TD><INPUT type=\"text\" name=\"display_fmt\" value=\"%%pref_fmt%%\" size=\"50\"></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD colspan=\"2\">&nbsp;</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD colspan=\"2\"><B>Requires</B></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Site Control:</B></TD>\r\n    <TD>%%pref_var%%</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Perm to view:</B></TD>\r\n    <TD>%%pre!
 f_perm_view%%</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Perm to edit:</B></TD>\r\n    <TD>%%pref_perm_edit%%</TD>\r\n  </TR>\r\n  <TR>\r\n  <TD><B>Trusted User status:</B></TD>\r\n    <TD><INPUT type=\"checkbox\" name=\"req_tu\" value=\"1\"%%pref_tu%%></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD colspan=\"2\">&nbsp;</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD colspan=\"2\"><B>Validation</B> (blank to allow anything)</TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>HTML allowed?</B></TD>\r\n    <TD><INPUT type=\"checkbox\" name=\"html\" value=\"1\"%%pref_html%%></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Field length:</B></TD>\r\n    <TD><INPUT type=\"text\" size=\"5\" maxlength=\"5\" name=\"length\" value=\"%%pref_length%%\"></TD>\r\n  </TR>\r\n  <TR>\r\n    <TD><B>Regular expression:</B>\r\n      <BR>Perl regexp - but you must escape pipes</TD>\r\n    <TD><INPUT type=\"text\" size=\"50\" name=\"regex\" value=\"%%pref_regex%%\"></TD>\r\n  </TR>\r\n</TABLE>\r\n\r\n<INPUT type=\"submit\" name=\"save\" v!
 alue=\"Save\">\r\n<INPUT type=\"submit\" name=\"get\" value=\"Get\">\r
\n</FORM>\r\n','1','','Admin Pages','default','en');
+ INSERT INTO blocks VALUES ('userpref_reset','<INPUT type=\"submit\" name=\"reset\" value=\"Reset Preferences\">','1','<P>This block contains the reset button for the userpref pages. The button must be named \"reset\" but you can otherwise change how it looks.</p>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('userpref_oldpass_field','You must enter your account password to change protected settings.\r\n<BR><B>Password:</B><INPUT TYPE=\"password\" SIZE=\"30\" NAME=\"verify_me\"></P>\r\n','1','<P>This block is the description and form element in which the user enters his old password to change protected settings. On the user\'s first login, the block <B>userpref_oldpass_hidden</B> is used instead.</P>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('userpref_oldpass_hidden','<INPUT TYPE=\"hidden\" NAME=\"verify_me\" value=\"%%pass%%\">','1','<P>This block is the hidden form element containing the user\'s old password. It is only used on the user\'s first login; the block <B>userpref_oldpass_field</B> is used the rest of the time.</P>','Accounts','default','en');
+ INSERT INTO blocks VALUES ('required_pref_marker','<FONT color=\"#ff0000\">*</FONT>','1','','Accounts','default','en');
  
  #
***************
*** 393,397 ****
  
  INSERT INTO box VALUES ('cron_edit_queue','','#main sub\r\n\r\n# Get the expire time\r\nmy $expire = $S->{UI}->{VARS}->{queue_edit_max_time};\r\nmy $factors = {\r\n	d => \'86400\',\r\n	h => \'3600\',\r\n	m => \'60\',\r\n	s => \'1\'\r\n};\r\n$expire =~ s/([^\\d])$//;\r\nmy $time_sub = $expire * $factors->{$1};\r\n\r\nmy $select = {\r\n	DEBUG => 0,\r\n	WHAT => \"sid, score, time, displaystatus\",\r\n	FROM => \'stories\',\r\n	WHERE => \"displaystatus = -3 AND UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(time) >= $time_sub\",\r\n	ORDER_BY => \'time DESC\'\r\n};\r\n\r\nmy ($rv, $sth) = $S->db_select($select);\r\n\r\nmy $sid_move_to_moderate;\r\nwhile (my $story = $sth->fetchrow_hashref()) {\r\n	# only move if the time has expired\r\n	$sid_move_to_moderate = $story->{sid};\r\n	$S->move_story_to_voting($story->{sid});\r\n}\r\n\r\n$sth->finish();\r\n\r\nreturn 1;\r\n','','empty_box',0);
! INSERT INTO box VALUES ('user_box','Login','my $content;\r\nif ($S->{UID} > 0) {\r\n  if ($S->have_perm(\'moderate\')) {\r\n    my ($nstories, $tstories) = $S->_count_new_sub();\r\n    my $color = \'\';\r\n    my $c_end = \'\';\r\n    if ($nstories) {\r\n       $color = \'<font color=\"#FF0000\"><b>\';\r\n       $c_end = \'</b></font>\';\r\n    }\r\n    $content = qq|\r\n    %%dot%% <a class=\"light\" href=\"%%rootdir%%/modsub\">Moderate Submissions</a> ($tstories/$color$nstories$c_end new)<BR>|;\r\n  }\r\n\r\n  if ($S->{TRUSTLEV} == 2 || $S->have_perm(\'super_mojo\')) {\r\n    $content .= qq{%%dot%% <a class=\"light\" href=\"%%rootdir%%/search?type=comment;hidden_comments=show\">Review Hidden Comments</a><br />};\r\n  }\r\n  \r\n  my $urlnick = $S->urlify($S->{NICK});\r\n  my $diary_link = $S->{UI}->{VARS}->{use_diaries} ? \r\n		qq{\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/diary\">Your Diary</a><br />\r\n      %%dot%% <a class=\"light\" href=\"!
 %%rootdir%%/submitstory/Diary\">New Diary Entry</a><br /> \r\n		} : \'\';\r\n	my $upload_link = ($S->{UI}->{VARS}->{allow_uploads} && ($S->have_perm(\'upload_user\') || $S->have_perm(\'upload_admin\'))) ?\r\n		qq{%%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/files\">Your Files</a><br />} : \'\';\r\n\r\n	my $ad_link = $S->{UI}->{VARS}->{use_ads} ?\r\n		qq{\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/ads\">Your Advertisements</a><br />\r\n	  %%dot%% <a class=\"light\" href=\"%%rootdir%%/submitad\">Submit Ad</a><br />\r\n		} : \'\';\r\n\r\n  $content .= qq|\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick\">User Info</a><br />\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/comments\">Your Comments</a><br />\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/stories\">Your Stories</a><br?>\r\n      $diary_link\r\n	  $ad_link\r\n      $upload_link\r\n      %%dot%% <a class=\"light\!
 " href=\"%%rootdir%%/user/$urlnick/prefs\">User Preferences</a><br />\
r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/interface/prefs\">Display Preferences</a><br />\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/interface/comments\">Comment Preferences</a><br />\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/logout\">Logout $S->{NICK}</a><BR>|;\r\n\r\n    $title = $S->{NICK};\r\n} else {\r\n    $content = $S->{UI}->{BLOCKS}->{login_box};\r\n    $content =~ s/%%LOGIN_ERROR%%/$S->{LOGIN_ERROR}/;\r\n}\r\nreturn {content => $content, title => $title };\r\n','the login box','box',0);
  INSERT INTO box VALUES ('hotlist_box','Your Hotlist','if ($S->{HOTLIST} && $#{$S->{HOTLIST}} >= 0) {\r\n	my $box_content;\r\n\r\n	foreach my $sid (@{$S->{HOTLIST}}) {\r\n		my $stories = $S->getstories(\r\n			{-type => \'fullstory\',\r\n			-sid => $sid});\r\n		my $story = $stories->[0];\nnext unless ($story);\n\r\n\r\n		my $show = $S->{UI}->{VARS}->{show_new_comments};\r\n		my $num_new = $S->new_comments_since_last_seen($sid) if ($show eq \"hotlist\" || $show eq \"all\");\r\n\r\n		my $end_s = ($story->{commentcount} == 1) ? \'\' : \'s\';\r\n		$box_content .= qq~%%dot%% <A CLASS=\"light\" HREF=\"%%rootdir%%/story/$sid\">$story->{title}</a> ($story->{commentcount} comment$end_s~;\r\n		$box_content .= \", $num_new new\" if defined($num_new);\r\n		$box_content .= \")<BR>\";\r\n	}\r\n\r\n	return unless $box_content;\nmy $title = \"$S->{NICK}\'s Hotlist\";\r\n	return {title => $title, content => $box_content };\r\n}\r\n','the hotlist box','box',1);
  INSERT INTO box VALUES ('menu_footer','','my $submit = \'\';\r\nmy $acct = \'\';\r\n\r\nif ( $S->have_perm(\'story_post\') ) {\r\n    $submit = \'<A HREF=\"%%rootdir%%/submit\">submit story</A> |\';\r\n}\r\n\r\nif ($S->{UID} < 0) {\r\n    $acct = \'<A HREF=\"%%rootdir%%/newuser\">create account</A> |\';\r\n}\r\n\r\nmy $content = qq{\r\n%%norm_font%%\r\n$submit\r\n$acct\r\n<A HREF=\"%%rootdir%%/special/faq\">faq</A> |\r\n<A HREF=\"%%rootdir%%/search\">search</A>\r\n%%norm_font_end%%};\r\n\r\nreturn $content;','Text-mode main menu','blank_box',0);
--- 406,410 ----
  
  INSERT INTO box VALUES ('cron_edit_queue','','#main sub\r\n\r\n# Get the expire time\r\nmy $expire = $S->{UI}->{VARS}->{queue_edit_max_time};\r\nmy $factors = {\r\n	d => \'86400\',\r\n	h => \'3600\',\r\n	m => \'60\',\r\n	s => \'1\'\r\n};\r\n$expire =~ s/([^\\d])$//;\r\nmy $time_sub = $expire * $factors->{$1};\r\n\r\nmy $select = {\r\n	DEBUG => 0,\r\n	WHAT => \"sid, score, time, displaystatus\",\r\n	FROM => \'stories\',\r\n	WHERE => \"displaystatus = -3 AND UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(time) >= $time_sub\",\r\n	ORDER_BY => \'time DESC\'\r\n};\r\n\r\nmy ($rv, $sth) = $S->db_select($select);\r\n\r\nmy $sid_move_to_moderate;\r\nwhile (my $story = $sth->fetchrow_hashref()) {\r\n	# only move if the time has expired\r\n	$sid_move_to_moderate = $story->{sid};\r\n	$S->move_story_to_voting($story->{sid});\r\n}\r\n\r\n$sth->finish();\r\n\r\nreturn 1;\r\n','','empty_box',0);
! INSERT INTO box VALUES ('user_box','Login','my $content;\r\nif ($S->{UID} > 0) {\r\n  if ($S->have_perm(\'moderate\')) {\r\n    my ($nstories, $tstories) = $S->_count_new_sub();\r\n    my $color = \'\';\r\n    my $c_end = \'\';\r\n    if ($nstories) {\r\n       $color = \'<font color=\"#FF0000\"><b>\';\r\n       $c_end = \'</b></font>\';\r\n    }\r\n    $content = qq|\r\n    %%dot%% <a class=\"light\" href=\"%%rootdir%%/modsub\">Moderate Submissions</a> ($tstories/$color$nstories$c_end new)<BR>|;\r\n  }\r\n\r\n  if ($S->{TRUSTLEV} == 2 || $S->have_perm(\'super_mojo\')) {\r\n    $content .= qq{%%dot%% <a class=\"light\" href=\"%%rootdir%%/search?type=comment;hidden_comments=show\">Review Hidden Comments</a><br />};\r\n  }\r\n  \r\n  my $urlnick = $S->urlify($S->{NICK});\r\n  my $diary_link = $S->{UI}->{VARS}->{use_diaries} ? \r\n		qq{\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/diary\">Your Diary</a><br />\r\n      %%dot%% <a class=\"light\" href=\"!
 %%rootdir%%/submitstory/Diary\">New Diary Entry</a><br /> \r\n		} : \'\';\r\n	my $upload_link = ($S->{UI}->{VARS}->{allow_uploads} && ($S->have_perm(\'upload_user\') || $S->have_perm(\'upload_admin\'))) ?\r\n		qq{%%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/files\">Your Files</a><br />} : \'\';\r\n\r\n	my $ad_link = $S->{UI}->{VARS}->{use_ads} ?\r\n		qq{\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/ads\">Your Advertisements</a><br />\r\n	  %%dot%% <a class=\"light\" href=\"%%rootdir%%/submitad\">Submit Ad</a><br />\r\n		} : \'\';\r\n\r\n  $content .= qq|\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick\">User Info</a><br />\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/comments\">Your Comments</a><br />\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/user/$urlnick/stories\">Your Stories</a><br?>\r\n      $diary_link\r\n	  $ad_link\r\n      $upload_link\r\n      %%dot%% <a class=\"light\!
 " href=\"%%rootdir%%/user/$urlnick/prefs\">User Preferences</a><br />\
r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/my/prefs/Interface\">Display Preferences</a><br />\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/my/prefs/Comments\">Comment Preferences</a><br />\r\n      %%dot%% <a class=\"light\" href=\"%%rootdir%%/logout\">Logout $S->{NICK}</a><BR>|;\r\n\r\n    $title = $S->{NICK};\r\n} else {\r\n    $content = $S->{UI}->{BLOCKS}->{login_box};\r\n    $content =~ s/%%LOGIN_ERROR%%/$S->{LOGIN_ERROR}/;\r\n}\r\nreturn {content => $content, title => $title };\r\n','the login box','box',0);
  INSERT INTO box VALUES ('hotlist_box','Your Hotlist','if ($S->{HOTLIST} && $#{$S->{HOTLIST}} >= 0) {\r\n	my $box_content;\r\n\r\n	foreach my $sid (@{$S->{HOTLIST}}) {\r\n		my $stories = $S->getstories(\r\n			{-type => \'fullstory\',\r\n			-sid => $sid});\r\n		my $story = $stories->[0];\nnext unless ($story);\n\r\n\r\n		my $show = $S->{UI}->{VARS}->{show_new_comments};\r\n		my $num_new = $S->new_comments_since_last_seen($sid) if ($show eq \"hotlist\" || $show eq \"all\");\r\n\r\n		my $end_s = ($story->{commentcount} == 1) ? \'\' : \'s\';\r\n		$box_content .= qq~%%dot%% <A CLASS=\"light\" HREF=\"%%rootdir%%/story/$sid\">$story->{title}</a> ($story->{commentcount} comment$end_s~;\r\n		$box_content .= \", $num_new new\" if defined($num_new);\r\n		$box_content .= \")<BR>\";\r\n	}\r\n\r\n	return unless $box_content;\nmy $title = \"$S->{NICK}\'s Hotlist\";\r\n	return {title => $title, content => $box_content };\r\n}\r\n','the hotlist box','box',1);
  INSERT INTO box VALUES ('menu_footer','','my $submit = \'\';\r\nmy $acct = \'\';\r\n\r\nif ( $S->have_perm(\'story_post\') ) {\r\n    $submit = \'<A HREF=\"%%rootdir%%/submit\">submit story</A> |\';\r\n}\r\n\r\nif ($S->{UID} < 0) {\r\n    $acct = \'<A HREF=\"%%rootdir%%/newuser\">create account</A> |\';\r\n}\r\n\r\nmy $content = qq{\r\n%%norm_font%%\r\n$submit\r\n$acct\r\n<A HREF=\"%%rootdir%%/special/faq\">faq</A> |\r\n<A HREF=\"%%rootdir%%/search\">search</A>\r\n%%norm_font_end%%};\r\n\r\nreturn $content;','Text-mode main menu','blank_box',0);
***************
*** 409,415 ****
  INSERT INTO box VALUES ('rdf_feeds','External Feeds','return unless $S->{UI}->{VARS}->{use_rdf_feeds} || $S->have_perm(\'rdf_admin\');\r\n\r\nmy $to_display = {};\r\nif (@ARGS || $S->{CGI}->param(\'rdf\')) {\r\n	my $rdf_arg = $S->{CGI}->param(\'rdf\');\r\n	if ($rdf_arg eq \'all\') {\r\n		$to_display->{\'all\'} = 1;\r\n	} else {\r\n		@ARGS = split(/,/, $rdf_arg) if $rdf_arg;\r\n		foreach (@ARGS) {\r\n			$to_display->{$_} = 1;\r\n		}\r\n	}\r\n}\r\n\r\nmy $content;\r\nmy $channels = $S->rdf_channels();\r\nmy $user_feeds = $S->rdf_get_prefs() unless @ARGS;\r\nmy $item_limit = defined($S->{prefs}->{rdf_max_headlines}) ?\r\n	$S->{prefs}->{rdf_max_headlines} :\r\n	defined($S->{UI}->{VARS}->{rdf_max_headlines}) ?\r\n	$S->{UI}->{VARS}->{rdf_max_headlines} : 15;\r\n\r\nforeach my $c (@{$channels}) {\r\n	unless ($to_display->{all} == 1) {\r\n		if (@ARGS) {\r\n			next unless $to_display->{ $c->{rid} };\r\n		} else {\r\n			next unless $user_feeds->{ $c->{rid} };\r\n		}\r\n	}\r\n	next u!
 nless $c->{title};\r\n	unless ($S->have_perm(\'rdf_admin\')) {\r\n		next if $c->{submitted} || !$c->{enabled};\r\n	}\r\n\r\n	if ($S->{UI}->{VARS}->{rdf_use_images} && $c->{image_url}) {\r\n		$content .= qq|<a href=\"$c->{image_link}\"><img src=\"$c->{image_url}\" alt=\"$c->{image_title}\" border=\"1\"></a><br>\\n|;\r\n	} else {\r\n		$content .= qq|<b><a class=\"light\" href=\"$c->{link}\">$c->{title}</a></b><br />\\n|;\r\n	}\r\n\r\n	my $items = $S->rdf_items($c->{rid}, $item_limit);\r\n	foreach my $i (@{$items}) {\r\n		$content .= qq|%%dot%% <a class=\"light\" href=\"$i->{link}\">$i->{title}</a><br />\\n|;\r\n	}\r\n\r\n	if ($S->{UI}->{VARS}->{rdf_use_forms} && $c->{form_link}) {\r\n		$content .= qq|<form action=\"$c->{form_link}\" method=\"GET\">$c->{form_title}: <input type=\"text\" name=\"$c->{form_name}\"></form><br />\\n|;\r\n	}\r\n\r\n	$content .= \"<br />\\n\";\r\n}\r\n\r\nif ($content && $S->have_perm(\'submit_rdf\')) {\r\n	$content = qq|<a class=\"light\" href=\"%%r!
 ootdir%%/submitrdf\">Submit Feed</a><br /><br />\\n| . $content;\r\n}\
r\n\r\nreturn $content;\r\n','contains RDF feeds from other sites','box',1);
  INSERT INTO box VALUES ('submit_rdf','Submit Feed','return \"Sorry, you don\'t have permission to submit a feed.\"\r\n\r\nunless $S->have_perm(\'submit_rdf\');\r\n\r\nmy $action = $S->{CGI}->param(\'action\') || \'showform\';\r\n\r\nif ($action eq \'showform\') {\r\n\r\nreturn &disp_form();\r\n\r\n} elsif ($action eq \'save\') {\r\n\r\nmy $url = $S->{CGI}->param(\'url\');\r\n\r\nreturn (\'Please fill in the URL field\') unless $url;\r\n\r\n# check to see if this RDF already exists\r\n\r\nmy $is_dup = 0;\r\n\r\nmy $channels = $S->rdf_channels;\r\n\r\nforeach my $c (@{$channels}) {\r\n\r\n$is_dup = 1 if $c->{rdf_link} eq $url;\r\n\r\n}\r\n\r\nreturn &disp_form(\'That RDF already exists, or has been submitted already.\') if $is_dup;\r\n\r\n\r\n\r\nmy $do_fetch = $S->{UI}->{VARS}->{allow_rdf_fetch} ? 1 : 0;\r\n\r\nmy ($id, $res) = $S->rdf_add_channel($url, $do_fetch, $S->{NICK});\r\n\r\nunless ($res) {\r\n\r\n$S->rdf_remove_channel($id);\r\n\r\nreturn &disp_form(\'Error adding!
  RDF file: $res\');\r\n\r\n}\r\n\r\nmy $fetched_msg = qq|\r\n\r\n%%norm_font%%Your RDF has been fetched. An admin will check it out as soon as possible%%norm_font_end%%|;\r\n\r\nreturn $fetched_msg;\r\n\r\n}\r\n\r\n\r\n\r\nsub disp_form {\r\n\r\nmy $form = qq|\r\n\r\n%%norm_font%% %%submit_rdf_message%% %%norm_font_end%%\r\n\r\n<p>\r\n\r\n<form action=\"%%rootdir%%/?\" method=\"GET\">\r\n\r\n<input type=\"hidden\" name=\"op\" value=\"submitrdf\">\r\n\r\n<input type=\"hidden\" name=\"action\" value=\"save\">\r\n\r\n<table border=0 cellspacing=0 cellpadding=0>|;\r\n\r\n$form .= qq|\r\n\r\n<tr>\r\n\r\n<td><FONT color=\"#FF0000\">%%norm_font%%$_[0]%%norm_font_end%%</font></td>\r\n\r\n</tr>| if $_[0];\r\n\r\n$form .= qq|\r\n\r\n<tr>\r\n\r\n<td>%%norm_font%%URL of RDF file:%%norm_font_end%% <input type=\"text\" name=\"url\" size=\"50\"></td>\r\n\r\n</tr>\r\n\r\n<tr>\r\n\r\n<td><input type=\"submit\" value=\"Submit\"></td>\r\n\r\n</tr>\r\n\r\n</table>\r\n\r\n</form>\r\n\r\n|;\r\n\!
 r\nreturn $form;\r\n\r\n}\r\n\r\n','Box to do submitrdf op and such.',
'titled_box',0);
! INSERT INTO box VALUES ('whos_online','Who\'s online','## New Who\'s Online Box\n## Quite a bit of stuff borrowed from the old one.\n\n# return if anonymous for now\nreturn if $S->{UID} == -1;\n\n# The time stuff can be changed to taste\n\n# The query\n\nmy ($rv,$sth) = $S->db_select({\n   FROM => \'whos_online\',\n   WHAT => \'ip, uid\',\n   WHERE => \'last_visit > DATE_SUB(NOW(), INTERVAL 30 MINUTE)\',\n   ORDER_BY => \'uid\'\n});\n\nmy %uids;\nmy $total;\nmy $anontotal;\n\nwhile (my $s = $sth->fetchrow_hashref()) {\n      if ($s->{\'uid\'} == -1) {\n        $anontotal++;\n        next;\n        }\n   $total++;\n   $uids{ $s->{\'uid\'} }++;\n}\n\n$sth->finish;\n\nmy @sorted = sort keys %uids;\n\nmy $out;\nmy $hidden;\nforeach (@sorted) {\n   if ($S->user_data($_)->{prefs}->{online_cloak}) {\n      $hidden++;\n      next;\n   }\n   my $nick = $S->user_data($_)->{nickname};\n   $out .= qq~%%dot%% <A HREF=\"%%rootdir%%/user/uid:$_\">$nick</A>~;\n   $out .= \" ($uids{$_})\" !
 if $uids{$_} > 1;\n   $out .= \"<BR>\\n\";\n}\nif($anontotal){\n   my $anon_user_nick = $S->{UI}->{VARS}->{anon_user_nick};\n   $out .= \"%%dot%% $anon_user_nick ($anontotal)<BR>\";\n   }\nif ($hidden) {\n   $out .= qq~%%dot%% Cloaked Users ($hidden)<p>~;\n} else {\n   $out .= \'<p>\';\n}\n$total = $total + $anontotal;\n$out .= qq~<small>Note: You may cloak yourself from appearing here in your <A HREF=\"%%rootdir%%/interface/prefs\">Display Preferences</A></small>.~;\nreturn {content => $out, title => \"Who\'s Online? ($total)\"};\n','','box',1);
  INSERT INTO box VALUES ('show_ad','Show Advertisement','my $arg0 = $ARGS[0];\r\nmy $arg1 = $ARGS[1];\r\nmy $ad_id;\r\nmy $adhash = {};\r\nmy $content = \'\';\r\n\r\n# if the ad_id is in the url, use the url\r\nif( $arg0 eq \'fromurl\' || $arg0 eq \'allcgi\' ) {\r\n $ad_id = $S->{CGI}->param(\'ad_id\');\r\n\r\n# if they want to see what the fields are...\r\n} elsif( $arg0 eq \'showfields\' ){\r\n\r\n	my $ex_ad = $S->get_example_ad($arg1);\r\n	return \'\' unless( defined($ex_ad) && (ref($ex_ad) eq \'HASH\') );\r\n\r\n	if( exists $S->{UI}->{BLOCKS}->{\"preview_\" . $ex_ad->{ad_tmpl}} ) {\r\n		$content = $S->{UI}->{BLOCKS}->{ \"preview_\". $ex_ad->{ad_tmpl} };\r\n	} else {\r\n		$content = $S->{UI}->{BLOCKS}->{ $ex_ad->{ad_tmpl} };\r\n	}\r\n\r\n	$content =~ s/%%FILE_PATH%%//g;\r\n	$content =~ s/%%TEXT1%%/This is text1/g;\r\n	$content =~ s/%%TEXT2%%/This is text2/g;\r\n	$content =~ s/%%TITLE%%/This is the title/g;\r\n	$content =~ s/%%LINK_URL%%/This is the link url/g;\r\n	$conte!
 nt =~ s[%%REDIRECT_URL%%][%%rootdir%%]g;\r\n\r\n	return { content => $content };\r\n\r\n# else if ad_id is specified in template, use that\r\n} elsif( $arg0 =~ /\\d/ ) {\r\n $ad_id = $arg0;\r\n}\r\n\r\nunless( defined( $ad_id ) || $arg0 eq \'allcgi\' ) {\r\n	return \'\';\r\n}\r\n\r\n# if we need everything from cgi, let get_ad_hash know\r\nmy $source = \'db\';\r\n$source = \'cgi\' if( $arg0 eq \'allcgi\' );\r\n\r\n$adhash = $S->get_ad_hash($ad_id, $source);\r\n\r\nmy $image = $adhash->{ad_file};\r\nmy $subdir = $adhash->{sponsor};\r\n$subdir = \'example\' if( $adhash->{example} == 1 );\r\n\r\nmy $image_path = $subdir . \'/\' . $image;\r\n\r\nif( exists $S->{UI}->{BLOCKS}->{\"preview_\" . $adhash->{ad_tmpl}} ) {\r\n	$content = $S->{UI}->{BLOCKS}->{ \"preview_\". $adhash->{ad_tmpl} };\r\n} else {\r\n	$content = $S->{UI}->{BLOCKS}->{ $adhash->{ad_tmpl} };\r\n}\r\n\r\n$content =~ s/%%FILE_PATH%%/$image_path/g;\r\n$content =~ s/%%TEXT1%%/$adhash->{ad_text1}/g;\r\n$content =~ s/%!
 %TEXT2%%/$adhash->{ad_text2}/g;\r\n$content =~ s/%%TITLE%%/$adhash->{a
d_title}/g;\r\n$content =~ s/%%LINK_URL%%/$adhash->{ad_url}/g;\r\n$content =~ s/%%SID%%/$adhash->{ad_sid}/g;\r\n$content =~ s[%%REDIRECT_URL%%][%%rootdir%%/redirect/$ad_id]g;\r\n\r\nreturn { content => $content };\r\n','Just a simple box that will show the ad specified','box',0);
! INSERT INTO box VALUES ('ad_box','Advertisement','return \'\' unless( $S->{UI}->{VARS}->{use_ads} );\r\n\r\nmy $adhash = $S->get_next_ad();\r\nreturn \'\' unless( $adhash->{ERROR} != 1 );\r\n\r\nmy $content = $S->{UI}->{BLOCKS}->{$adhash->{ad_tmpl}};\r\n\r\nmy $subdir = ($adhash->{example} == 1) ? \'example\' : $adhash->{sponsor};\nmy $file_path = $subdir . \'/\' .  $adhash->{ad_file};\n\n$content =~ s/%%LINK_URL%%/$adhash->{ad_url}/g;\r\n$content =~ s/%%TITLE%%/$adhash->{ad_title}/g;\r\n$content =~ s/%%TEXT1%%/$adhash->{ad_text1}/g;\r\n$content =~ s/%%TEXT2%%/$adhash->{ad_text2}/g;\r\n$content =~ s/%%FILE_PATH%%/$file_path/g;\r\n$content =~ s/%%SID%%/$adhash->{ad_sid}/g;\r\n$content =~ s[%%REDIRECT_URL%%][%%rootdir%%/redirect/$adhash->{ad_id}];\r\n\r\nif( $S->pref(\'ad_open_new_win\') eq \'Yes\' ) {\r\n  $content =~ s/%%TARGET%%/target=\"_blank\"/g;\r\n}\r\n\r\nreturn { content => $content };\r\n','Simple ad box for the side of the page','box',0);
  INSERT INTO box VALUES ('ad_types','Advertisement Type Listing','my $content = $S->make_ad_type_list(\'no_choice\');\r\n\r\nreturn { content => $content };\r\n','Shows a list of all of the advertisement types','blank_box',0);
  INSERT INTO box VALUES ('buyimpressions_box','Purchase Ad Impressions','# This box controls /ads\r\n# -> If no argument is given, assumes the user wants to purchase\r\n# more impressions.\r\n# -> If distribute=1 will bring up ad impression distribution\r\n# page.\r\n\r\nmy $content = \'\';\r\n\r\nmy $distribute = $S->cgi->param(\'distribute\');\r\n\r\nif( $distribute eq \'dist\' ) {\r\n	$content = $S->ad_impression_distribute();\r\n}\r\nelse {\r\n	$content = $S->purchase_impressions();\r\n}\r\n\r\nreturn { content => $content };\r\n','controls /ads.  Displays either a form to distribute impressions between multiple ads, or to just buy impressions directly.','blank_box',0);
--- 422,428 ----
  INSERT INTO box VALUES ('rdf_feeds','External Feeds','return unless $S->{UI}->{VARS}->{use_rdf_feeds} || $S->have_perm(\'rdf_admin\');\r\n\r\nmy $to_display = {};\r\nif (@ARGS || $S->{CGI}->param(\'rdf\')) {\r\n	my $rdf_arg = $S->{CGI}->param(\'rdf\');\r\n	if ($rdf_arg eq \'all\') {\r\n		$to_display->{\'all\'} = 1;\r\n	} else {\r\n		@ARGS = split(/,/, $rdf_arg) if $rdf_arg;\r\n		foreach (@ARGS) {\r\n			$to_display->{$_} = 1;\r\n		}\r\n	}\r\n}\r\n\r\nmy $content;\r\nmy $channels = $S->rdf_channels();\r\nmy $user_feeds = $S->rdf_get_prefs() unless @ARGS;\r\nmy $item_limit = defined($S->{prefs}->{rdf_max_headlines}) ?\r\n	$S->{prefs}->{rdf_max_headlines} :\r\n	defined($S->{UI}->{VARS}->{rdf_max_headlines}) ?\r\n	$S->{UI}->{VARS}->{rdf_max_headlines} : 15;\r\n\r\nforeach my $c (@{$channels}) {\r\n	unless ($to_display->{all} == 1) {\r\n		if (@ARGS) {\r\n			next unless $to_display->{ $c->{rid} };\r\n		} else {\r\n			next unless $user_feeds->{ $c->{rid} };\r\n		}\r\n	}\r\n	next u!
 nless $c->{title};\r\n	unless ($S->have_perm(\'rdf_admin\')) {\r\n		next if $c->{submitted} || !$c->{enabled};\r\n	}\r\n\r\n	if ($S->{UI}->{VARS}->{rdf_use_images} && $c->{image_url}) {\r\n		$content .= qq|<a href=\"$c->{image_link}\"><img src=\"$c->{image_url}\" alt=\"$c->{image_title}\" border=\"1\"></a><br>\\n|;\r\n	} else {\r\n		$content .= qq|<b><a class=\"light\" href=\"$c->{link}\">$c->{title}</a></b><br />\\n|;\r\n	}\r\n\r\n	my $items = $S->rdf_items($c->{rid}, $item_limit);\r\n	foreach my $i (@{$items}) {\r\n		$content .= qq|%%dot%% <a class=\"light\" href=\"$i->{link}\">$i->{title}</a><br />\\n|;\r\n	}\r\n\r\n	if ($S->{UI}->{VARS}->{rdf_use_forms} && $c->{form_link}) {\r\n		$content .= qq|<form action=\"$c->{form_link}\" method=\"GET\">$c->{form_title}: <input type=\"text\" name=\"$c->{form_name}\"></form><br />\\n|;\r\n	}\r\n\r\n	$content .= \"<br />\\n\";\r\n}\r\n\r\nif ($content && $S->have_perm(\'submit_rdf\')) {\r\n	$content = qq|<a class=\"light\" href=\"%%r!
 ootdir%%/submitrdf\">Submit Feed</a><br /><br />\\n| . $content;\r\n}\
r\n\r\nreturn $content;\r\n','contains RDF feeds from other sites','box',1);
  INSERT INTO box VALUES ('submit_rdf','Submit Feed','return \"Sorry, you don\'t have permission to submit a feed.\"\r\n\r\nunless $S->have_perm(\'submit_rdf\');\r\n\r\nmy $action = $S->{CGI}->param(\'action\') || \'showform\';\r\n\r\nif ($action eq \'showform\') {\r\n\r\nreturn &disp_form();\r\n\r\n} elsif ($action eq \'save\') {\r\n\r\nmy $url = $S->{CGI}->param(\'url\');\r\n\r\nreturn (\'Please fill in the URL field\') unless $url;\r\n\r\n# check to see if this RDF already exists\r\n\r\nmy $is_dup = 0;\r\n\r\nmy $channels = $S->rdf_channels;\r\n\r\nforeach my $c (@{$channels}) {\r\n\r\n$is_dup = 1 if $c->{rdf_link} eq $url;\r\n\r\n}\r\n\r\nreturn &disp_form(\'That RDF already exists, or has been submitted already.\') if $is_dup;\r\n\r\n\r\n\r\nmy $do_fetch = $S->{UI}->{VARS}->{allow_rdf_fetch} ? 1 : 0;\r\n\r\nmy ($id, $res) = $S->rdf_add_channel($url, $do_fetch, $S->{NICK});\r\n\r\nunless ($res) {\r\n\r\n$S->rdf_remove_channel($id);\r\n\r\nreturn &disp_form(\'Error adding!
  RDF file: $res\');\r\n\r\n}\r\n\r\nmy $fetched_msg = qq|\r\n\r\n%%norm_font%%Your RDF has been fetched. An admin will check it out as soon as possible%%norm_font_end%%|;\r\n\r\nreturn $fetched_msg;\r\n\r\n}\r\n\r\n\r\n\r\nsub disp_form {\r\n\r\nmy $form = qq|\r\n\r\n%%norm_font%% %%submit_rdf_message%% %%norm_font_end%%\r\n\r\n<p>\r\n\r\n<form action=\"%%rootdir%%/?\" method=\"GET\">\r\n\r\n<input type=\"hidden\" name=\"op\" value=\"submitrdf\">\r\n\r\n<input type=\"hidden\" name=\"action\" value=\"save\">\r\n\r\n<table border=0 cellspacing=0 cellpadding=0>|;\r\n\r\n$form .= qq|\r\n\r\n<tr>\r\n\r\n<td><FONT color=\"#FF0000\">%%norm_font%%$_[0]%%norm_font_end%%</font></td>\r\n\r\n</tr>| if $_[0];\r\n\r\n$form .= qq|\r\n\r\n<tr>\r\n\r\n<td>%%norm_font%%URL of RDF file:%%norm_font_end%% <input type=\"text\" name=\"url\" size=\"50\"></td>\r\n\r\n</tr>\r\n\r\n<tr>\r\n\r\n<td><input type=\"submit\" value=\"Submit\"></td>\r\n\r\n</tr>\r\n\r\n</table>\r\n\r\n</form>\r\n\r\n|;\r\n\!
 r\nreturn $form;\r\n\r\n}\r\n\r\n','Box to do submitrdf op and such.',
'titled_box',0);
! INSERT INTO box VALUES ('whos_online','Who\'s online','## New Who\'s Online Box\n## Quite a bit of stuff borrowed from the old one.\n\n# return if anonymous for now\nreturn if $S->{UID} == -1;\n\n# The time stuff can be changed to taste\n\n# The query\n\nmy ($rv,$sth) = $S->db_select({\n   FROM => \'whos_online\',\n   WHAT => \'ip, uid\',\n   WHERE => \'last_visit > DATE_SUB(NOW(), INTERVAL 30 MINUTE)\',\n   ORDER_BY => \'uid\'\n});\n\nmy %uids;\nmy $total;\nmy $anontotal;\n\nwhile (my $s = $sth->fetchrow_hashref()) {\n      if ($s->{\'uid\'} == -1) {\n        $anontotal++;\n        next;\n        }\n   $total++;\n   $uids{ $s->{\'uid\'} }++;\n}\n\n$sth->finish;\n\nmy @sorted = sort keys %uids;\n\nmy $out;\nmy $hidden;\nforeach (@sorted) {\n   if ($S->user_data($_)->{prefs}->{online_cloak} eq \'on\') {\n      $hidden++;\n      next;\n   }\n   my $nick = $S->user_data($_)->{nickname};\n   $out .= qq~%%dot%% <A HREF=\"%%rootdir%%/user/uid:$_\">$nick</A>~;\n   $out .= \" ($ui!
 ds{$_})\" if $uids{$_} > 1;\n   $out .= \"<BR>\\n\";\n}\nif($anontotal){\n   my $anon_user_nick = $S->{UI}->{VARS}->{anon_user_nick};\n   $out .= \"%%dot%% $anon_user_nick ($anontotal)<BR>\";\n   }\nif ($hidden) {\n   $out .= qq~%%dot%% Cloaked Users ($hidden)<p>~;\n} else {\n   $out .= \'<p>\';\n}\n$total = $total + $anontotal;\n$out .= qq~<small>Note: You may cloak yourself from appearing here in your <A HREF=\"%%rootdir%%/my/prefs/Interface\">Display Preferences</A></small>.~;\nreturn {content => $out, title => \"Who\'s Online? ($total)\"};\n','','box',1);
  INSERT INTO box VALUES ('show_ad','Show Advertisement','my $arg0 = $ARGS[0];\r\nmy $arg1 = $ARGS[1];\r\nmy $ad_id;\r\nmy $adhash = {};\r\nmy $content = \'\';\r\n\r\n# if the ad_id is in the url, use the url\r\nif( $arg0 eq \'fromurl\' || $arg0 eq \'allcgi\' ) {\r\n $ad_id = $S->{CGI}->param(\'ad_id\');\r\n\r\n# if they want to see what the fields are...\r\n} elsif( $arg0 eq \'showfields\' ){\r\n\r\n	my $ex_ad = $S->get_example_ad($arg1);\r\n	return \'\' unless( defined($ex_ad) && (ref($ex_ad) eq \'HASH\') );\r\n\r\n	if( exists $S->{UI}->{BLOCKS}->{\"preview_\" . $ex_ad->{ad_tmpl}} ) {\r\n		$content = $S->{UI}->{BLOCKS}->{ \"preview_\". $ex_ad->{ad_tmpl} };\r\n	} else {\r\n		$content = $S->{UI}->{BLOCKS}->{ $ex_ad->{ad_tmpl} };\r\n	}\r\n\r\n	$content =~ s/%%FILE_PATH%%//g;\r\n	$content =~ s/%%TEXT1%%/This is text1/g;\r\n	$content =~ s/%%TEXT2%%/This is text2/g;\r\n	$content =~ s/%%TITLE%%/This is the title/g;\r\n	$content =~ s/%%LINK_URL%%/This is the link url/g;\r\n	$conte!
 nt =~ s[%%REDIRECT_URL%%][%%rootdir%%]g;\r\n\r\n	return { content => $content };\r\n\r\n# else if ad_id is specified in template, use that\r\n} elsif( $arg0 =~ /\\d/ ) {\r\n $ad_id = $arg0;\r\n}\r\n\r\nunless( defined( $ad_id ) || $arg0 eq \'allcgi\' ) {\r\n	return \'\';\r\n}\r\n\r\n# if we need everything from cgi, let get_ad_hash know\r\nmy $source = \'db\';\r\n$source = \'cgi\' if( $arg0 eq \'allcgi\' );\r\n\r\n$adhash = $S->get_ad_hash($ad_id, $source);\r\n\r\nmy $image = $adhash->{ad_file};\r\nmy $subdir = $adhash->{sponsor};\r\n$subdir = \'example\' if( $adhash->{example} == 1 );\r\n\r\nmy $image_path = $subdir . \'/\' . $image;\r\n\r\nif( exists $S->{UI}->{BLOCKS}->{\"preview_\" . $adhash->{ad_tmpl}} ) {\r\n	$content = $S->{UI}->{BLOCKS}->{ \"preview_\". $adhash->{ad_tmpl} };\r\n} else {\r\n	$content = $S->{UI}->{BLOCKS}->{ $adhash->{ad_tmpl} };\r\n}\r\n\r\n$content =~ s/%%FILE_PATH%%/$image_path/g;\r\n$content =~ s/%%TEXT1%%/$adhash->{ad_text1}/g;\r\n$content =~ s/%!
 %TEXT2%%/$adhash->{ad_text2}/g;\r\n$content =~ s/%%TITLE%%/$adhash->{a
d_title}/g;\r\n$content =~ s/%%LINK_URL%%/$adhash->{ad_url}/g;\r\n$content =~ s/%%SID%%/$adhash->{ad_sid}/g;\r\n$content =~ s[%%REDIRECT_URL%%][%%rootdir%%/redirect/$ad_id]g;\r\n\r\nreturn { content => $content };\r\n','Just a simple box that will show the ad specified','box',0);
! INSERT INTO box VALUES ('ad_box','Advertisement','return \'\' if( $S->pref(\'showad\') eq \'off\' );\nreturn \'\' unless( $S->{UI}->{VARS}->{use_ads} );\r\n\r\nmy $adhash = $S->get_next_ad();\r\nreturn \'\' unless( $adhash->{ERROR} != 1 );\r\n\r\nmy $content = $S->{UI}->{BLOCKS}->{$adhash->{ad_tmpl}};\r\n\r\nmy $subdir = ($adhash->{example} == 1) ? \'example\' : $adhash->{sponsor};\nmy $file_path = $subdir . \'/\' .  $adhash->{ad_file};\n\n$content =~ s/%%LINK_URL%%/$adhash->{ad_url}/g;\r\n$content =~ s/%%TITLE%%/$adhash->{ad_title}/g;\r\n$content =~ s/%%TEXT1%%/$adhash->{ad_text1}/g;\r\n$content =~ s/%%TEXT2%%/$adhash->{ad_text2}/g;\r\n$content =~ s/%%FILE_PATH%%/$file_path/g;\r\n$content =~ s/%%SID%%/$adhash->{ad_sid}/g;\r\n$content =~ s[%%REDIRECT_URL%%][%%rootdir%%/redirect/$adhash->{ad_id}];\r\n\r\nif( $S->pref(\'ad_open_new_win\') eq \'on\' ) {\r\n  $content =~ s/%%TARGET%%/target=\"_blank\"/g;\r\n}\r\n\r\nreturn { content => $content };\r\n','Simple ad box for the s!
 ide of the page','box',0);
  INSERT INTO box VALUES ('ad_types','Advertisement Type Listing','my $content = $S->make_ad_type_list(\'no_choice\');\r\n\r\nreturn { content => $content };\r\n','Shows a list of all of the advertisement types','blank_box',0);
  INSERT INTO box VALUES ('buyimpressions_box','Purchase Ad Impressions','# This box controls /ads\r\n# -> If no argument is given, assumes the user wants to purchase\r\n# more impressions.\r\n# -> If distribute=1 will bring up ad impression distribution\r\n# page.\r\n\r\nmy $content = \'\';\r\n\r\nmy $distribute = $S->cgi->param(\'distribute\');\r\n\r\nif( $distribute eq \'dist\' ) {\r\n	$content = $S->ad_impression_distribute();\r\n}\r\nelse {\r\n	$content = $S->purchase_impressions();\r\n}\r\n\r\nreturn { content => $content };\r\n','controls /ads.  Displays either a form to distribute impressions between multiple ads, or to just buy impressions directly.','blank_box',0);
***************
*** 436,439 ****
--- 449,469 ----
  INSERT INTO box VALUES ('css','css','my $content;\r\n\r\nmy $file = $S->cgi->param(\'file\');\r\nmy $block = $file.\"_css\";\r\n\r\n$content = $S->{UI}->{BLOCKS}->{$block};\r\n$S->apache->content_type(\'text/css\');\r\n\r\nreturn {content => $content};','Returns a block with type text/css','empty_box',0);
  INSERT INTO box VALUES ('admin_search','Search Admin Tools','# search terms?\r\nmy $query = $S->cgi->param(\'query\');\r\n\r\n# search where?\r\n# extract the chosen search locations\r\nmy $search_param = $S->cgi->param(\'search_in\');\r\nmy %search_in;\r\nmy $searches_selected = 0;\r\nforeach (ref($search_param) eq \'ARRAY\' ? @{$search_param} : ($search_param)) {\r\n	next unless $_;\r\n	$search_in{$_} = 1;\r\n	$searches_selected++;\r\n}\r\n\r\n# if they didn\'t select any searches, or this is a fresh load, then select all\r\nunless ($searches_selected) {\r\n	foreach (qw(blockval blockdesc boxval boxdesc specval vardesc)) {\r\n		$search_in{$_} = 1;\r\n	}\r\n}\r\n\r\nmy ($blockval, $blockdesc, $boxval, $boxdesc, $specval, $vardesc) = \"\";\r\nmy ($blocksearchwhere, $boxsearchwhere, $specsearchwhere, $varsearchwhere) = \"\";\r\nmy ($type_phrase, $type_any, $type_all) = \"\";\r\n\r\n# remember what was previously selected. yes, this is kind of ugly\r\n$blockval  = \' selecte!
 d=\"selected\"\' if $search_in{blockval};\r\n$blockdesc = \' selected=\"selected\"\' if $search_in{blockdesc};\r\n$boxval    = \' selected=\"selected\"\' if $search_in{boxval};\r\n$boxdesc   = \' selected=\"selected\"\' if $search_in{boxdesc};\r\n$specval   = \' selected=\"selected\"\' if $search_in{specval};\r\n$vardesc   = \' selected=\"selected\"\' if $search_in{vardesc};\r\n\r\n# same thing for search type, though set a default of all\r\nif ($S->cgi->param(\'search_type\') eq \'phrase\') {\r\n	$type_phrase = \' checked=\"checked\"\';\r\n} elsif($S->cgi->param(\'search_type\') eq \'all\') {\r\n	$type_all = \' checked=\"checked\"\';\r\n} elsif($S->cgi->param(\'search_type\') eq \'any\') {\r\n	$type_any = \' checked=\"checked\"\';\r\n} else {\r\n	$type_all = \' checked=\"checked\"\';\r\n}\r\n\r\n# set up search fields\r\nmy $search_for_field = qq{<input type=\"text\" name=\"query\" value=\"$query\" /><input type=\"submit\" value=\"Search\" />};\r\n\r\nmy $search_in_field =!
  \'<select name=\"search_in\" multiple=\"multiple\" size=\"6\">\';\r\n
$search_in_field .= qq{\r\n	<option value=\"blockval\"$blockval>Block values</option>\r\n	<option value=\"blockdesc\"$blockdesc>Block descriptions</option>} if $S->have_perm(\'edit_blocks\');\r\n\r\n$search_in_field .= qq{\r\n	<option value=\"boxval\"$boxval>Box code</option>\r\n	<option value=\"boxdesc\"$boxdesc>Box descriptions</option>} if $S->have_perm(\'edit_boxes\');\r\n\r\n$search_in_field .= qq{\r\n	<option value=\"specval\"$specval>Special Pages</option>} if $S->have_perm(\'edit_special\');\r\n\r\n$search_in_field .= qq{\r\n	<option value=\"vardesc\"$vardesc>Site Controls descriptions</option>} if $S->have_perm(\'edit_vars\');\r\n\r\n$search_in_field .= \"\\n</select>\";\r\n\r\nmy $search_opt_field = qq{<input type=\"radio\" name=\"search_type\" value=\"all\"$type_all /> All words<br />\r\n<input type=\"radio\" name=\"search_type\" value=\"any\"$type_any /> Any words<br />\r\n<input type=\"radio\" name=\"search_type\" value=\"phrase\"$type_phrase /> Phrase};\r\n\r\n!
 my $content .= qq{\r\n<form method=\"get\" action=\"%%rootdir%%/admin/search\">\r\n<table border=\"0\">\r\n	<tr>\r\n		<td valign=\"top\" rowspan=\"2\">%%norm_font%%Search in:<br />$search_in_field%%norm_font_end%%</td>\r\n		<td>%%norm_font%%Search for:<br />$search_for_field%%norm_font_end%%</td>\r\n	</tr>\r\n	<tr>\r\n		<td>%%norm_font%%$search_opt_field%%norm_font_end%%</td>\r\n	</tr>\r\n</table>\r\n</form>\r\n   };\r\n\r\nif ($query) {\r\n	my ($blockresults, $boxresults, $specresults, $varresults) = (\"\",\"\",\"\",\"\");\r\n\r\n	# of the three column names which might be needed, these are used\r\n	# repeatedly, so stick them in a var instead of re-building them\r\n	my $content_string = &search_string($S, $query, \'content\');\r\n	my $desc_string    = &search_string($S, $query, \'description\');\r\n\r\n	$blocksearchwhere .= &search_string($S, $query, \'block\') if ($blockval);\r\n	$blocksearchwhere .= \' OR \' if ($blockdesc && $blockval);\r\n	$blocksearchwhere .= $desc_s!
 tring if ($blockdesc);\r\n	$boxsearchwhere   .= $content_string if ($b
oxval);\r\n	$boxsearchwhere   .= \' OR \' if ($boxdesc && $boxval);\r\n	$boxsearchwhere   .= $desc_string if ($boxdesc);\r\n	$specsearchwhere  .= $content_string if ($specval);\r\n	$varsearchwhere   .= $desc_string if ($vardesc);\r\n\r\n	if ($blocksearchwhere && $S->have_perm(\'edit_blocks\')) {\r\n		my ($rv, $sth) = $S->db_select({\r\n			WHAT  => \'bid,description,theme\',\r\n			FROM  => \'blocks\',\r\n			WHERE => $blocksearchwhere\r\n		});\r\n		while (my $rec = $sth->fetchrow_hashref) {\r\n			my $desc = $rec->{description} || \"<i>(no description)</i>\";\r\n			$blockresults .= qq{\r\n	<dt><a href=\"%%rootdir%%/admin/blocks/edit/$rec->{theme}/$rec->{bid}\">$rec->{bid}</a></dt>\r\n	<dd>$desc</dd>}\r\n		}\r\n		$blockresults = \"<dl> $blockresults </dl>\" if $blockresults;\r\n	}\r\n\r\n	if ($boxsearchwhere && $S->have_perm(\'edit_boxes\')) {\r\n		my ($rv, $sth) = $S->db_select({\r\n			WHAT  => \'boxid, description\',\r\n			FROM  => \'box\',\r\n			WHERE => $boxsearchwhere\r\n		!
 });\r\n		while (my $rec = $sth->fetchrow_hashref) {\r\n			my $desc = $rec->{description} || \"<i>(no description)</i>\";\r\n			$boxresults .= qq{\r\n	<dt><a href=\"%%rootdir%%/admin/boxes/$rec->{boxid}\">$rec->{boxid}</a></dt>\r\n	<dd>$desc</dd>}\r\n		}\r\n		$boxresults = \"<dl> $boxresults </dl>\" if $boxresults;\r\n	}\r\n\r\n	if ($specsearchwhere && $S->have_perm(\'edit_special\')) {\r\n		my ($rv, $sth) = $S->db_select({\r\n			WHAT => \'pageid,title,description\',\r\n			FROM => \'special\',\r\n			WHERE => $specsearchwhere\r\n		});\r\n		while (my $rec = $sth->fetchrow_hashref) {\r\n			my $desc = $rec->{description} || \"<i>(no description)</i>\";\r\n			$specresults .= qq{\r\n	<dt><a href=\"%%rootdir%%/admin/special?id=$rec->{pageid}\">$rec->{title}</a></dt>\r\n	<dd>$desc</dd>}\r\n		}\r\n		$specresults = \"<dl> $specresults </dl>\" if $specresults;\r\n	}\r\n\r\n	if ($varsearchwhere && $S->have_perm(\'edit_vars\')) {\r\n		my ($rv, $sth) = $S->db_select({\r\n			WHAT => \'name!
 ,description\',\r\n			FROM => \'vars\',\r\n			WHERE => $varsearchwhere
\r\n		});\r\n		while (my $rec = $sth->fetchrow_hashref) {\r\n			my $desc = $rec->{description} || \"<i>(no description)</i>\";\r\n			$varresults .= qq{\r\n	<dt><a href=\"%%rootdir%%/admin/vars/edit/$rec->{name}\">$rec->{name}</a></dt>\r\n	<dd>$desc</dd>}\r\n		}\r\n		$varresults = \"<dl> $varresults </dl>\" if $varresults;\r\n	}\r\n\r\n	$content .= \"<H3>Blocks found:</H3>\\n%%norm_font%%$blockresults%%norm_font_end%%\" if $blockresults;\r\n	$content .= \"<H3>Boxes found:</H3>\\n%%norm_font%%$boxresults%%norm_font_end%%\" if $boxresults;\r\n	$content .= \"<H3>Special Pages found:</H3>\\n%%norm_font%%$specresults%%norm_font_end%%\" if $specresults;\r\n	$content .= \"<H3>Site Controls found:</H3>\\n%%norm_font%%$varresults%%norm_font_end%%\" if $varresults;\r\n	unless ($varresults || $blockresults || $boxresults || $specresults) {\r\n		$content .= \"%%norm_font%%Nothing matching your search phrase was found in the selected tools.%%norm_font_end%%\";\r\n	}\r\n}\r\n\r\n$content =!
  \"<table width=\\\"100%\\\">\r\n	<tr width=\\\"100%\\\" bgcolor=\\\"%%title_bgcolor%%\\\"><td>%%title_font%%Search Admin Tools%%title_font_end%%</td></tr>\r\n	<tr><td>$content</td></tr>\r\n</table>\";\r\n\r\nreturn $content;\r\n\r\nsub search_string {\r\n	my ($S, $query, $field) = @_;\r\n\r\n	my $search_string;\r\n	if ($S->cgi->param(\'search_type\') eq \'phrase\') {\r\n		# easy enough\r\n		$search_string = \"$field LIKE \" . $S->dbh->quote(\"%${query}%\");\r\n	} else {\r\n		while ($query =~ /([\\w-]+)/g) {\r\n			if ($search_string) {\r\n				$search_string .= \' AND \'\r\n					if $S->cgi->param(\'search_type\') eq \'all\';\r\n				$search_string .= \' OR \'\r\n					if $S->cgi->param(\'search_type\') eq \'any\';\r\n			}\r\n			$search_string .= \"$field LIKE \" . $S->dbh->quote(\"%${1}%\");\r\n		}\r\n	}\r\n\r\n	return \"($search_string)\";\r\n}\r\n','Simple admin search tool for locating blocks by content or description. This is called from the admin tools menu.','blank_box',!
 0);
+ INSERT INTO box VALUES ('userpref_menu','','my $edit = 0;\r\nmy $return = \'\';\r\nmy $nick = $S->param->{nick};\r\nmy $tool = $S->param->{tool} || \'info\';\r\nmy $admin_edit = \'\';\r\n\r\n# first, do we have permission to edit \r\n# this user\'s prefs?\r\n\r\nif ( $S->{UID} == $S->param->{uid} || $S->have_perm(\'edit_user\') ) {\r\n  $edit = 1;\r\n}\r\n\r\n$admin_edit = qq{[<A href=\"%%rootdir%%/user/$nick/prefs\">edit user</A>]} if ($S->have_perm(\'edit_user\'));\r\n\r\n# links to create\r\nmy $links = \"<P>$admin_edit ${nick}\'s \";\r\n\r\n# user info pages\r\nif ( $tool eq \'info\' ) {\r\n  $links .= qq{\r\n     <A href=\"%%rootdir%%/user/$nick\">Info</A>};\r\n  $links .= qq{\r\n     <A href=\"%%rootdir%%/user/$nick/comments\">Comments</A>};\r\n  $links .= qq{\r\n     <A href=\"%%rootdir%%/user/$nick/stories\">Stories</A>};\r\n\r\n  if ( $S->{UI}->{VARS}->{use_diaries} ) {\r\n    $links .= qq{\r\n     <A href=\"%%rootdir%%/user/$nick/diary\">Diary</A>};\r\n  }\r\n\r\!
 n  if ( $S->{UI}->{VARS}->{use_ratings} ) {\r\n    $links .= qq{\r\n     <A href=\"%%rootdir%%/user/$nick/ratings\">Ratings</A>};\r\n  }\r\n\r\n  if ( $S->{UI}->{VARS}->{allow_uploads} ) {\r\n    $links .= qq{\r\n     <A href=\"%%rootdir%%/user/$nick/files\">Files</A>};\r\n  }\r\n\r\n  if ( $S->{UI}->{VARS}->{use_ads} ) {\r\n    $links .= qq{\r\n     <A href=\"%%rootdir%%/user/$nick/ads\">Ads</A>};\r\n  }\r\n\r\n  $return = $links . \"</P>\";\r\n} elsif ( $edit && $tool eq \'prefs\' ) {\r\n  my %editlinks;\r\n  my ($rv, $sth) = $S->db_select({\r\n               WHAT => \'page\',\r\n               FROM => \'pref_items\',\r\n               GROUP_BY => \'page\'\r\n  });\r\n  while (my ($item) = $sth->fetchrow_array()) {\r\n    $editlinks{\"$item\"} = \"%%rootdir%%/user/$nick/prefs/$item\";\r\n  }\r\n  $links .= qq{\r\n     <A href=\"%%rootdir%%/user/$nick/prefs/Protected\">Protected</A>};\r\n\r\n  foreach my $item (sort {$b cmp $a} keys %editlinks) {\r\n    $links .= qq{\r\n  !
  <A href=\"$editlinks{$item}\">$item</A>};\r\n  }\r\n  $return = $link
s . \"</P>\";\r\n}\r\n\r\nreturn $return;\r\n','navigation for user pref pages','empty_box',0);
+ INSERT INTO box VALUES ('pref_selectbox','','my $prefname = shift @ARGS;\r\nmy $choice = shift @ARGS;\r\nmy @choices = @ARGS;\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"$prefname\" size=\"1\">};\r\n\r\nforeach my $c (@choices) {\r\n  my $checked = ($c eq $choice) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"$c\"$checked>$c</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','Generic select box for user preferences. takes parameters name,value,option1,option2,...\r\nNot suitable for select boxes with code-generated option lists.','empty_box',0);
+ INSERT INTO box VALUES ('pref_checkbox','','my $prefname = $ARGS[0];\r\nmy $choice = $ARGS[1];\r\n\r\nmy $selected = ($choice eq \'on\') ? \' CHECKED\' : \'\';\r\n\r\nreturn qq{<INPUT type=\"checkbox\" name=\"$prefname\" value=\"on\"$selected>};','a generic checkbox. Takes two arguments, the pref name and the current pref value.','empty_box',0);
+ INSERT INTO box VALUES ('time_zone_pref','','my %zones = $S->_timezone_hash();\r\nmy $S_zone = $ARGS[0];\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"time_zone\" size=\"1\">};\r\n\r\nforeach my $zone (sort keys %zones) {\r\n  my $z = uc($zone);\r\n  my $selected = \'\';\r\n  if ($z eq $S_zone) {\r\n    $selected = \' SELECTED\';\r\n  }\r\n  $select .= qq{\r\n         <OPTION value=\"$z\"$selected>[$z] $zones{$zone}</OPTION>};\r\n}\r\n\r\n$select .= \"\r\n      </SELECT>\";\r\n\r\nreturn $select;','timezone selectbox','empty_box',0);
+ INSERT INTO box VALUES ('startpage_pref','','my $choice = $ARGS[0];\r\n\r\nmy @choices = sort keys %{ $S->{SECTION_DATA} };\r\nunshift(@choices, \'__main__\', \'__all__\');\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"start_page\" size=\"1\"};\r\n\r\nforeach my $c (@choices) {\r\n  my $name;\r\n  if ( $c eq \'__main__\' ) {\r\n    $name = \'Front Page\';\r\n  } elsif ( $c eq \'__all__\' ) {\r\n    $name = \'Everything\';\r\n  } else {\r\n    $name = $S->{SECTION_DATA}->{$c}->{title};\r\n  }\r\n  my $checked = ($c eq $choice) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"$c\"$checked>$name</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\nreturn $select;','','empty_box',0);
+ INSERT INTO box VALUES ('img_server_pref','','my $current = $ARGS[0];\r\n\r\nreturn unless $S->var(\'image_mirrors\');\r\nmy @mirrors = split /\\n/, $S->var(\'image_mirrors\');\r\nmy $default_imgdir = $S->{PREF_ITEMS}->{imagedir}->{default_value};\r\n\r\nmy (%servers, $name, $url);\r\n\r\nforeach my $server (@mirrors) {\r\n ($name, $url) = split /,/, $server;\r\n $url =~ s/\\r//;\r\n $servers{$name} = $url;\r\n}\r\n\r\nmy $selected = ( $current eq $default_imgdir ) ? \' SELECTED\' : \'\';\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"imagedir\" size=\"1\">\r\n        <OPTION value=\"$default_imgdir\"$selected>Default</OPTION>};\r\n\r\nforeach my $server (sort keys %servers) {\r\n  $selected = ( $current eq $servers{$server} ) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n         <OPTION value=\"$servers{$server}\"$selected>$server</A>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','','empty_box',0);
+ INSERT INTO box VALUES ('user_theme_pref','','my $choice = $ARGS[0];\r\nmy $themes = $S->{UI}->{VARS}->{user_themes};\r\nmy @themes = split ( /,\\s*/, $themes );\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"theme\">};\r\n\r\nunless ( $S->{PREF_ITEMS}->{theme}->{default_value} ) {\r\n  my $checked = ($choice eq \'\') ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"\"$checked>none</OPTION>};\r\n}\r\n\r\nforeach my $t (@themes) {\r\n  my $checked = ($t eq $choice) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"$t\"$checked>$t</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','','empty_box',0);
+ INSERT INTO box VALUES ('box_pref','','my @choice = @ARGS;\r\n\r\nmy %boxes = %{$S->{BOX_DATA}};\r\nmy $current_prefs;\r\nmy $return = \'\';\r\n\r\n# convert the comma-separated list into a hash\r\nforeach my $i (@choice) {\r\n  $current_prefs->{$i} = 1;\r\n}\r\n\r\nmy $col = 0;\r\n\r\nforeach my $c (keys %boxes) {\r\n  next unless $boxes{$c}->{user_choose};\r\n  $return .= qq{\r\n    <TR>} unless $col;\r\n  my $checked = $current_prefs->{$c} ? \" CHECKED\" : \"\";\r\n  $return .= qq{\r\n      <TD><input type=\"checkbox\" name=\"displayed_boxes\" value=\"$c\"$checked /></TD>\r\n      <TD>$boxes{$c}->{title}</TD>};\r\n  $return .= qq{\r\n    </TR>} if $col;\r\n  $col = ($col) ? \"0\" : \"1\";\r\n}\r\n\r\n$return .= \"<TD></TD><TD></TD></TR>\" if $col;\r\n\r\n$return = qq{\r\n<TABLE border=\"0\">\r\n$return\r\n</TABLE>};\r\n\r\nreturn $return;','','empty_box',0);
+ INSERT INTO box VALUES ('rdf_pref','','my @choice = @ARGS;\r\n\r\nmy $channels = $S->rdf_channels();\r\nmy $current_prefs;\r\nmy $return = \'\';\r\n\r\n# convert the comma-separated list into a hash\r\nforeach my $i (@choice) {\r\n  $current_prefs->{$i} = 1;\r\n}\r\n\r\nmy $col = 0;\r\n\r\nforeach my $c (@{$channels}) {\r\n  $return .= qq{\r\n    <TR>} unless $col;\r\n  next unless $c->{enabled} && $c->{title} && !$c->{submitted};\r\n  my $checked = $current_prefs->{$c->{rid}} ? \" CHECKED\" : \"\";\r\n  $return .= qq{\r\n      <TD><input type=\"checkbox\" name=\"rdf_feeds\" value=\"$c->{rid}\"$checked /></TD>\r\n      <TD><a href=\"%%rootdir%%/special/rdf_preview/?rdf=$c->{rid}\">$c->{title}</a></TD>};\r\n  $return .= qq{\r\n    </TR>} if $col;\r\n  $col = ($col) ? \"0\" : \"1\";\r\n}\r\n\r\n$return .= \"<TD></TD><TD></TD></TR>\" if $col;\r\n\r\n$return = qq{\r\n<TABLE border=\"0\">\r\n$return\r\n</TABLE>};\r\n\r\nreturn $return;','','empty_box',0);
+ INSERT INTO box VALUES ('rating_order_pref','','my $choice = $ARGS[0];\r\n\r\nmy %choices = ( \"unrate_highest\", \"Unrated, then Highest\", \"highest\", \"Highest rated first\", \"lowest\", \"Lowest rated first\", \"dontcare\", \"Ignore ratings\" );\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"commentrating\" size=\"1\">};\r\n\r\nforeach my $c (keys %choices) {\r\n  my $checked = ($c eq $choice) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"$c\"$checked>$choices{$c}</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','','empty_box',0);
+ INSERT INTO box VALUES ('postmode_pref','','my $choice = $ARGS[0];\r\n\r\nmy %choices = ( \"text\", \"Plain Text\", \"html\", \"HTML Formatted\", \"auto\", \"Autoformat\" );\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"posttype\" size=\"1\">};\r\n\r\nforeach my $c (keys %choices) {\r\n  my $checked = ($c eq $choice) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"$c\"$checked>$choices{$c}</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','','empty_box',0);
+ INSERT INTO box VALUES ('show_hidden_pref','','my $current = $ARGS[0];\r\n\r\nmy $choices = {\r\n    \'yes\' => \'Yes\',\r\n    \'no\' => \'No\',\r\n    \'untilrating\' => \"Show until I\'ve rated\"\r\n};\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"hidingchoice\" size=\"1\">};\r\n\r\nforeach my $choice (keys %{$choices}) {\r\n    my $selected = $choice eq $current ? \' SELECTED\' : \'\';\r\n    $select .= qq{\r\n        <OPTION value=\"$choice\"$selected>$choices->{$choice}</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','','empty_box',0);
+ INSERT INTO box VALUES ('user_group_box','','my ($curr_id) = $ARGS[0];\r\n\r\nmy ($rv, $sth) = $S->db_select({\r\n  WHAT => \'perm_group_id\',\r\n  FROM => \'perm_groups\',\r\n  DEBUG => 0});\r\n\r\nmy $selector = qq{\r\n<SELECT NAME=\"perm_group_id\" SIZE=1>};\r\n\r\nmy $selected = \'\';\r\n\r\nwhile (my $group = $sth->fetchrow()) {\r\n  $selected = \'\';\r\n  $selected = \" SELECTED\" if ($group eq $curr_id);\r\n  $selector .= qq{\r\n  <OPTION VALUE=\"$group\"$selected>$group};\r\n}\r\n\r\n$selector .= \"</SELECT>\";\r\n\r\nreturn $selector;\r\n','','empty_box',0);
+ INSERT INTO box VALUES ('subscriber','','return unless ($S->{UID} == $S->param->{uid});\r\nreturn unless ($S->have_perm(\'allow_subscription\'));\r\nreturn unless ($S->{UI}->{VARS}->{use_subscriptions});\r\n\r\nmy $user = $S->user_data($S->{UID});\r\n\r\nwarn \"(subscriber) active subscription? $user->{sub}->{active}\";\r\n\r\nif ( $user->{sub}->{active} ) {\r\n  my $expires = $user->{sub}->{expires};\r\n  my $now = time;\r\n  my $remaining_days = (int((($expires - $now) / 86400)) + 1);\r\n  return qq{Thank you for subscribing. Your subscription expires in $remaining_days days};\r\n} else {\r\n  return qq{\r\n<P>You are not currently a subscriber. Why not <A href=\"%%rootdir%%/subscribe\">become one</A>?};\r\n}','','empty_box',0);
+ INSERT INTO box VALUES ('commentmode_overflow_pref','','my $choice = $ARGS[0];\r\n\r\nmy %choices = ( \"minimal\", \"Minimal\", \"threaded\", \"Threaded\", \"nested\", \"Nested\", \"flat\", \"Flat\", \"flat_unthread\", \"Flat (unthread)\" );\r\n\r\nif ( $S->var(\'allow_dynamic_comment_mode\') && $S->pref(\'dynamic_interface\') eq \'on\' ) {\r\n  $choices{\'dminimal\'} = \"Dynamic Minimal\";\r\n  $choices{\'dthreaded\'} = \"Dynamic Threaded\";\r\n} else {\r\n  $choice =~ s/^d//;\r\n}\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"commentmode_overflow\" size=\"1\">};\r\n\r\nforeach my $c (sort keys %choices) {\r\n  my $checked = ($c eq $choice) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"$c\"$checked>$choices{$c}</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','','empty_box',0);
+ INSERT INTO box VALUES ('commentmode_pref','','my $choice = $ARGS[0];\r\n\r\nmy %choices = ( \"use_overflow\", \"Always use overflow mode\", \"minimal\", \"Minimal\", \"threaded\", \"Threaded\", \"nested\", \"Nested\", \"flat\", \"Flat\", \"flat_unthread\", \"Flat (unthreaded)\" );\r\n\r\nif ( $S->var(\'allow_dynamic_comment_mode\') && $S->pref(\'dynamic_interface\') eq \'on\' ) {\r\n  $choices{\'dminimal\'} = \"Dynamic Minimal\";\r\n  $choices{\'dthreaded\'} = \"Dynamic Threaded\";\r\n} else {\r\n  $choice =~ s/^d//;\r\n}\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"commentmode\" size=\"1\">};\r\n\r\nforeach my $c (sort keys %choices) {\r\n  my $checked = ($c eq $choice) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"$c\"$checked>$choices{$c}</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','','empty_box',0);
+ INSERT INTO box VALUES ('cookie_expire_pref','','my $choice = $ARGS[0];\r\n\r\nmy %choices = ( \"3600\", \"1 hour\", \"86400\", \"1 day\", \"604800\", \"1 week\", \"1209600\", \"2 weeks\", \"2592000\", \"1 month (30 days)\", \"5184000\", \"2 months\" );\r\n\r\nmy $select = qq{\r\n      <SELECT name=\"cookie_expire\" size=\"1\">};\r\n\r\nforeach my $c (sort {$a <=> $b} keys %choices) {\r\n  my $checked = ($c eq $choice) ? \' SELECTED\' : \'\';\r\n  $select .= qq{\r\n        <OPTION value=\"$c\"$checked>$choices{$c}</OPTION>};\r\n}\r\n\r\n$select .= qq{\r\n      </SELECT>};\r\n\r\nreturn $select;','','empty_box',0);
  
  #
***************
*** 719,723 ****
  INSERT INTO ops VALUES ('olderlist','default_template','olderlist',0,1,'','','','Gives a listing of older stories.');
  INSERT INTO ops VALUES ('search','default_template','search',0,1,'','find','length=2:/type/string/,\n/string/','Everything related to searching content on the site.');
- INSERT INTO ops VALUES ('interface','default_template','interface_prefs',0,1,'','','/tool/','Displays and edits preferences.');
  INSERT INTO ops VALUES ('user','default_template','edit_user',0,1,'','whois my ~.+','EVAL{\r\n  my $p = {};\r\n  if ($S->cgi->param(\'caller_op\') eq \'my\') {\r\n    unshift @path__COMMA__ $S->{NICK};\r\n  } elsif ($S->cgi->param(\'caller_op\') =~ m/^~(.+)$/) {\r\n    unshift @path__COMMA__ $1;\r\n  }\r\n  my $uid;\r\n  if ($path[0] =~ /uid:/) {\r\n    $path[0] =~ s/^uid://;\r\n    $uid = $path[0];\r\n    $path[0] = $S->get_nick_from_uid($uid);\r\n  } else {\r\n    $uid=$S->get_uid_from_nick($path[0]); \r\n  }\r\n  if ($path[1] eq \'edit\') { $path[1] = \'prefs\' }\r\n  if ($path[1] eq \'diary\') {\r\n    $p = {\r\n      op      => \'section\'__COMMA__\r\n      user    => \"$path[0]\"__COMMA__\r\n      section => \'Diary\'__COMMA__\r\n      page    => $path[2]\r\n    };\r\n  } elsif ($path[1] =~ /comment/) {\r\n    $p->{op}      = \'search\';\r\n    $p->{type}    = \'comment_by\';\r\n    $p->{string}  = $path[0];\r\n  } elsif ($path[1] eq \'ads\') {\r\n    $p->{op}      =!
  \'adinfo\';\r\n    $p->{ad_id}   = \"uid:$uid\";\r\n  } elsif ($path[1] eq \'stories\' || $path[1] eq \'story\') {\r\n    $p->{op}      = \'search\';\r\n    $p->{type}    = \'author\';\r\n    $p->{string}  = $path[0];\r\n  } else {\r\n    $p->{op}      = \'user\';\n    $p->{action}  = $path[2];\r\n    $p->{tool}    = $path[1];\r\n    $p->{nick}    = $path[0];\r\n    $p->{uid}     = $uid;\r\n  }\r\n  return $p;\r\n}','Display and edit registered users.');
  INSERT INTO ops VALUES ('section','index_template','main_page',0,1,'','','/section/page/','Lists the stories, with intros, that are in a specified section.');
--- 749,752 ----
***************
*** 890,893 ****
--- 919,926 ----
  INSERT INTO patches VALUES ('1_1-dev',1,'MultiPolls','sql');
  INSERT INTO patches VALUES ('1_1-dev',2,'Sessions','sql');
+ INSERT INTO patches VALUES ('1_1-dev',3,'CommentPost','sql');
+ INSERT INTO patches VALUES ('1_1-dev',4,NULL,'pre');
+ INSERT INTO patches VALUES ('1_1-dev',4,'UserPrefs','sql');
+ INSERT INTO patches VALUES ('1_1-dev',4,NULL,'post');
  
  #
***************
*** 909,915 ****
  INSERT INTO perm_groups VALUES ('Anonymous','comment_post,poll_vote,story_post,poll_post_comments,poll_read_comments,view_polls',0,'Anonymous users');
  INSERT INTO perm_groups VALUES ('Users','attach_poll,comment_post,comment_rate,moderate,poll_post_comments,poll_read_comments,poll_vote,story_post,submit_ad,submit_rdf,view_polls,use_spellcheck,editorial_comments',1,'Normal users. This should be the default perm level probably.');
! INSERT INTO perm_groups VALUES ('Editors','attach_poll,comment_post,comment_rate,edit_polls,edit_special,list_polls,moderate,poll_post_comments,poll_read_comments,poll_vote,story_admin,story_list,story_post,submit_ad,submit_rdf,view_polls,use_spellcheck,editorial_comments,view_log',0,'Editorial administrators');
! INSERT INTO perm_groups VALUES ('Admins','ad_admin,attach_poll,comment_delete,comment_post,comment_rate,edit_blocks,edit_macros,edit_polls,edit_sections,edit_special,edit_user,edit_vars,editorial_comments,list_polls,moderate,poll_post_comments,poll_read_comments,poll_vote,rdf_admin,story_admin,story_list,story_post,submit_ad,upload_admin,use_spellcheck,view_comment_ip,view_log,view_polls,admin_search',0,'Site administrators and junk');
! INSERT INTO perm_groups VALUES ('Superuser','ad_admin,attach_poll,comment_delete,comment_post,comment_rate,cron_admin,edit_blocks,edit_boxes,edit_groups,edit_hooks,edit_macros,edit_ops,edit_own_story,edit_polls,edit_sections,edit_special,edit_topics,edit_user,edit_vars,editorial_comments,hotlist,list_polls,make_new_accounts,moderate,poll_post_comments,poll_read_comments,poll_vote,rdf_admin,show_hidden_sections,story_admin,story_commentstatus_select,story_displaystatus_select,story_list,story_post,submit_ad,submit_rdf,subscription_admin,super_mojo,upload_admin,upload_content,upload_user,use_spellcheck,view_comment_ip,view_log,view_polls,bypass_safe_mode,admin_search',0,'All permissions');
  INSERT INTO perm_groups VALUES ('Advertisers','attach_poll,comment_post,comment_rate,moderate,poll_post_comments,poll_read_comments,poll_vote,story_post,submit_ads,submit_rdf,view_polls,submit_ad,use_spellcheck,editorial_comments',0,'Advertiser group, these people should be able to submit ads.');
  
--- 942,948 ----
  INSERT INTO perm_groups VALUES ('Anonymous','comment_post,poll_vote,story_post,poll_post_comments,poll_read_comments,view_polls',0,'Anonymous users');
  INSERT INTO perm_groups VALUES ('Users','attach_poll,comment_post,comment_rate,moderate,poll_post_comments,poll_read_comments,poll_vote,story_post,submit_ad,submit_rdf,view_polls,use_spellcheck,editorial_comments',1,'Normal users. This should be the default perm level probably.');
! INSERT INTO perm_groups VALUES ('Editors','attach_poll,comment_post,comment_rate,edit_polls,edit_special,list_polls,moderate,poll_post_comments,poll_read_comments,poll_vote,story_admin,story_list,story_post,submit_ad,submit_rdf,view_polls,use_spellcheck,editorial_comments,view_log,ad_opt_out,edit_prefs',0,'Editorial administrators');
! INSERT INTO perm_groups VALUES ('Admins','ad_admin,attach_poll,comment_delete,comment_post,comment_rate,edit_blocks,edit_macros,edit_polls,edit_sections,edit_special,edit_user,edit_vars,editorial_comments,list_polls,moderate,poll_post_comments,poll_read_comments,poll_vote,rdf_admin,story_admin,story_list,story_post,submit_ad,upload_admin,use_spellcheck,view_comment_ip,view_log,view_polls,admin_search,ad_opt_out,edit_prefs',0,'Site administrators and junk');
! INSERT INTO perm_groups VALUES ('Superuser','ad_admin,attach_poll,comment_delete,comment_post,comment_rate,cron_admin,edit_blocks,edit_boxes,edit_groups,edit_hooks,edit_macros,edit_ops,edit_own_story,edit_polls,edit_sections,edit_special,edit_topics,edit_user,edit_vars,editorial_comments,hotlist,list_polls,make_new_accounts,moderate,poll_post_comments,poll_read_comments,poll_vote,rdf_admin,show_hidden_sections,story_admin,story_commentstatus_select,story_displaystatus_select,story_list,story_post,submit_ad,submit_rdf,subscription_admin,super_mojo,upload_admin,upload_content,upload_user,use_spellcheck,view_comment_ip,view_log,view_polls,bypass_safe_mode,admin_search,ad_opt_out,edit_prefs',0,'All permissions');
  INSERT INTO perm_groups VALUES ('Advertisers','attach_poll,comment_post,comment_rate,moderate,poll_post_comments,poll_read_comments,poll_vote,story_post,submit_ads,submit_rdf,view_polls,submit_ad,use_spellcheck,editorial_comments',0,'Advertiser group, these people should be able to submit ads.');
  
***************
*** 998,1001 ****
--- 1031,1107 ----
  
  #
+ # Table structure for table 'pref_items'
+ #
+ 
+ CREATE TABLE pref_items (
+   prefname varchar(32) NOT NULL default '',
+   title varchar(50) NOT NULL default '',
+   description text,
+   visible int(1) default '0',
+   html int(1) default '0',
+   perm_view varchar(32) default NULL,
+   perm_edit varchar(32) default NULL,
+   var varchar(32) default NULL,
+   req_tu int(1) default '0',
+   default_value text,
+   length int(5) default NULL,
+   regex text,
+   page varchar(50) default NULL,
+   field text,
+   display_order int(5) default NULL,
+   template varchar(30) default NULL,
+   display_fmt text,
+   enabled int(1) default '1',
+   required int(1) default '0',
+   PRIMARY KEY  (prefname),
+   KEY page_idx (page)
+ ) TYPE=MyISAM;
+ 
+ #
+ # Dumping data for table 'pref_items'
+ #
+ 
+ INSERT INTO pref_items VALUES ('admin_notes','Admin Notes','Information about the user that only site administrators can see',1,1,'edit_user','edit_user','allow_admin_notes',0,'',0,'','User Info','<textarea COLS=\"50\" ROWS=\"5\" NAME=\"admin_notes\" WRAP=\"soft\">%%value%%</textarea>',3,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('fakeemail','Email','This is the address that will be displayed in comments and in your user info. It will not be used to email forgotten passwords. You may want to add some kind of spam protection so that harvesters cannot parse it.',1,0,'','','',0,'',50,'','User Info','<input TYPE=\"text\" SIZE=\"50\" NAME=\"fakeemail\" VALUE=\"%%value%%\">',5,'text_pref','<A href=\"mailto:%%value%%\">%%value%%</A>',1,0);
+ INSERT INTO pref_items VALUES ('homepage','Homepage','If you have a homepage, enter the address here and it will be added to your comments and user info. The full path is required: remember the \"http://\"!',1,0,'','','',0,'',100,'^http','User Info','<input TYPE=\"text\" SIZE=\"50\" NAME=\"homepage\" VALUE=\"%%value%%\">',6,'text_pref','<A href=\"%%value%%\">%%value%%</A>',1,0);
+ INSERT INTO pref_items VALUES ('bio','Bio','Enter any kind of biographical information you want other users to see about yourself here.',1,1,'','','',0,'',255,'','User Info','<textarea COLS=\"50\" ROWS=\"5\" WRAP=\"soft\" NAME=\"bio\">%%value%%</textarea>',7,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('publickey','Public Key','If you have a PGP/GPG public key (used for encrypting and signing email), paste it in here.',1,0,'','','',0,'',0,'','User Info','<textarea COLS=\"50\" ROWS=\"5\" NAME=\"publickey\">%%value%%</textarea>',8,'text_pref','<pre>%%value%%</pre>',1,0);
+ INSERT INTO pref_items VALUES ('upload_user_quota','Disk Quota','The maximum amount of space this user can take up with his uploaded files (in kb)',0,0,'','edit_user','allow_uploads',0,'0',0,'\\d+','Interface','<INPUT type=\"text\" name=\"upload_user_quota\" value=\"%%value%%\" size=\"5\">',0,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('upload_max_file_size','Max File Size','The maximum size a single file can be (in kb)',0,0,'','edit_user','allow_uploads',0,'0',0,'\\d+','Interface','<INPUT type=\"text\" name=\"upload_max_file_size\" value=\"%%value%%\" size=\"5\">',0,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('digest','Story Digest','Story headlines and intros can be emailed to you at your real email address on the schedule you choose.',0,0,'','','enable_story_digests',0,'Never',10,'(Never|Daily|Weekly|Monthly)','Interface','%%BOX,pref_selectbox,digest,%%value%%,Never,Daily,Weekly,Monthly%%',1,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('time_zone','Your Time Zone','Setting your (non-daylight savings) time zone here will make the site display all times and dates in your local time',0,0,'','','',0,'EST',4,'[a-zA-z]+','Interface','%%BOX,time_zone_pref,%%value%%%%',2,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('maxstories','Number of story summaries to show','(on front page)',0,0,'','','',0,'8',3,'\\d+','Interface','<input type=\"text\" size=\"5\" name=\"maxstories\" value=\"%%value%%\">',3,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('maxtitles','Number of story titles to show','(in \"older stories\" box)',0,0,'','','',0,'10',3,'\\d+','Interface','<input type=\"text\" size=\"5\" name=\"maxtitles\" value=\"%%value%%\">',4,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('textarea_cols','Text box width','This allows you to set how big of a text box you have to type stories and comments into.',0,0,'','','',0,'50',4,'\\d+','Interface','<input type=\"text\" size=\"5\" name=\"textarea_cols\" value=\"%%value%%\">',5,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('textarea_rows','Text box height','This allows you to set how big of a text box you have to type stories and comments into.',0,0,'','','',0,'15',4,'\\d+','Interface','<input type=\"text\" size=\"5\" name=\"textarea_rows\" value=\"%%value%%\">',6,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('norm_font_face','Font Face','',0,0,'','','',0,'verdana, arial, helvetica, sans-serif',0,'[a-zA-z,\\s]','Interface','<input type=\"text\" size=\"30\" name=\"norm_font_face\" value=\"%%value%%\" />',7,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('norm_font_size','Font Size','',0,0,'','','',0,'2',5,'\\w+','Interface','<input type=\"text\" size=\"5\" name=\"norm_font_size\" value=\"%%value%%\">',8,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('showad','Show ads','',0,0,'','ad_opt_out','use_ads',0,'All',16,'^(on|off)$','Interface','%%BOX,pref_checkbox,showad,%%value%%%%',9,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('ad_open_new_win','Open advertisement clicks in new window','',0,0,'','','use_ads',0,'off',3,'^(on|off)$','Interface','%%BOX,pref_checkbox,ad_open_new_win,%%value%%%%',10,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('show_topic','Show topic images with stories','',0,0,'','','use_topics',0,'on',3,'^(on|off)$','Interface','%%BOX,pref_checkbox,show_topic,%%value%%%%',11,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('start_page','Start page','',0,0,'','','',0,'__main__',0,'\\w+','Interface','%%BOX,startpage_pref,%%value%%%%',12,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('online_cloak','Hide yourself in the Who\'s Online box','',0,0,'','','use_whosonline',0,'off',3,'^(on|off)$','Interface','%%BOX,pref_checkbox,online_cloak,%%value%%%%',13,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('dynamic_interface','Use dynamic interface elements','This turns on javascript-driven items such as dynamic comment mode',0,0,'','','allow_dynamic_comment_mode',0,'off',3,'^(on|off)$','Interface','%%BOX,pref_checkbox,dynamic_interface,%%value%%%%',14,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('spellcheck_default','Spellcheck posts by default','',0,0,'','use_spellcheck','spellcheck_enabled',0,'off',3,'^(on|off)$','Interface','%%BOX,pref_checkbox,spellcheck_default,%%value%%%%',15,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('speling','Spelling variant','',0,0,'','use_spellcheck','spellcheck_enabled',0,'american',8,'(American|Canadian|British)','Interface','%%BOX,pref_selectbox,speling,%%value%%,American,Canadian,British%%',16,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('imagedir','Preferred image server','Choose an image server closest to you for the quickest page load times',0,0,'','','use_alt_image_servers',0,'/images',0,'','Interface','%%BOX,img_server_pref,%%value%%%%',17,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('theme','Use which theme','',0,0,'','','allow_user_themes',0,'',0,'\\w+','Interface','%%BOX,user_theme_pref,%%value%%%%',18,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('cookie_expire','Cookie Expiry','How long does your login cookie last?',0,0,'','','',0,'2592000',0,'','Interface','%%BOX,cookie_expire_pref,%%value%%%%',19,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('displayed_boxes','Boxes','',0,0,'','','',0,'hotlist_box,poll_box,rdf_feeds,whos_online',0,'','Interface','%%BOX,box_pref,%%value%%%%',20,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('max_rdf_titles','Maximum headlines per feed','',0,0,'','','use_rdf_feeds',0,'15',2,'\\d+','Interface','<input type=\"text\" name=\"max_rdf_titles\" value=\"%%value%%\" size=\"5\">',21,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('rdf_feeds','External Feeds','[<a href=\"%%rootdir%%/submitrdf\">Submit New Feed</A>]',0,0,'','','use_rdf_feeds',0,'',0,'','Interface','%%BOX,rdf_pref,%%value%%%%',22,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('commentmode','Comment display mode','',0,0,'','','',0,'threaded',0,'(use_overflow|minimal|dminimal|threaded|dthreaded|nested|flat|flat_unthread)','Comments','%%BOX,commentmode_pref,%%value%%%%',1,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('commentmode_overflow_at','Change to overflow mode at','',0,0,'','','',0,'200',0,'\\d+','Comments','<input type=\"text\" size=\"10\" name=\"commentmode_overflow_at\" value=\"%%value%%\">',2,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('commentmode_overflow','Comment display mode (overflow)','Comment display modes:\n<UL>\n <LI>flat (unthreaded): straight chronological order</LI>\n <LI>flat: comments and replies grouped, but not indented</LI>\n <LI>minimal: titles only, replies indented</LI>\n <LI>threaded: top-level comments expanded, all other titles only, replies indented</LI>\n <LI>nested: all comments shown in full, replies indented</LI>\n</UL>',0,0,'','','',0,'threaded',0,'(minimal|dminimal|threaded|dthreaded|nested|flat|flat_unthread)','Comments','%%BOX,commentmode_overflow_pref,%%value%%%%',3,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('commenttype','Types of comments to display','',0,0,'','','',0,'mixed',10,'(mixed|topical|editorial|all|none)','Comments','%%BOX,pref_selectbox,commenttype,%%value%%,mixed,topical,editorial,all,none%%',4,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('commentrating','Sorting based on comment ratings','',0,0,'','','use_ratings',0,'highest',15,'(unrate_highest|highest|lowest|dontcare)','Comments','%%BOX,rating_order_pref,%%value%%%%',5,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('commentorder','Sorting based on comment age','',0,0,'','','',0,'oldest',6,'(newest|oldest)','Comments','%%BOX,pref_selectbox,commentorder,%%value%%,newest,oldest%%',6,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('ratingchoice','Rate comments','',0,0,'','comment_rate','use_ratings',0,'yes',4,'(yes|no|hide)','Comments','%%BOX,pref_selectbox,ratingchoice,%%value%%,yes,no,hide%%',7,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('hidingchoice','Show hidden comments','',0,0,'','','use_ratings',1,'untilrating',11,'(yes|no|untilrating)','Comments','%%BOX,show_hidden_pref,%%value%%%%',8,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('posttype','Post mode','',0,0,'','','',0,'auto',4,'(text|html|auto)','Comments','%%BOX,postmode_pref,%%value%%%%',9,'selectbox_pref','',1,0);
+ INSERT INTO pref_items VALUES ('sig','Signature','This will get attached to your comments. Sigs are typically used for quotations or links',0,1,'','comment_post','',0,'',160,'','Comments','<textarea COLS=\"50\" ROWS=\"5\" WRAP=\"soft\" NAME=\"sig\">%%value%%</textarea>',10,'text_pref','',1,0);
+ INSERT INTO pref_items VALUES ('sig_behavior','Signature type','',0,0,'','comment_post','allow_sig_behavior',0,'retroactive',11,'(retroactive|sticky|none)','Comments','%%BOX,pref_selectbox,sig_behavior,%%value%%,retroactive,sticky,none%%',11,'selectbox_pref','',1,0);
+ 
+ #
  # Table structure for table 'rdf_channels'
  #
***************
*** 1361,1364 ****
--- 1467,1473 ----
  #
  
+ INSERT INTO userprefs VALUES (1,'homepage','http://www.kuro5hin.org/');
+ INSERT INTO userprefs VALUES (1,'fakeemail','scoop at example.com');
+ INSERT INTO userprefs VALUES (1,'uid','1');
  
  #
***************
*** 1369,1394 ****
    uid int(11) NOT NULL auto_increment,
    nickname varchar(50) default NULL,
-   realname varchar(50) default NULL,
    realemail varchar(50) default NULL,
    origemail varchar(50) default NULL,
-   fakeemail varchar(50) default NULL,
-   homepage varchar(100) default NULL,
    passwd varchar(12) default NULL,
-   mode varchar(10) default NULL,
-   posttype varchar(10) default NULL,
-   bio varchar(255) default NULL,
-   sig varchar(160) default NULL,
-   mailreplies int(1) default NULL,
    trustlev int(1) default NULL,
-   threshold int(1) default NULL,
-   score int(1) default NULL,
-   points int(1) default NULL,
-   commentsort int(1) default '0',
-   defaultpoints int(1) default '0',
-   publickey text,
-   perms varchar(255) default NULL,
    perm_group varchar(50) default NULL,
    mojo varchar(5) default NULL,
-   admin_notes text,
    creation_ip varchar(16) NOT NULL default '',
    creation_time datetime NOT NULL default '0000-00-00 00:00:00',
--- 1478,1487 ----
***************
*** 1403,1407 ****
  #
  
! INSERT INTO users VALUES (1,'scoop','','scoop at example.com','scoop at example.com','scoop at example.com','http://www.kuro5hin.org/','MioQ79w6.4o','thread','plaintext','','',0,1,0,0,0,NULL,0,'',NULL,'Superuser',NULL,'','','0000-00-00 00:00:00',NULL,NULL,NULL);
  
  #
--- 1496,1500 ----
  #
  
! INSERT INTO users VALUES (1,'scoop','scoop at example.com','scoop at example.com','MioQ79w6.4o',1,'Superuser',NULL,'','0000-00-00 00:00:00',NULL,NULL,1);
  
  #
***************
*** 1425,1440 ****
  INSERT INTO vars VALUES ('queue_edit_max_time','2h','<P>This variable determines how long a story may remain in the edit queue before being forced to voting.  The possible values are a number followed by a letter indicating the time unit.  The default value is 2h (2 hours).<BR>\nRecognised time units are s (seconds), m (minutes), h (hours) and d (days).  The author of a story in the edit queue may move the story to voting at any time; if this hasn\'t happened by the time this time limit has been reached, Scoop will force the story to voting.  This variable has no effect unless the edit queue is active.</P>','text','Stories');
  INSERT INTO vars VALUES ('rootdir','','<P>This variable is the path that must precede all Scoop-generated pseudo-directories.  The possible values are any absolute path prefix, with no trailing slash.  The default is blank.<BR>\nThis will only be used if you are installing Scoop into a subdirectory.  If you are installing Scoop on its own virtualhost, this should be blank.  See the Scoop Admin Guide for details on how this variable should be set.</P>','text','General');
- INSERT INTO vars VALUES ('imagedir','/images','<P>This variable is used as a prefix for all image files.  The possible values are either an absolute pathname on the local server (\"/images\") with no trailing slash, or a fully qualified URL on a different server (\"http://images.example.com\") with no trailing slash.<BR>\nIf the value does no