[Slashdotjp-dev 725] [234] merged from 2.5.0.181

アーカイブの一覧に戻る

svnno****@sourc***** svnno****@sourc*****
2007年 10月 31日 (水) 14:54:45 JST


Revision: 234
          http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=slashdotjp&view=rev&rev=234
Author:   tach
Date:     2007-10-31 14:54:43 +0900 (Wed, 31 Oct 2007)

Log Message:
-----------
merged from 2.5.0.181

Modified Paths:
--------------
    slashjp/trunk/Slash/DB/MySQL/MySQL.pm
    slashjp/trunk/Slash/Slash.pm
    slashjp/trunk/Slash/Utility/Display/Display.pm
    slashjp/trunk/Slash/Utility/Environment/Environment.pm
    slashjp/trunk/debian/changelog
    slashjp/trunk/plugins/Admin/admin.pl
    slashjp/trunk/plugins/Admin/templates/editStory;admin;default
    slashjp/trunk/plugins/Admin/templates/static_files;admin;default
    slashjp/trunk/plugins/Ajax/htdocs/ajax.pl
    slashjp/trunk/plugins/Ajax/htdocs/images/admin.js
    slashjp/trunk/plugins/Ajax/htdocs/images/common.js
    slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js
    slashjp/trunk/plugins/Ajax/templates/data;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default
    slashjp/trunk/plugins/Blob/Blob.pm
    slashjp/trunk/plugins/Bookmark/templates/bookmarklink;misc;default
    slashjp/trunk/plugins/Bookmark/templates/bookmarktext;misc;default
    slashjp/trunk/plugins/Console/templates/display;console;default
    slashjp/trunk/plugins/FAQSlashdot/faq/UI.shtml
    slashjp/trunk/plugins/FireHose/FireHose.pm
    slashjp/trunk/plugins/FireHose/firehose.css
    slashjp/trunk/plugins/FireHose/mysql_schema.sql
    slashjp/trunk/plugins/FireHose/templates/data;firehose;default
    slashjp/trunk/plugins/FireHose/templates/firehose_options;misc;default
    slashjp/trunk/plugins/FireHose/templates/list;firehose;default
    slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivadmin;misc;default
    slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivtagbox;misc;default
    slashjp/trunk/plugins/Journal/Journal.pm
    slashjp/trunk/plugins/Messages/PLUGIN
    slashjp/trunk/plugins/Messages/messages.pl
    slashjp/trunk/plugins/Messages/templates/emailsponsor;messages;default
    slashjp/trunk/plugins/Remarks/Remarks.pm
    slashjp/trunk/plugins/Remarks/templates/display;remarks;default
    slashjp/trunk/plugins/Submit/submit.pl
    slashjp/trunk/plugins/Submit/templates/displayForm;submit;default
    slashjp/trunk/plugins/Tags/Clout/Describe.pm
    slashjp/trunk/plugins/Tags/Clout/Moderate.pm
    slashjp/trunk/plugins/Tags/Clout/Vote.pm
    slashjp/trunk/plugins/Tags/Clout.pm
    slashjp/trunk/plugins/Tags/Tags.pm
    slashjp/trunk/plugins/Tags/tags_updateclouts.pl
    slashjp/trunk/plugins/Tags/templates/tagsstorydivadmin;misc;default
    slashjp/trunk/plugins/Tags/templates/tagsstorydivtagbox;misc;default
    slashjp/trunk/plugins/Tags/templates/tagsurldivadmin;misc;default
    slashjp/trunk/plugins/Tags/templates/tagsurldivtagbox;misc;default
    slashjp/trunk/sql/mysql/defaults.sql
    slashjp/trunk/sql/mysql/slashschema_create.sql
    slashjp/trunk/sql/mysql/upgrades
    slashjp/trunk/themes/slashcode/htdocs/comments.css
    slashjp/trunk/themes/slashcode/htdocs/images/comments.js
    slashjp/trunk/themes/slashcode/htdocs/images/comments2.js
    slashjp/trunk/themes/slashcode/tasks/process_file_queue.pl
    slashjp/trunk/themes/slashcode/templates/dispComment;misc;default
    slashjp/trunk/themes/slashcode/templates/dispCommentDetails;misc;default
    slashjp/trunk/themes/slashcode/templates/dispStory;misc;default
    slashjp/trunk/themes/slashcode/templates/edit_comment;comments;default
    slashjp/trunk/themes/slashcode/templates/ipid_display;misc;default
    slashjp/trunk/themes/slashcode/templates/linkComment;misc;default
    slashjp/trunk/themes/slashcode/templates/messages;users;default
    slashjp/trunk/themes/slashcode/templates/printCommComments;misc;default
    slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default
    slashjp/trunk/themes/slashcode/templates/userlogin_cover;misc;default


-------------- next part --------------
Modified: slashjp/trunk/Slash/DB/MySQL/MySQL.pm
===================================================================
--- slashjp/trunk/Slash/DB/MySQL/MySQL.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/Slash/DB/MySQL/MySQL.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -282,6 +282,8 @@
 
 	'd2_comment_order'
 		=> sub { $_[0]->sqlSelectMany('code, name', 'code_param', "type='d2_comment_order'") },
+	'mediatypes'
+		=> sub { $_[0]->sqlSelectMany('code, name', 'string_param', "type='mediatypes'")}
 );
 
 ########################################################
@@ -6064,7 +6066,7 @@
 
 	if ($cid && $one_cid_only) {
 		$where .= "AND cid=$cid";
-	} elsif ($user->{hardthresh}) {
+	} elsif ($user->{hardthresh} && !$options->{discussion2}) {
 		my $threshold_q = $self->sqlQuote($user->{threshold});
 		$where .= "AND (comments.points >= $threshold_q";
 		$where .= "  OR comments.uid=$user->{uid}"	unless $user->{is_anon};

Modified: slashjp/trunk/Slash/Slash.pm
===================================================================
--- slashjp/trunk/Slash/Slash.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/Slash/Slash.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -105,6 +105,7 @@
 		cache_read_only	=> $cache_read_only,
 		one_cid_only	=> $options->{one_cid_only},
 	};
+	$gcfu_opt->{discussion2} = $discussion2;
 	if ($options->{force_read_from_master}) {
 		$thisComment = $slashdb->getCommentsForUser($discussion->{id}, $cid, $gcfu_opt);
 	} else {
@@ -1212,7 +1213,7 @@
 		} else {
 			my $pntcmt = @{$comments->{$comment->{pid}}{kids}} > $user->{commentspill};
 			$return .= $const->{commentbegin} .
-				linkComment($comment, $pntcmt, 1);
+				linkComment($comment, $pntcmt, { date => 1 });
 			$finish_list++;
 		}
 		$return .= $const->{fullcommentend} if ($user->{mode} eq 'flat');
@@ -1220,9 +1221,12 @@
 		if ($comment->{kids} && ($user->{mode} ne 'parents' || $pid)) {
 			if (my $str = displayThread($sid, $cid, $lvl+1, $comments, $const)) {
 				$return .= $const->{cagebegin} if $cagedkids;
-				$return .= $const->{indentbegin} if $indent;
+				if ($indent && $const->{indentbegin}) {
+					(my $indentbegin = $const->{indentbegin}) =~ s/^(<[^<>]+)>$/$1 id="commtree_$cid">/;
+					$return .= $indentbegin;
+				}
 				$return .= $str;
-				$return .= "$const->{indentend}" if $indent;
+				$return .= $const->{indentend} if $indent;
 				$return .= $const->{cageend} if $cagedkids;
 			}
 			# in flat or nested mode, all visible kids will
@@ -1350,7 +1354,7 @@
 		vislenify($comment); # create $comment->{ipid_vis} and {subnetid_vis}
 		if ($constants->{comments_hardcoded}) {
 			$comment->{ipid_display} = <<EOT;
-<br>IPID: <a href="$constants->{real_rootdir}/users.pl?op=userinfo&amp;userfield=$comment->{ipid}&amp;fieldname=ipid">$comment->{ipid_vis}</a>&nbsp;&nbsp;SubnetID: 
+IPID: <a href="$constants->{real_rootdir}/users.pl?op=userinfo&amp;userfield=$comment->{ipid}&amp;fieldname=ipid">$comment->{ipid_vis}</a>&nbsp;&nbsp;SubnetID: 
 <a href="$constants->{real_rootdir}/users.pl?op=userinfo&amp;userfield=$comment->{subnetid}&amp;fieldname=subnetid">$comment->{subnetid_vis}</a>
 EOT
 		} else {
@@ -1984,7 +1988,7 @@
 
 	$time_to_display = timeCalc($comment->{date});
 	unless ($user->{noscores}) {
-		$score_to_display .= "(Score:";
+		$score_to_display .= " (Score:";
 		$score_to_display .= length($comment->{points}) ? $comment->{points} : "?";
 		if ($reasons && $comment->{reason}) {
 			$score_to_display .= ", $reasons->{$comment->{reason}}{name}";
@@ -1998,7 +2002,7 @@
 			cid	=> $comment->{cid},
 			subject	=> "#$comment->{cid}",
 			subject_only => 1,
-		}, 1);
+		}, 1, { noextra => 1 });
 		$comment_link_to_display = qq| ($link)|;
 	} else {
 		$comment_link_to_display = " ";
@@ -2165,9 +2169,9 @@
 	my $classattr = $discussion2 ? qq[ class="$class"] : '';
 
 	my $head = $discussion2 ? <<EOT1 : <<EOT2;
-			<h4><a id="comment_link_$comment->{cid}" name="comment_link_$comment->{cid}" href="$gSkin->{rootdir}/comments.pl?sid=$comment->{sid}&amp;cid=$comment->{cid}" onclick="return setFocusComment($comment->{cid})">$comment->{subject}</a></h4>
+			<h4><a id="comment_link_$comment->{cid}" name="comment_link_$comment->{cid}" href="$gSkin->{rootdir}/comments.pl?sid=$comment->{sid}&amp;cid=$comment->{cid}" onclick="return setFocusComment($comment->{cid})">$comment->{subject}</a>
 EOT1
-			<h4><a name="$comment->{cid}">$comment->{subject}</a></h4>
+			<h4><a name="$comment->{cid}">$comment->{subject}</a>
 EOT2
 
 	my $return = '';
@@ -2178,11 +2182,11 @@
 EOT
 
 	$return .= <<EOT if !$options->{noshow};
-	<div class="commentTop">
+	<div id="comment_top_$comment->{cid}" class="commentTop newcomment">
 		<div class="title">
 $head
 $comment_links
-		 	<span id="comment_score_$comment->{cid}" class="score">$score_to_display</span>
+		 	<span id="comment_score_$comment->{cid}" class="score">$score_to_display</span></h4>
 		</div>
 		<div class="details">
 			by $user_nick_to_display$zoosphere_display

Modified: slashjp/trunk/Slash/Utility/Display/Display.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Display/Display.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/Slash/Utility/Display/Display.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -1082,11 +1082,9 @@
 =cut
 
 sub linkComment {
-	my($linkdata, $printcomment, $date) = @_;
+	my($linkdata, $printcomment, $options) = @_;
 	my $constants = getCurrentStatic();
 	my $form = getCurrentForm();
-	return _hard_linkComment(@_) if $constants->{comments_hardcoded};
-
 	my $user = getCurrentUser();
 	my $adminflag = $user->{seclev} >= 10000 ? 1 : 0;
 
@@ -1096,17 +1094,21 @@
 		$linkdata->{$_} = undef unless exists $linkdata->{$_};
 	}
 
-	$linkdata->{pid} = $linkdata->{original_pid} || $linkdata->{pid};
+	$linkdata->{pid}     = $linkdata->{original_pid} || $linkdata->{pid};
+	$linkdata->{comment} = $printcomment;
 
-	slashDisplay('linkComment', {
-		%$linkdata, # defaults
-		adminflag	=> $adminflag,
-		date		=> $date,
-		threshold	=> defined($linkdata->{threshold}) ? $linkdata->{threshold} : $user->{threshold},
-		commentsort	=> $user->{commentsort},
-		mode		=> $user->{mode},
-		comment		=> $printcomment,
-	}, { Return => 1, Nocomm => 1 });
+	if (!$options->{noextra}) {
+		%$linkdata = (%$linkdata,
+			adminflag	=> $adminflag,
+			date		=> $options->{date},
+			threshold	=> defined($linkdata->{threshold}) ? $linkdata->{threshold} : $user->{threshold},
+			commentsort	=> $user->{commentsort},
+			mode		=> $user->{mode},
+		);
+	}
+
+	return _hard_linkComment($linkdata) if $constants->{comments_hardcoded};
+	slashDisplay('linkComment', $linkdata, { Return => 1, Nocomm => 1 });
 }
 
 #========================================================================
@@ -1315,7 +1317,7 @@
 ########################################################
 # this sucks, but it is here for now
 sub _hard_linkComment {
-	my($linkdata, $printcomment, $date) = @_;
+	my($linkdata) = @_;
 	my $user = getCurrentUser();
 	my $constants = getCurrentStatic();
 	my $form = getCurrentForm();
@@ -1324,16 +1326,16 @@
 	my $subject = $linkdata->{subject};
 
 	my $display = qq|<a href="$gSkin->{rootdir}/comments.pl?sid=$linkdata->{sid}|;
-	$display .= "&amp;op=$linkdata->{op}" if $linkdata->{op};
-	$display .= "&amp;threshold=" . (defined($linkdata->{threshold}) ? $linkdata->{threshold} : $user->{threshold});
-	$display .= "&amp;commentsort=$user->{commentsort}" if defined $user->{commentsort};
-	$display .= "&amp;mode=$user->{mode}" if defined $user->{mode};
+	$display .= "&amp;op=$linkdata->{op}" if defined($linkdata->{op});
+	$display .= "&amp;threshold=$linkdata->{threshold}" if defined($linkdata->{threshold});
+	$display .= "&amp;commentsort=$user->{commentsort}" if defined $linkdata->{commentsort};
+	$display .= "&amp;mode=$user->{mode}" if defined $linkdata->{mode};
 	$display .= "&amp;no_d2=1" if $user->{state}{no_d2} || $linkdata->{no_d2};
 	$display .= "&amp;startat=$linkdata->{startat}" if $linkdata->{startat};
 	$display .= "&amp;tid=$user->{state}{tid}"
 		if $constants->{tids_in_urls} && $user->{state}{tid};
 
-	if ($printcomment) {
+	if ($linkdata->{comment}) {
 		$display .= "&amp;cid=$linkdata->{cid}";
 	} else {
 		$display .= "&amp;pid=" . ($linkdata->{original_pid} || $linkdata->{pid});
@@ -1347,7 +1349,7 @@
 		$display .= qq| (Score:$linkdata->{points})|
 			if !$user->{noscores} && $linkdata->{points};
 		$display .= " " . timeCalc($linkdata->{date}) 
-			if $date;
+			if $linkdata->{date};
 	}
 	#$display .= "\n";
 

Modified: slashjp/trunk/Slash/Utility/Environment/Environment.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Environment/Environment.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/Slash/Utility/Environment/Environment.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -3200,7 +3200,7 @@
 quoted but rather inserted directly into an SQL request.  For example,
 if passed "123" (a user id), will return "CAST('123' AS UNSIGNED)"
 (same value, quoted);  if passed "200123456789abcd" (an encoded IP),
-will return "CAST(CONV('200123456789abcd', 16, 10) AS UNSIGNED" which
+will return "CAST(CONV('200123456789abcd', 16, 10) AS UNSIGNED)" which
 can be used as an assignment into or test against a BIGINT column.
 
 For speed, does not do error-checking against the value passed in.

Modified: slashjp/trunk/debian/changelog
===================================================================
--- slashjp/trunk/debian/changelog	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/debian/changelog	2007-10-31 05:54:43 UTC (rev 234)
@@ -1,3 +1,9 @@
+slash (2.5.0.181-0.1) unstable; urgency=low
+
+  * New upstream CVS release
+
+ -- Taku YASUI <tach****@osdn*****>  Wed, 31 Oct 2007 14:53:58 +0900
+
 slash (2.5.0.180-0.1) unstable; urgency=low
 
   * New upstream cvs release
@@ -18,7 +24,7 @@
   * Fix warning: Use of uninitialized value at
     getDescForTopicsRendered() at plugins/Admin/admin.pl
 
- -- Taku YASUI <tach****@osdn*****>  Fri, 26 Oct 2007 15:06:24 +0900
+ -- Taku YASUI <tach****@osdn*****>  Wed, 31 Oct 2007 14:53:53 +0900
 
 slash (2.5.0.119-17) unstable; urgency=low
 

Modified: slashjp/trunk/plugins/Admin/admin.pl
===================================================================
--- slashjp/trunk/plugins/Admin/admin.pl	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Admin/admin.pl	2007-10-31 05:54:43 UTC (rev 234)
@@ -1516,7 +1516,9 @@
 	}
 	my $pending_file_count = 0;
 	my $story_static_files = [];
-	if ($stoid) {
+	if ($stoid || $form->{sid}) {
+		my $story = $slashdb->getStory($form->{sid});
+		$stoid ||= $story->{stoid};
 		$pending_file_count = $slashdb->numPendingFilesForStory($stoid); 		$story_static_files = $slashdb->getStaticFilesForStory($stoid);
 	}
 	slashDisplay('editStory', {
@@ -1722,7 +1724,7 @@
 					[$val, $_]
 				} @story_nexuses;
 
-	my $remove = qq{[<a href="javascript:st_main_add_really(%d,'%s',0,1)" class="nex_remove">x</a>]};
+	my $remove = qq{[<a href="#" onclick="st_main_add_really(%d,'%s',0,1); return false" class="nex_remove">x</a>]};
 
 	my $desc;
 	if (!@sorted_nexuses) {
@@ -2116,28 +2118,53 @@
 	my($stoid) = @_;
 	my $form    = getCurrentForm();
 	my $slashdb = getCurrentDB();
+	my $constants = getCurrentStatic();
+
+	my $saveblob = $constants->{admin_use_blob_for_upload};
+	my $savefile = !$saveblob;
+
 	if ($form->{media_file}) {
 		my $upload = $form->{query_apache}->upload;
 		if ($upload) {
 			my $fh = $upload->fh;
 			use File::Path;
-			mkpath("/tmp/upload", 0, 0755) unless -e "/tmp/upload";
 			$form->{media_file} =~ s|^.*?([^/:\\]+)$|$1|;
 			my $name = $form->{media_file};
 			my $suffix;
 			($suffix) = $name =~ /(\.\w+)$/;
-			use File::Temp qw(:mktemp);
-			my ($ofh, $tmpname) = mkstemps("/tmp/upload/fileXXXXXX", $suffix );
+			my($ofh, $tmpname, $blobdata);
+			mkpath("/tmp/upload", 0, 0755) unless -e "/tmp/upload";
+
+			if ($savefile) {
+				use File::Temp qw(:mktemp);
+				($ofh, $tmpname) = mkstemps("/tmp/upload/fileXXXXXX", $suffix );
+			}
 				
 			while (<$fh>) {
-				print $ofh $_;
+				print $ofh $_ if $savefile;
+				$blobdata .= $_ if $saveblob;
 			}
-			close $ofh;
+			if ($savefile) {
+				close $ofh;
+			}
+			my $action = $form->{media_action} eq "thumbnails" ? "thumbnails" : "upload";
 			my $file = {
 				stoid	=> $stoid,
-				file	=> "$tmpname",
-				action 	=> "upload",
+				action 	=> $action,
 			};
+			if ($savefile) {
+				$file->{file} = "$tmpname";
+			}
+			if ($saveblob) {
+				my $data;
+				my $blob = getObject("Slash::Blob");
+				$file->{blobid} = $blob->create({
+						data 	=> $blobdata,
+						seclev 	=> 0,
+						filename => $name
+				});
+
+			}
 			$slashdb->addFileToQueue($file);
 		}
 	}

Modified: slashjp/trunk/plugins/Admin/templates/editStory;admin;default
===================================================================
--- slashjp/trunk/plugins/Admin/templates/editStory;admin;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Admin/templates/editStory;admin;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -248,7 +248,7 @@
 				<label>
 					Upload an image/audio file for this story [% IF pending_file_count %]([% pending_file_count %] awaiting processing)[% END %]
 				</label>
-				<input type="file" name="media_file">
+				<input type="file" name="media_file"><select name="media_action"><option value="upload">upload</option><option value="thumbnails">thumbnails</option></select>
 
 				[% IF story_static_files && story_static_files.size  %]
 					<label>
@@ -259,6 +259,8 @@
 					[% trunc_name = mfile.name %]
 					[% trunc_name = trunc_name.replace('^\d+',"") %]
 					<tr><td>[% mfile.sfid %]</td><td><a href="[% constants.imagedir %]/articles/[% sid %][% trunc_name %]" style="color:#fff">[% mfile.name %]</td><td>[% constants.imagedir %]/articles/[% sid %][% trunc_name %]</td>
+					<td>[% mfile.width %]</td>
+					<td>[% mfile.height %]</td>
 <td>
 [% IF mfile.filetype == "image" %]
 <img src="[% constants.imagedir %]/articles/[% sid %][% trunc_name %]" width="25%" height="25%">

Modified: slashjp/trunk/plugins/Admin/templates/static_files;admin;default
===================================================================
--- slashjp/trunk/plugins/Admin/templates/static_files;admin;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Admin/templates/static_files;admin;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -17,9 +17,9 @@
 [% FOREACH mfile = story_static_files %]
 	[% trunc_name = mfile.name %]
 	[% trunc_name = trunc_name.replace('^\d+',"") %]
-	<tr><td>[% mfile.sfid %]</td><td><a href="[% constants.imagedir %]/articles/[% sid %][% trunc_name %]">[% mfile.name %]</td><td>[% constants.imagedir %]/articles/[% sid %][% trunc_name %]</td></tr>
+	<tr><td>[% mfile.sfid %]</td><td><a href="[% constants.imagedir %]/articles/[% sid %][% trunc_name %]">[% mfile.name %]</td><td>[% constants.imagedir %]/articles/[% sid %][% trunc_name %]</td><td>[% mfile.width %]</td><td>[% mfile.height %]</td></tr>
 	[% IF mfile.filetype == "image" %]
-	<tr><td colspan="3"><img src="[% constants.imagedir %]/articles/[% sid %][% trunc_name %]"></td></tr>
+	<tr><td colspan="t"><img src="[% constants.imagedir %]/articles/[% sid %][% trunc_name %]"></td></tr>
 	[% END %]
 
 [% END %]

Modified: slashjp/trunk/plugins/Ajax/htdocs/ajax.pl
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/ajax.pl	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Ajax/htdocs/ajax.pl	2007-10-31 05:54:43 UTC (rev 234)
@@ -524,8 +524,10 @@
         my $user_edits_table = {
                 d2_comment_q     => $params{'d2_comment_q'}     || undef,
                 d2_comment_order => $params{'d2_comment_order'} || undef,
-                emaildisplay     => $params{'emaildisplay'}     || undef,
                 nosigs           => ($params{'nosigs'}          ? 1 : 0),
+                noscores          => ($params{'noscores'}            ? 1 : 0),
+                domaintags        => ($params{'domaintags'} != 2     ? $params{'domaintags'} : undef),
+                m2_with_comm_mod  => ($params{'m2_with_mod_on_comm'} ? 1 : undef),
         };
 
         $slashdb->setUser($params{uid}, $user_edits_table);

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/admin.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/admin.js	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/admin.js	2007-10-31 05:54:43 UTC (rev 234)
@@ -87,7 +87,7 @@
 	var tagshistid = "taghist-" + id;
 	var popupid    = "taghistory-" + id;
 	var title      = "History ";
-	var buttons    = createPopupButtons("<a href=\"#\">[?]</a></span><span><a href=\"javascript:closePopup('" + popupid + "-popup')\">[X]</a>");
+	var buttons    = createPopupButtons("<a href=\"#\" onclick=\"return false\">[?]</a></span><span><a href=\"#\" onclick=\"closePopup('" + popupid + "-popup'); return false\">[X]</a>");
 	title = title + buttons;
 	createPopup(getXYForId(tagshistid), title, popupid);
 	ajax_update(params, "taghistory-" + id + "-contents");
@@ -123,7 +123,7 @@
 	var params = [];
 	params['op'] = 'remarks_config';
 	var title = "Remarks Config ";
-	var buttons = createPopupButtons('<a href="javascript:closePopup(\'remarksconfig-popup\', 1)">[X]</a>');
+	var buttons = createPopupButtons('<a href="#" onclick="closePopup(\'remarksconfig-popup\', 1); return false">[X]</a>');
 	title = title + buttons;
 	createPopup(getXYForId('remarks_table'), title + buttons, 'remarksconfig');
 	ajax_update(params, 'remarksconfig-contents');

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/common.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/common.js	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/common.js	2007-10-31 05:54:43 UTC (rev 234)
@@ -1226,7 +1226,7 @@
 function vendorStoryPopup() {
 	id = vendor_popup_id;
 	var title = "<a href='//intel.vendors.slashdot.org' onclick=\"javascript:urchinTracker('/vendor_intel-popup/intel_popup_title');\">Intel's Opinion Center</a>";
-	var buttons = createPopupButtons("<a href=\"javascript:closePopup('vendorStory-" + id + "-popup')\">[X]</a>");
+	var buttons = createPopupButtons("<a href=\"#\" onclick=\"closePopup('vendorStory-" + id + "-popup')\">[X]</a>");
 	title = title + buttons;
 	var closepopup = function (e) {
 	if (!e) var e = window.event;
@@ -1251,7 +1251,7 @@
 function vendorStoryPopup2() {
 	id = vendor_popup_id;
 	var title = "<a href='//intel.vendors.slashdot.org' onclick=\"javascript:urchinTracker('/vendor_intel-popup/intel_popup_title');\">Intel's Opinion Center</a>";
-	var buttons = createPopupButtons("<a href=\"javascript:closePopup('vendorStory-" + id + "-popup')\">[X]</a>");
+	var buttons = createPopupButtons("<a href=\"#\" onclick=\"closePopup('vendorStory-" + id + "-popup')\">[X]</a>");
 	title = title + buttons;
 	var closepopup = function (e) {
 		if (!e) var e = window.event;

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js	2007-10-31 05:54:43 UTC (rev 234)
@@ -1,8 +1,8 @@
 // $Id$
 
 function configSectionPopup() { 
-	var title = "<a href=\"javascript:window.location.reload()\" style=\"color:#fff;\">Sectional&nbsp;Display&nbsp;Prefs</a>&nbsp;";
-	var buttons = createPopupButtons("<a href=\"/faq/UI.shtml#ui500\">[?]</a>","<a href=\"javascript:window.location.reload()\">[X]</a>");
+	var title = "<a href=\"#\" onclick=\"window.location.reload()\" style=\"color:#fff;\">Sectional&nbsp;Display&nbsp;Prefs</a>&nbsp;";
+	var buttons = createPopupButtons("<a href=\"/faq/UI.shtml#ui500\">[?]</a>","<a href=\"#\" onclick=\"window.location.reload()\">[X]</a>");
 	title = title + buttons;
 	createPopup(getXYForId('links-sections-title'), title, "sectionprefs", "", "Loading...");
 	

Modified: slashjp/trunk/plugins/Ajax/templates/data;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/data;ajax;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Ajax/templates/data;ajax;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -16,5 +16,5 @@
 [% SWITCH value %]
 	
 [% CASE 'set_section_prefs_success_msg' %]
-	<a href="javascript:window.location.reload();" style="color:#fff;">Close</a>
+	<a href="#" onclick="window.location.reload(); return false" style="color:#fff;">Close</a>
 [% END %]

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -20,6 +20,8 @@
 <table width="100%">
 	<tr>
 	<td valign="middle">
+                &nbsp;<p>
+
 		[% IF user.discussion2 && user.discussion2 == "slashdot" %]
                 	<blockquote>
 			<div>
@@ -36,31 +38,6 @@
 			</blockquote>
                 [% END %]
 
-                <p><b>Email Display</b>
-                (currently
-                [%- IF !user.fakeemail; " not displayed";
-                ELSE; ": <tt>"; user.fakeemail | strip_literal; "</tt>";
-                END %])<br>
-                [% IF !user.emaildisplay.defined;
-                        IF user.fakeemail %]
-                        <i>(Your current email address was apparently set before
-                        users' email addresses were forced to one of the below
-                        choices. Please pick one and click Save.)</i><br>
-                        [% END;
-                        user.emaildisplay = 0;
-                END;
-                IF user.emaildisplay.defined;
-                        emaildisplay.${user.emaildisplay} = constants.markup_checked_attribute;
-                END %]
-                <blockquote>
-		<div>
-                <input type="radio" name="emaildisplay" [% emaildisplay.0 %] value=0> Do not display an e-mail address.<br>
-                <input type="radio" name="emaildisplay" [% emaildisplay.1 %] value=1> Show your email address with random SPAM-armoring applied.<br>
-                [% PROCESS formNote note='This changes weekly' %]
-                <input type="radio" name="emaildisplay" [% emaildisplay.2 %] value=2> Show your real email address without cowering behind childish anonymity or obfuscation.
-                </div>
-		</blockquote>
-
 		[% s_check = '';
 		IF user.nosigs;
 			s_check = constants.markup_checked_attribute;
@@ -68,6 +45,37 @@
 
 		<label><input type="checkbox" name="nosigs"[% s_check %]>&nbsp;Disable Sigs</label>
                 [% PROCESS formNote note='Strip sig quotes from comments' %]
+
+                <p>
+
+                [% n_check = '';
+                IF user.noscores;
+                        n_check = constants.markup_checked_attribute;
+                END %]
+                <label><input type="checkbox" name="noscores"[% n_check %]>&nbsp;Do Not Display Scores</label>
+                [% PROCESS formNote note="Hides score: They still <b>apply</b> you just don't see them." %]
+
+                &nbsp;<p>
+
+                [% UNLESS user.domaintags.defined; user.domaintags = 2; END %]
+                [% domaintags.${user.domaintags} = constants.markup_checked_attribute -%]
+
+                <b>Display Link Domains?</b> (shows the actual domain of any link in brackets)<br>
+                <blockquote><div>
+                <input type="radio" name="domaintags" [% domaintags.0 %] value=0> Never show link domains<br>
+                <input type="radio" name="domaintags" [% domaintags.1 %] value=1> Show the links domain only in recommended situations<br>
+                <input type="radio" name="domaintags" [% domaintags.2 %] value=2> Always show link domains
+                </div></blockquote>
+
+                <p>
+
+                [% IF user.is_admin && constants.m2 %]
+                        [% s_m2c_check = '';
+                        IF user.m2_with_comm_mod;
+                                s_m2c_check = constants.markup_checked_attribute;
+                        END %]
+                <label><input type="checkbox" name="m2_with_mod_on_comm" [% s_m2c_check %]>&nbsp;Show Metamoderation in Comment Moderation Listing</label>
+                [% END %]
 	</td>
 	</tr>
 </table>

Modified: slashjp/trunk/plugins/Blob/Blob.pm
===================================================================
--- slashjp/trunk/plugins/Blob/Blob.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Blob/Blob.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -182,6 +182,12 @@
 	return $self->sqlDelete($self->{_table}, "reference_count < 1");
 }
 
+sub get {
+	my($self, $sig) = @_;
+	my $sig_q = $self->sqlQuote($sig);
+	return $self->sqlSelectHashref($self->{_table}, "id = $sig_q");
+}
+
 sub getFilesForStories {
 	my($self) = @_;
 	$self->sqlSelectAllHashrefArray('*', 'story_files', '', "ORDER BY stoid,description");

Modified: slashjp/trunk/plugins/Bookmark/templates/bookmarklink;misc;default
===================================================================
--- slashjp/trunk/plugins/Bookmark/templates/bookmarklink;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Bookmark/templates/bookmarklink;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -14,9 +14,9 @@
 10000
 __template__
 [% IF user.state.ssl %]
-	<a href="javascript:location.href='[% constants.absolutedir_secure %]/bookmark.pl?url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title)">[% title || "Post to $constants.sitename" %]</a>
+	<a href="#" onclick="location.href='[% constants.absolutedir_secure %]/bookmark.pl?url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title); return false">[% title || "Post to $constants.sitename" %]</a>
 [% ELSE %]
-	<a href="javascript:location.href='[% constants.absolutedir %]/bookmark.pl?url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title)">[% title || "Post to $constants.sitename" %]</a>
+	<a href="#" onclick="location.href='[% constants.absolutedir %]/bookmark.pl?url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title); return false">[% title || "Post to $constants.sitename" %]</a>
 [% END %]
 __version__
 $Id$

Modified: slashjp/trunk/plugins/Bookmark/templates/bookmarktext;misc;default
===================================================================
--- slashjp/trunk/plugins/Bookmark/templates/bookmarktext;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Bookmark/templates/bookmarktext;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -24,9 +24,9 @@
 <br>
 <p>		               
 <xmp><!-- Start [% constants.sitename %] It link -->
-<a href="javascript:location.href='[% constants.absolutedir %]/bookmark.pl?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)">
+<a href="#" onclick="location.href='[% constants.absolutedir %]/bookmark.pl?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title); return false">
 <img src="[% constants.absolutedir %]/favicon.ico" alt="[% constants.sitename %]" border="0" height="16" width="16"></a> &nbsp;
-<a href="javascript:location.href='[% constants.absolutedir %]/bookmark.pl?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)">[% constants.sitename %] It!
+<a href="#" onclick="location.href='[% constants.absolutedir %]/bookmark.pl?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title); return false">[% constants.sitename %] It!
 <!-- End [% constants.sitename %] It link -->
 </xmp></p>
 <br>

Modified: slashjp/trunk/plugins/Console/templates/display;console;default
===================================================================
--- slashjp/trunk/plugins/Console/templates/display;console;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Console/templates/display;console;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -34,7 +34,7 @@
 		[% firehosebox %]
 		</div>
 	[% ELSE %]
-	<a href="javascript:reloadBin()">Reload Bin</a>
+	<a href="#" onclick="reloadBin(); return false">Reload Bin</a>
 	<br>
 	<iframe name="submitframe" id="submitiframe" src="[% gSkin.rootdir %]/submit.pl?op=list&amp;nowrapper=1&amp;fromconsole=1" width="100%" height="800"></iframe>
 	[% END %]

Modified: slashjp/trunk/plugins/FAQSlashdot/faq/UI.shtml
===================================================================
--- slashjp/trunk/plugins/FAQSlashdot/faq/UI.shtml	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FAQSlashdot/faq/UI.shtml	2007-10-31 05:54:43 UTC (rev 234)
@@ -19,13 +19,13 @@
         <p>The policy for Slashboxes is as follows:</p>
         <ol>
                 <li>The remote site gives us permission.</li>
-                <li>The remote site provides an RDF file for us to parse (here is <a href="/slashdot.rdf">our rdf</a> if you want an example).</li>
+                <li>The remote site provides an RSS feed URL.</li>
                 <li>We decide that it belongs on Slashdot.</li>
         </ol>
-        <p>Currently the grand Slashbox poobah is <a href="mailto:pater****@slash*****">CowboyNeal</a>. Email him a URL to the RDF, as well as a technical contact, and we'll consider your addition to the roster.</p>
+        <p>Currently the Slashbox contact address is <a href="mailto:help****@slash*****"></a>. Email us your feed URL, as well as a technical contact, and we'll consider your addition to the roster.</p>
         <p><em><small>
                 Answered by: <a href="mailto:malda****@slash*****">CmdrTaco</a><br>
-                Last Modified: 6/14/00
+                Last Modified: 10/23/2007
         </small></em></p>
 
 <h2><a name="ui200" id="ui200">What is this little [?] I see in stories?</a></h2>

Modified: slashjp/trunk/plugins/FireHose/FireHose.pm
===================================================================
--- slashjp/trunk/plugins/FireHose/FireHose.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FireHose/FireHose.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -53,6 +53,7 @@
 	$data->{editorpop} ||= 0;
 	$data->{body_length} = $data->{bodytext} ? length($data->{bodytext}) : 0;
 	$data->{word_count} = countWords($data->{introtext}) + countWords($data->{bodytext});
+	$data->{mediatype} ||= "none";
 
 	my $text_data = {};
 	$text_data->{title} = delete $data->{title};
@@ -265,6 +266,7 @@
 			email			=> $submission->{email},
 			emaildomain		=> $submission->{emaildomain},
 			name			=> $submission->{name},
+			mediatype		=> $submission->{mediatype}
 		};
 		$data->{url_id} = $submission->{url_id} if $submission->{url_id};
 		my $firehose_id = $self->createFireHose($data);
@@ -1805,7 +1807,8 @@
 			$mode = "full";
 		}
 	}
-	
+
+	# number of firehose items per page in the normal case
 	if ($mode eq "full") {
 		if ($user->{is_admin}) {
 			$options->{limit} = $pagesize eq "large" ? 50 : 25;
@@ -1820,25 +1823,23 @@
 		}
 	}
 
-	if ($constants->{smalldevices_ua_regex}) {
+	# the non-normal cases: a small device (e.g., iPhone) or an embedded use (e.g., Google Gadget)
+	my $force_smaller = $form->{embed};
+	if (!$force_smaller && $constants->{smalldevices_ua_regex}) {
 		my $smalldev_re = qr($constants->{smalldevices_ua_regex});
 		if ($ENV{HTTP_USER_AGENT} && $ENV{HTTP_USER_AGENT} =~ $smalldev_re) {
-			$options->{smalldevices} = 1;
-			if ($mode eq "full") {
-				$options->{limit} = $pagesize eq "large" ? 15 : 10;
-			} else {
-				$options->{limit} = $pagesize eq "large" ? 20 : 15;
-			}
+			$force_smaller = 1;
 		}
 	}
 
-	if ($form->{gadget}) {
-			$options->{smalldevices} = 1;
-			if ($mode eq "full") {
-				$options->{limit} = $pagesize eq "large" ? 15 : 10;
-			} else {
-				$options->{limit} = $pagesize eq "large" ? 20 : 15;
-			}
+	# ...for which we'll have fewer items per page
+	if ($force_smaller) {
+		$options->{smalldevices} = 1;
+		if ($mode eq "full") {
+			$options->{limit} = $pagesize eq "large" ? 15 : 10;
+		} else {
+			$options->{limit} = $pagesize eq "large" ? 20 : 15;
+		}
 	}
 
 	if ($user->{is_admin} && $form->{setusermode}) {
@@ -2064,7 +2065,7 @@
 		}
 	}
 
-	if ($form->{gadget}) {
+	if ($form->{embed}) {
 		$#{@$user_tags_top} = 2;
 	}
 

Modified: slashjp/trunk/plugins/FireHose/firehose.css
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose.css	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FireHose/firehose.css	2007-10-31 05:54:43 UTC (rev 234)
@@ -447,3 +447,4 @@
 .briefarticle .storylinks .comments a:hover {background:transparent url('//images.slashdot.org/sic_icons.png') no-repeat scroll 0px -1498px; color: #fff !important}
 .briefarticle .storylinks .comments.nocomment, .briefarticle .storylinks .comments span  {display: none}
 
+.embed .paginate, .embed .firemenu, .embed + .copyright { display: none; }

Modified: slashjp/trunk/plugins/FireHose/mysql_schema.sql
===================================================================
--- slashjp/trunk/plugins/FireHose/mysql_schema.sql	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FireHose/mysql_schema.sql	2007-10-31 05:54:43 UTC (rev 234)
@@ -35,6 +35,7 @@
 	body_length MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL,
 	word_count MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL,
 	srcname VARCHAR(32) NOT NULL DEFAULT '',
+	mediatype enum("text", "none", "video", "image", "audio") default "none" NOT NULL,
 	PRIMARY KEY (id),
 	UNIQUE globjid (globjid),
 	KEY createtime (createtime),

Modified: slashjp/trunk/plugins/FireHose/templates/data;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/data;firehose;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FireHose/templates/data;firehose;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -89,7 +89,7 @@
 		[% IF user.state.firehose_page == "user" %]
 			This user's Firehose page contains no [% IF form.page %]additional [% END %]entries;
 		[% ELSE %]
-			No matches were found.  You may want to try [% IF new_color %]<a href="?[% IF form.gadget %]gadget=1&amp;[% END %]color=[% new_color | strip_paramattr %]">[% END %]lowering your color threshold[% IF new_color %] to [% new_color %][% END %][% IF new_color %]</a>[% END %]  or [% IF options.duration != -1 %]<a href="?[% IF form.gadget %]gadget=1&amp;[% END %]startdate=&amp;duration=-1">[% END %]expanding your time window[% IF options.duration != -1 %]</a>[% END %]
+			No matches were found.  You may want to try [% IF new_color %]<a href="?[% IF form.embed %]embed=1&amp;[% END %]color=[% new_color | strip_paramattr %]">[% END %]lowering your color threshold[% IF new_color %] to [% new_color %][% END %][% IF new_color %]</a>[% END %]  or [% IF options.duration != -1 %]<a href="?[% IF form.embed %]embed=1&amp;[% END %]startdate=&amp;duration=-1">[% END %]expanding your time window[% IF options.duration != -1 %]</a>[% END %]
 		[% END %]
 		</b>
 		<br><br>

Modified: slashjp/trunk/plugins/FireHose/templates/firehose_options;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/firehose_options;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FireHose/templates/firehose_options;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -25,8 +25,8 @@
 		paused = user.firehose_pause;
 	END;
 %]
-	<span id="play"[% IF !paused %] class="hide"[% END %]><a href="javascript:firehose_play()" title="Currently paused">Play</a></span>
-	<span id="pause" [% IF paused %] class="hide"[% END %]><a href="javascript:firehose_pause()" title="Currently playing">Pause</a></span>
+	<span id="play"[% IF !paused %] class="hide"[% END %]><a href="#" onclick="firehose_play(); return false" title="Currently paused">Play</a></span>
+	<span id="pause" [% IF paused %] class="hide"[% END %]><a href="#" onclick="firehose_pause(); return false" title="Currently playing">Pause</a></span>
 
 	[% IF options.orderby == "popularity" || options.orderby == "editorpop" || options.orderby == "popularity2" %]
 	<span id="popularity"><a href="[% gSkin.rootdir %]/firehose.pl?orderby=createtime" title="Toggle sort popularity/time - Currently popularity" onclick="firehose_set_options('orderby','createtime'); return false;">Popularity</a></span>

Modified: slashjp/trunk/plugins/FireHose/templates/list;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/list;firehose;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FireHose/templates/list;firehose;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -47,7 +47,7 @@
 
 <div id="slashboxes">
 [% UNLESS user.noboxes %]
-  [% IF slashboxes && !(form.smalldevices || form.gadget || (constants.smalldevices_ua_regex && ua.match(constants.smalldevices_ua_regex)));
+  [% IF slashboxes && !(form.smalldevices || form.embed || (constants.smalldevices_ua_regex && ua.match(constants.smalldevices_ua_regex)));
     slashboxes %]
   [% END %]
 [% END %]

Modified: slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivadmin;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivadmin;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivadmin;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -17,7 +17,7 @@
 
 [% PROCESS ajax_reskey_tag reskey_label => 'admin_commands-reskey-' _ id, reskey_name => 'ajax_admin' %]
 <input type="text" id="tags_admin_commands-[% id %]" name="tags_admin_commands-[% id %]" value="" size=50 maxlength=60 onkeyup="handleEnter(event, adminTagsCommands, '[% id %]','firehose')">
-<input type="button" value="Admin" onclick="adminTagsCommands('[% id %]','firehose')" class="button"> <span id="taghist-[% id %]"><a href="javascript:tagsHistory('[% id %]','firehose')">[History]</a></span>
+<input type="button" value="Admin" onclick="adminTagsCommands('[% id %]','firehose')" class="button"> <span id="taghist-[% id %]"><a href="#" onclick="tagsHistory('[% id %]','firehose'); return false">[History]</a></span>
 
 <div>[% tags_admin_str %]</div>
 

Modified: slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivtagbox;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivtagbox;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivtagbox;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -17,22 +17,22 @@
 <div id="tagbox-[% id %]" class="tags">
 [% IF !form.skipvote && !options.nothumbs %]
 	<span id="updown-[% item.id %]" class="vote[% IF vote == "down" %]ddown[% ELSIF vote == "up" %]dup[% END %]">
-	  <a href="javascript:firehose_up_down('[% item.id %]','+')" class="up" title="Vote this item up"
+	  <a href="#" onclick="firehose_up_down('[% item.id %]','+'); return false" class="up" title="Vote this item up"
 	     [% IF !user.is_anon %]onMouseDown="show_nod_menu(this, '[% item.id %]')" onMouseOver="show_nod_menu(this, '[% item.id %]', 1200, 5200)" onMouseOut="dont_show_nodnix_menu()"[% END %]>+</a>
-	  <a href="javascript:firehose_up_down('[% item.id %]','-')" class="down" title="Vote this item down"
+	  <a href="#" onclick="firehose_up_down('[% item.id %]','-'); return false" class="down" title="Vote this item down"
 	     [% IF !user.is_anon %]onMouseDown="show_nix_menu(this, '[% item.id %]')" onMouseOver="show_nix_menu(this, '[% item.id %]', 1200, 5200)" onMouseOut="dont_show_nodnix_menu()"[% END %]>-</a>
 	</span>  
 [% END %]
 	<div id="tagbox-title-[% id %]" class="tagtitleclosed">
-		&nbsp;[% IF user.tags_canwrite_stories %]<a href="javascript:tagsToggleStoryDiv('[% id %]','[% user.is_admin && !user.firehose_usermode %]','firehose');">[% ELSIF user.is_anon %]<a href="javascript:show_login_box()">[% ELSE %]<a href="[% gSkin.rootdir %]/subscribe.pl">[% END %]<span class="tagsheader" id="toggletags-button-[% id %]">[+]</span></a>
+		&nbsp;[% IF user.tags_canwrite_stories %]<a href="#" onclick="tagsToggleStoryDiv('[% id %]','[% user.is_admin && !user.firehose_usermode %]','firehose'); return false">[% ELSIF user.is_anon %]<a href="#" onclick="show_login_box(); return false">[% ELSE %]<a href="[% gSkin.rootdir %]/subscribe.pl">[% END %]<span class="tagsheader" id="toggletags-button-[% id %]">[+]</span></a>
 		<span id="tags-top-[% id %]">
 			[% PROCESS firehose_tags_top id = id tags_top = tags_top item = item -%]
 		</span>
 		[%- IF user.tags_canwrite_stories && (user.firehose_usermode || !user.is_admin) %]
-			<span class="tagname"><span class="tagmenu">, <a onClick="clickCompleter(this,'[% id %]','[% user.is_admin && !user.firehose_usermode %]','firehose', 4, {action1:completer_setTag})">feedback</a></span></span>
+			<span class="tagname"><span class="tagmenu">, <a onClick="clickCompleter(this,'[% id %]','[% user.is_admin && !user.firehose_usermode %]','firehose', 4, {action1:completer_setTag}); return false">feedback</a></span></span>
 		[% END %]
 		[% IF user.is_admin && !user.firehose_usermode -%]
-			<i>(<span id="note-form-[% item.id %]" class="hide"><input type="text" id="note-input-[% item.id %]" value="[% item.note | strip_attribute %]" size="30" onkeyup="handleEnter(event, firehose_save_note, '[% id %]')"> <input type="button" value="note" onclick="firehose_save_note('[% item.id %]')"></span><a id="note-text-[% item.id %]" onclick="firehose_open_note('[% item.id %]')">[% IF !item.note  %]Note[% END %][% item.note | strip_literal %]</a>)</i>
+			<i>(<span id="note-form-[% item.id %]" class="hide"><input type="text" id="note-input-[% item.id %]" value="[% item.note | strip_attribute %]" size="30" onkeyup="handleEnter(event, firehose_save_note, '[% id %]')"> <input type="button" value="note" onclick="firehose_save_note('[% item.id %]')"></span><a id="note-text-[% item.id %]" href="#" onclick="firehose_open_note('[% item.id %]'); return false">[% IF !item.note  %]Note[% END %][% item.note | strip_literal %]</a>)</i>
 		[%- END -%]
 	</div>
 
@@ -49,7 +49,7 @@
 		<div id="tags-user-[% id %]" class="taguser"></div>
 	[% IF user.is_admin && !user.firehose_usermode %]
 		<div id="tags-admin-[% id %]" class="tagadmin"></div>
-		<div id="admin-extras-[% item.id %]" class="tagadminextra"><a href="javascript:firehose_get_admin_extras('[% item.id %]')">Get extras</a></div>
+		<div id="admin-extras-[% item.id %]" class="tagadminextra"><a href="#" onclick="firehose_get_admin_extras('[% item.id %]'); return false">Get extras</a></div>
 	[% END %]
 		<div id="toggletags-message-[% id %]" class="message"></div>
 	</div>

Modified: slashjp/trunk/plugins/Journal/Journal.pm
===================================================================
--- slashjp/trunk/plugins/Journal/Journal.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Journal/Journal.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -60,10 +60,14 @@
 	$self->sqlUpdate('journals', \%j1, "id=$id") if keys %j1;
 	$self->sqlUpdate('journals_text', \%j2, "id=$id") if $j2{article};
 	if ($constants->{plugin}{FireHose}) {
-		my $journal_item = $self->get($id);
-		my $firehose = getObject("Slash::FireHose");
-		if ($journal_item->{promotetype} eq "publicize" || $journal_item->{promotetype} eq "publish") {
-			$firehose->createUpdateItemFromJournal($id);
+		my $reskey = getObject('Slash::ResKey');
+		my $rkey = $reskey->key('submit', { nostate => 1 });
+		if ($rkey && $rkey->createuse) {
+			my $journal_item = $self->get($id);
+			my $firehose = getObject("Slash::FireHose");
+			if ($journal_item->{promotetype} eq "publicize" || $journal_item->{promotetype} eq "publish") {
+				$firehose->createUpdateItemFromJournal($id);
+			}
 		}
 	}
 }
@@ -209,11 +213,15 @@
 	my $slashdb = getCurrentDB();
 	$slashdb->setUser($uid, { journal_last_entry_date => $date });
 	if ($constants->{plugin}{FireHose}) {
-		my $firehose = getObject("Slash::FireHose");
-		my $journal = getObject("Slash::Journal");
-		my $j = $journal->get($id);
-		if ($j->{promotetype} eq "publicize" || $j->{promotetype} eq "publish") {
-			$firehose->createItemFromJournal($id);
+		my $reskey = getObject('Slash::ResKey');
+		my $rkey = $reskey->key('submit', { nostate => 1 });
+		if ($rkey && $rkey->createuse) {
+			my $firehose = getObject("Slash::FireHose");
+			my $journal = getObject("Slash::Journal");
+			my $j = $journal->get($id);
+			if ($j->{promotetype} eq "publicize" || $j->{promotetype} eq "publish") {
+				$firehose->createItemFromJournal($id);
+			}
 		}
 	}
 

Modified: slashjp/trunk/plugins/Messages/PLUGIN
===================================================================
--- slashjp/trunk/plugins/Messages/PLUGIN	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Messages/PLUGIN	2007-10-31 05:54:43 UTC (rev 234)
@@ -14,6 +14,7 @@
 template=templates/data;messages;default
 template=templates/display;messages;default
 template=templates/display_prefs;messages;default
+template=templates/edit;messages;default
 template=templates/emailsponsor;messages;default
 template=templates/footer;messages;default
 template=templates/html_invalid;misc;default

Modified: slashjp/trunk/plugins/Messages/messages.pl
===================================================================
--- slashjp/trunk/plugins/Messages/messages.pl	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Messages/messages.pl	2007-10-31 05:54:43 UTC (rev 234)
@@ -65,70 +65,8 @@
 sub edit_message {
 	my($messages, $constants, $user, $form, $error_message) = @_;
 
-	my $template = <<EOT;
-[% IF preview %]
-	[% PROCESS titlebar width="100%" title="Preview Message" %]
-	[% preview %]
-	<P>
-[% END %]
-	[% PROCESS titlebar width="100%" title="Send Message" %]
-
-<!-- error message -->
-[% IF error_message %][% error_message %][% END %]
-<!-- end error message -->
-
-<FORM ACTION="[% gSkin.rootdir %]/messages.pl" METHOD="POST">
-	<INPUT TYPE="HIDDEN" NAME="op" VALUE="send_message">
-[% IF form.formkey %]
-	<INPUT TYPE="HIDDEN" NAME="formkey" VALUE="[% form.formkey %]">
-[% END %]
-
-	<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
-	<TR><TD ALIGN="RIGHT">User: </TD>
-		<TD><INPUT TYPE="text" NAME="to_user" VALUE="[% form.to_user | strip_attribute %]" SIZE=50 MAXLENGTH=50></TD>
-	</TR>
-	<TR><TD ALIGN="RIGHT">Subject: </TD>
-		<TD><INPUT TYPE="text" NAME="postersubj" VALUE="[% form.postersubj | strip_attribute %]" SIZE=50 MAXLENGTH=50></TD>
-	</TR>
-	<TR>
-		<TD ALIGN="RIGHT" VALIGN="TOP">Comment</TD>
-		<TD><TEXTAREA WRAP="VIRTUAL" NAME="postercomment" ROWS="[% user.textarea_rows || constants.textarea_rows %]" COLS="[% user.textarea_cols || constants.textarea_cols %]">[% form.postercomment | strip_literal %]</TEXTAREA>
-		<BR>(Use the Preview Button! Check those URLs!
-		Don't forget the http://!)
-	</TD></TR>
-
-	<TR><TD> </TD><TD>
-
-		<INPUT TYPE="SUBMIT" NAME="which" VALUE="Submit">
-		<INPUT TYPE="SUBMIT" NAME="which" VALUE="Preview">
-	</TD></TR><TR>
-		<TD VALIGN="TOP" ALIGN="RIGHT">Allowed HTML: </TD><TD><FONT SIZE="1">
-			&lt;[% constants.approvedtags.join("&gt;			&lt;") %]&gt;
-		</FONT>
-	</TD></TR>
-</TABLE>
-
-</FORM>
-
-<B>Important Stuff:</B>
-	<LI>Please try to keep posts on topic.
-	<LI>Try to reply to other people's comments instead of starting new threads.
-	<LI>Read other people's messages before posting your own to avoid simply duplicating
-		what has already been said.
-	<LI>Use a clear subject that describes what your message is about.
-	<LI>Offtopic, Inflammatory, Inappropriate, Illegal, or Offensive comments might be
-		moderated. (You can read everything, even moderated posts, by adjusting your
-		threshold on the User Preferences Page)
-
-<P><FONT SIZE="2">Problems regarding accounts or comment posting should be sent to
-	<A HREF="mailto:[% constants.adminmail | strip_attribute %]">[% constants.siteadmin_name %]</A>.</FONT>
-
-
-EOT
-
 	header(getData('header')) or return;
-	# print edit screen
-	slashDisplay(\$template, {error_message => $error_message});
+	slashDisplay('edit', { error_message => $error_message });
 	footer();
 }
 

Modified: slashjp/trunk/plugins/Messages/templates/emailsponsor;messages;default
===================================================================
--- slashjp/trunk/plugins/Messages/templates/emailsponsor;messages;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Messages/templates/emailsponsor;messages;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -13,9 +13,6 @@
 __instructions__
 placeholder
 __template__
-Drink Slurm, in all four delectable varieties!  Slurm Classic,
-Royal Slurm, Super Slurm, and now New Slurm!
-Slurm: It's so delicious, you'll eat it until you explode!
 
 __seclev__
 500

Modified: slashjp/trunk/plugins/Remarks/Remarks.pm
===================================================================
--- slashjp/trunk/plugins/Remarks/Remarks.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Remarks/Remarks.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -180,7 +180,7 @@
 	}
 	$slashdb->setUser($user->{uid}, $data) if keys %$data;
 	# this should be in a template -- pudge
-	return "<a href=\"javascript:closePopup('remarksconfig-popup', 1)\">Close</a>";
+	return "<a href=\"#\" onclick=\"closePopup('remarksconfig-popup', 1)\">Close</a>";
 }
 
 1;

Modified: slashjp/trunk/plugins/Remarks/templates/display;remarks;default
===================================================================
--- slashjp/trunk/plugins/Remarks/templates/display;remarks;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Remarks/templates/display;remarks;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -27,7 +27,7 @@
 
 <table class="data" width="100%">
 	<tr class="data_head">
-		<th colspan="5">Remarks (Last Updated [% Slash.timeCalc(Slash.db.getTime, '%Y-%m-%d %H:%M:%S %Z', 0) %]) <a href="javascript:remarks_popup()">[Config]</a></th>
+		<th colspan="5">Remarks (Last Updated [% Slash.timeCalc(Slash.db.getTime, '%Y-%m-%d %H:%M:%S %Z', 0) %]) <a href="#" onclick="remarks_popup(); return false">[Config]</a></th>
 	</tr>
 [% i = 1; FOREACH remark = remarks_ref; i = i == 1 ? 2 : 1 %]
 	<tr class="data_hl[% i %]"> <!-- remark.id:[% remark.rid %] -->

Modified: slashjp/trunk/plugins/Submit/submit.pl
===================================================================
--- slashjp/trunk/plugins/Submit/submit.pl	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Submit/submit.pl	2007-10-31 05:54:43 UTC (rev 234)
@@ -628,7 +628,8 @@
 		story		=> $form->{story},
 		subj		=> $form->{subj},
 		tid		=> $form->{tid},
-		primaryskid	=> $form->{primaryskid}
+		primaryskid	=> $form->{primaryskid},
+		mediatype	=> $form->{mediatype},
 	};
 	$submission->{url_id} = $url_id if $url_id;
 

Modified: slashjp/trunk/plugins/Submit/templates/displayForm;submit;default
===================================================================
--- slashjp/trunk/plugins/Submit/templates/displayForm;submit;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Submit/templates/displayForm;submit;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -86,7 +86,7 @@
 			[% PROCESS formNote note => "Where users can contact you" %]
 			[% IF constants.plugin.FireHose %]
 				[% PROCESS formLabel value => "Url"  %]
-				<input type="text" name="url" value="[% form.url | strip_attribute %]" size="50">
+				<input type="text" name="url" value="[% form.url | strip_attribute %]" size="50"> Url type [% Slash.createSelect('mediiatype', Slash.db.getDescriptions('mediatypes'), { default => form.mediatype || "none" , return => 1 }) %]
 				[% PROCESS formNote note => "Main url of submission (optional but if provided must be unique) " %]
 			[% END %]
 			[% PROCESS formLabel value => "Subject"  %]

Modified: slashjp/trunk/plugins/Tags/Clout/Describe.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout/Describe.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/Clout/Describe.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -1,22 +1,30 @@
 package Slash::Clout::Describe;
 
+use strict;
+use warnings;
+use Slash::Utility;
+use base 'Slash::Clout';
+
 use vars qw($VERSION);
 
 ($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
 
-# Hard-coded constants should be in the vars table.
+sub init {
+	my($self) = @_;
+	$self->SUPER::init(@_);
+	# Hard-coded constants should be in the vars table.
+	# cumfrac is the cumulative fraction of how much weight is propagated
+	# for each matching tag.  E.g. if $cumfrac is 0.5, the first match may
+	# propagate up to 50% of the weight, the second another 25%, the
+	# third another 12.5% etc.
+	$self->{cumfrac} = 0.5;
+	$self->{debug_uids} = { };
+	$self->{debug} = 0;
+	1;
+}
 
-# cumfrac is the cumulative fraction of how much weight is propagated
-# for each matching tag.  E.g. if $cumfrac is 0.5, the first match may
-# propagate up to 50% of the weight, the second another 25%, the
-# third another 12.5% etc.
-
-my $cumfrac = 0.5;
-my $months_back = 4;
-my $clid = 1;
-
 sub getUserClout {
-	my($class, $user_stub) = @_;
+	my($self, $user_stub) = @_;
 	my $clout = $user_stub->{karma} >= -3
 		? log($user_stub->{karma}+10)
 		: 0;
@@ -31,15 +39,15 @@
 }
 
 sub get_nextgen {
-	my($class, $g) = @_;
-	my $reader = getObject('Slash::DB', { db_type => 'reader' });
+	my($self, $g) = @_;
+	my $tags_reader = getObject('Slash::Tags', { db_type => 'reader' });
 	# TODO:
 	# - opposite tags. presumably a separate call that joins
 	#   sourcetag to newtag via tagnames AS sourcetn and
 	#   tagnames AS newtn and (sourcetn.tagname=CONCAT('!', newtn.tagname)
 	#   OR newtn.tagname=CONCAT('!', sourcetn.tagname))
 	#   except that would be a double table scan I think, ugh
-	my $hr_ar = $reader->sqlSelectAllHashrefArray(
+	my $hr_ar = $tags_reader->sqlSelectAllHashrefArray(
 		"sourcetag.uid AS sourcetag_uid,
 		 UNIX_TIMESTAMP(newtag.created_at)-UNIX_TIMESTAMP(sourcetag.created_at)
 			AS timediff,
@@ -59,11 +67,12 @@
 		"sourcetag.inactivated IS NULL
 		 AND sourcetag.globjid=globjs.globjid
 		 AND sourcetag.uid=sourcetpc.uid
+		 AND sourcetpc.clid=$self->{clid}
 		 AND sourcetag.globjid=newtag.globjid
 		 AND sourcetag.tagnameid=newtag.tagnameid
-		 AND sourcetag.tagnameid NOT IN ($nodid, $nixid)
+		 AND sourcetag.tagnameid NOT IN ($self->{nodid}, $self->{nixid})
 		 AND sourcetag.tagid != newtag.tagid
-		 AND newtag.created_at >= DATE_SUB(NOW(), INTERVAL $months_back MONTH)
+		 AND newtag.created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)
 		 AND newtag.uid=users_info.uid
 		 AND newtpc.uid IS NULL
 		 AND sourcetpc.gen=$g",
@@ -72,38 +81,40 @@
 }
 
 sub process_nextgen {
-	my($class, $hr_ar) = @_;
+	my($self, $hr_ar, $tags_peerclout) = @_;
 	my %newtag_uid = ( map { $_->{newtag_uid}, 1 } @$hr_ar );
 	my @newtag_uid = sort { $a <=> $b } keys %newtag_uid;
 
-	my $insert_ar = [ ];
-	my $i = 0;
+	my $insert_ar = [ ]; my $i = 0;
 	for my $newtag_uid (@newtag_uid) {
 		my @match = grep { $_->{newtag_uid} == $newtag_uid } @$hr_ar;
 		my $match0 = $match[0];
 		my($clout, $created_at, $karma, $tokens) =
 			($match0->{clout}, $match0->{created_at_ut}, $match0->{karma}, $match0->{tokens});
-		if ($debug_uids->{$newtag_uid}) {
-			slashdLog("$class starting uid=%d", $newtag_uid);
+		if ($self->{debug_uids}{$newtag_uid}) {
+			print STDERR ref($self) . sprintf(" starting uid=%d\n", $newtag_uid);
+			++$self->{debug};
 		}
-		my $uid_mults = $class->get_mults(\@match);
-		my $weight = $class->get_total_weight($uid_mults, $clout, $created_at, $karma, $tokens);
+		my $uid_mults = $self->get_mults(\@match);
+		my $weight = $self->get_total_weight($tags_peerclout, $uid_mults, $clout, $created_at, $karma, $tokens);
 		push @$insert_ar, {
 			uid =>		$newtag_uid,
 			clout =>	$weight,
 		};
-		if ($debug_uids->{$newtag_uid}) {
-			$debug = 1;
-			my $umd = Dumper($uid_mults); $umd =~ s/\s+/ /g;
-			slashdLog("$class uid=$newtag_uid weight="
-				. $class->get_total_weight($uid_mults, $clout, $created_at, $karma, $tokens)
-				. " mults: $umd");
-			$debug = 0;
+		if ($self->{debug}) {
+			use Data::Dumper; my $umd = Dumper($uid_mults); $umd =~ s/\s+/ /g;
+			print STDERR ref($self) . " uid=$newtag_uid weight="
+				. $self->get_total_weight($tags_peerclout, $uid_mults, $clout, $created_at, $karma, $tokens)
+				. " mults: $umd\n";
 		}
 		++$i;
-		if ($i % 1000 == 0) {
-			slashdLog("$class process_nextgen processed $i (uid $newtag_uid, matched " . scalar(@match) . ")");
+		if ($i % 100 == 0) {
+			print STDERR ref($self) . " process_nextgen processed $i (uid $newtag_uid, matched " . scalar(@match) . ")\n";
 		}
+		if ($self->{debug_uids}{$newtag_uid}) {
+			print STDERR ref($self) . sprintf(" done uid=%d\n", $newtag_uid);
+			--$self->{debug};
+		}
 		Time::HiRes::sleep(0.01);
 	}
 
@@ -111,10 +122,10 @@
 }
 
 sub get_mults {
-	my($class, $match_ar) = @_;
+	my($self, $match_ar) = @_;
 	my $uid_mults = { };
 	for my $hr (@$match_ar) {
-		my $mult = $class->get_mult($hr);
+		my $mult = $self->get_mult($hr);
 		$uid_mults->{ $hr->{sourcetag_uid} } ||= [ ]; 
 		push @{$uid_mults->{ $hr->{sourcetag_uid} }}, $mult;
 	}
@@ -122,7 +133,7 @@
 }
 
 sub get_mult {
-	my($class, $hr) = @_;
+	my($self, $hr) = @_;
 	
 	my $mult = 1.0;
 	
@@ -154,7 +165,8 @@
 	}
 	
 	# Tagging different types gets different mults.
-	my $type = $globjtypes->{ $hr->{gtid} };
+	my $slashdb = getCurrentDB();
+	my $type = $slashdb->getGlobjTypes()->{ $hr->{gtid} };
 	if ($type eq 'stories') {
 		# full credit for matching tags on stories
 	} elsif ($type eq 'comments') {
@@ -169,13 +181,15 @@
 sub get_total_weight {
 		# uid_mults is a hashref where the key is the source uid and
 		# the value is an arrayref of mults from that uid
-	my($class, $uid_mults, $clout, $created_at, $karma, $tokens) = @_;
+	my($self, $tags_peerclout, $uid_mults, $clout, $created_at, $karma, $tokens) = @_;
 
 	return 0 if $clout == 0 || $tokens < -1000 || $karma < -10;
 		
 	my @total_mults = ( );
 	
 	# Start by sorting source uids by decreasing weight.
+my @nodef = grep { !defined $tags_peerclout->{$_} } keys %$uid_mults; $#nodef = 20 if $#nodef > 20; print STDERR "nodef: '@nodef', t_p:" . Dumper($tags_peerclout) if @nodef;
+#print STDERR "uid_mults: " . Dumper($uid_mults);
 	my @source_uids = sort { $tags_peerclout->{$b} <=> $tags_peerclout->{$a} } keys %$uid_mults;
 
 	# If all source uids have weight 0, we know the answer quickly.
@@ -190,20 +204,20 @@
 			
 	# Get the mult for each of those
 	for my $uid (@source_uids) {
-		my @balanced = $class->balance_weight_vectors(@{$uid_mults->{$uid}});
-		push @total_mults, $tags_peerclout->{$uid} * $class->sum_weight_vectors(@balanced);
-		if ($debug) {
-			my @tm2 = map { sprintf("%.5g", @_) } @total_mults;
-			slashdLog("$class source_uid=$uid ($tags_peerclout->{$uid}) total_mults='@tm2'");
+		my @balanced = $self->balance_weight_vectors(@{$uid_mults->{$uid}});
+		push @total_mults, $tags_peerclout->{$uid} * $self->sum_weight_vectors(@balanced);
+		if ($self->{debug}) {
+			my @tm2 = map { sprintf("%.5g", $_) } @total_mults;
+			print STDERR ref($self) . " source_uid=$uid ($tags_peerclout->{$uid}) total_mults='@tm2'\n";
 		}       
 	}       
 			
 	# Then (using the same decreasing-multipliers algorithm) get the
 	# total of all those mults.
-	my @balanced = $class->balance_weight_vectors(@total_mults);
-	my $total = $class->sum_weight_vectors(@balanced);
-	if ($debug) {   
-		slashdLog("$class total=$total");
+	my @balanced = $self->balance_weight_vectors(@total_mults);
+	my $total = $self->sum_weight_vectors(@balanced);
+	if ($self->{debug}) {   
+		print STDERR ref($self) . " total=$total\n";
 	}               
 			
 	# If this user was created recently, less weight for them.
@@ -245,11 +259,11 @@
 }
 
 sub balance_weight_vectors {
-	my $class = shift @_;
-	my @w = sort { abs($b) <=> abs($a) || $b > $a } @_;
+	my($self, @w) = @_;
+	@w = sort { abs($b) <=> abs($a) || $b > $a } @w;
 	my $w_pos_mag = 0; for my $w (@w) { $w_pos_mag += $w if $w > 0 };
 	my $w_neg_mag = 0; for my $w (@w) { $w_neg_mag -= $w if $w < 0 };
-	return @_ if !$w_pos_mag && !$w_neg_mag;
+	return @w if !$w_pos_mag && !$w_neg_mag;
 
 	my @ret;
 	# Swinging more than 60-40% one way or the other reduces the
@@ -263,57 +277,40 @@
 		@ret = map { $_ > 0 ? $_*$pos_reduc_factor : $_ } @_;
 	} else {
 		# No change.
-		@ret = @_;
+		@ret = @w;
 	}
-	if ($debug) {
+	if ($self->{debug}) {
 		my @w2 = map { sprintf("%5d", @_) } @w;   $#w2 = 4 if $#w2 > 4;
 		my @r2 = map { sprintf("%5d", @_) } @ret; $#r2 = 4 if $#r2 > 4;
-		slashdLog(sprintf("$class balance_weight_vectors pos=%.5g neg=%.5g from '%s' to '%s'",
-			$w_pos_mag, $w_neg_mag, join(' ', @w2), join(' ', @r2)));
+		print STDERR sprintf("%s balance_weight_vectors pos=%.5g neg=%.5g from '%s' to '%s'\n",
+			ref($self), $w_pos_mag, $w_neg_mag, join(' ', @w2), join(' ', @r2));
 	}
 	return @ret;
 }
 
 sub sum_weight_vectors {
-	my $class = shift @_;
-	my @w = sort { abs($b) <=> abs($a) || $b > $a } @_;
+	my($self, @v) = @_;
+	my @w = sort { abs($b) <=> abs($a) || $b > $a } @v;
 	$#w = 50 if $#w > 50; # beyond this point contributions are tiny
 	my $weight = 0;
 	my $cur_magnitude = 1;
 	for my $w (@w) {
-		$cur_magnitude *= $cumfrac;
+		$cur_magnitude *= $self->{cumfrac};
 		$weight += $cur_magnitude * $w;
 	}
 	$weight = 0 if $weight < 0;
-	if ($debug) {
-		slashdLog("sum_weight_vectors weight='$weight' w='@w'");
+	if ($self->{debug}) {
+		print STDERR ref($self) . " sum_weight_vectors weight='$weight' w='@w'\n";
 	}
 	return $weight;
 }
 
-sub insert_nextgen {
-	my($class, $g, $insert_ar) = @_;
-	my $slashdb = getCurrentDB();
-	# XXX Should turn off autocommit for this loop
-	for my $hr (@$insert_ar) {
-		$hr->{gen} = $g; 
-		$slashdb->sqlInsert('tags_peerclout', $hr);
-	}
-}       
-	
-sub update_tags_peerclout {
-	my($class, $insert_ar) = @_;
-	for my $hr (@$insert_ar) {
-		$tags_peerclout->{ $hr->{uid} } = $hr->{clout}; 
-	} 
-}               
-		
 sub copy_peerclout_sql {
-	my($class) = @_;
+	my($self) = @_;
 	my $slashdb = getCurrentDB();
 	$slashdb->sqlDo("SET AUTOCOMMIT=0");
-	$slashdb->sqlDo("UPDATE users_clout SET clout=NULL WHERE clid='$clid'");
-	$slashdb->sqlDo("INSERT INTO users_clout (clout_id, uid, clid, clout) SELECT NULL, uid, '$clid', clout FROM tags_peerclout WHERE clid='$clid'");
+	$slashdb->sqlDo("UPDATE users_clout SET clout=NULL WHERE clid='$self->{clid}'");
+	$slashdb->sqlDo("REPLACE INTO users_clout (clout_id, uid, clid, clout) SELECT NULL, uid, '$self->{clid}', clout FROM tags_peerclout WHERE clid='$self->{clid}'");
 	$slashdb->sqlDo("COMMIT");
 	$slashdb->sqlDo("SET AUTOCOMMIT=1");
 }                       

Modified: slashjp/trunk/plugins/Tags/Clout/Moderate.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout/Moderate.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/Clout/Moderate.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -1,13 +1,39 @@
 package Slash::Clout::Moderate;
 
+use strict;
+use warnings;
+use Slash::Utility;
+use base 'Slash::Clout';
+
 use vars qw($VERSION);
 
 ($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
 
+sub init {
+	1;
+}
+
 sub getUserClout {
 	my($class, $user_stub) = @_;
 	return 1;
 }
 
+sub get_nextgen {
+	return [ ];
+}
+
+sub process_nextgen {
+	return [ ];
+}
+
+sub insert_nextgen {
+}
+
+sub update_tags_peerclout {
+}
+
+sub copy_peerclout_sql {
+}
+
 1;
 

Modified: slashjp/trunk/plugins/Tags/Clout/Vote.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout/Vote.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/Clout/Vote.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -1,15 +1,30 @@
 package Slash::Clout::Vote;
 
+use strict;
+use warnings;
+use Slash::Utility;
+use base 'Slash::Clout';
+
 use vars qw($VERSION);
 
 ($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
 
-my $cumfrac = 0.45;
-my $months_back = 4;
-my $clid = 2;
+sub init {
+        my($self) = @_;
+        $self->SUPER::init(@_);
+        # Hard-coded constants should be in the vars table.
+        # cumfrac is the cumulative fraction of how much weight is propagated
+        # for each matching tag.  E.g. if $cumfrac is 0.5, the first match may
+        # propagate up to 50% of the weight, the second another 25%, the
+        # third another 12.5% etc.
+        $self->{cumfrac} = 0.45;
+	$self->{debug_uids} = { };
+	$self->{debug} = 0;
+	1;
+}
 
 sub getUserClout {
-	my($class, $user_stub) = @_;
+	my($self, $user_stub) = @_;
 	my $clout = $user_stub->{karma} >= -3
 		? log($user_stub->{karma}+10)/50
 		: 0;
@@ -23,12 +38,13 @@
 }
 
 sub get_nextgen {
-	my($class, $g) = @_;
+	my($self, $g) = @_;
 
 	# Populate the firehose_ogaspt table with the necessary data.
 	my $constants = getCurrentStatic();
 	my $subscribe_future_secs = $constants->{subscribe_future_secs};
 	my $slashdb = getCurrentDB();
+	my $globj_types = $slashdb->getGlobjTypes();
 	$slashdb->sqlDelete('firehose_ogaspt');
 	# First, the pub dates for submissions that made it into stories.
 	$slashdb->sqlDo("INSERT INTO firehose_ogaspt
@@ -37,9 +53,9 @@
 			WHERE stories.stoid=story_param.stoid
 				AND in_trash='no'
 				AND story_param.name='subid'
-				AND globjs.gtid='$globjtypes->{submissions}'
+				AND globjs.gtid='$globj_types->{submissions}'
 				AND story_param.value=globjs.target_id
-				AND stories.time >= DATE_SUB(NOW(), INTERVAL $months_back MONTH)
+				AND stories.time >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)
 			GROUP BY globjid");
 	# Then, the same for journal entries that made it into stories.
 	$slashdb->sqlDo("INSERT INTO firehose_ogaspt
@@ -48,9 +64,9 @@
 			WHERE stories.stoid=story_param.stoid
 				AND in_trash='no'
 				AND story_param.name='journal_id'
-				AND globjs.gtid='$globjtypes->{journals}'
+				AND globjs.gtid='$globj_types->{journals}'
 				AND story_param.value=globjs.target_id
-				AND stories.time >= DATE_SUB(NOW(), INTERVAL $months_back MONTH)
+				AND stories.time >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)
 			GROUP BY globjid");
 	# Those queries run in under a second each.  But, wait a decent
 	# amount of time for them to replicate.
@@ -93,16 +109,20 @@
 			 AND tagnames_similar.dest_tnid=newtag.tagnameid
 		 AND simil != 0
 		 AND sourcetag.tagid != newtag.tagid
-		 AND newtag.created_at >= DATE_SUB(NOW(), INTERVAL $months_back MONTH)
+		 AND newtag.created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)
 		 AND newtag.uid=users_info.uid
 		 AND newtpc.uid IS NULL
-		 AND sourcetpc.gen=$g",
+		 AND sourcetpc.gen=$g
+		 AND sourcetpc.clid=$self->{clid}",
 		"ORDER BY newtag.tagid");
 	return $hr_ar;
 }
 
 sub process_nextgen {
-	my($class, $hr_ar) = @_;
+	my($self, $hr_ar, $tags_peerclout) = @_;
+
+	$self->count_uid_nodnix($hr_ar);
+
 	my %newtag_uid = ( map { $_->{newtag_uid}, 1 } @$hr_ar );
 	my @newtag_uid = sort { $a <=> $b } keys %newtag_uid;
 	my $user_nodnixes_min = 3;
@@ -111,45 +131,49 @@
 	my $insert_ar = [ ];
 	my $i = 0;
 	for my $newtag_uid (@newtag_uid) {
-		my $user_nodnixes_count = $nodc->{$newtag_uid} + $nixc->{$newtag_uid};
+		++$self->{debug} if $self->{debug_uids}{$newtag_uid};
+		my $user_nodnixes_count = ($self->{nodc}{$newtag_uid} || 0) + ($self->{nixc}{$newtag_uid} || 0);
 		my $user_nodnixes_mult = 0;
 		if ($user_nodnixes_count >= $user_nodnixes_full) {
 			$user_nodnixes_mult = 1;
 		} elsif ($user_nodnixes_count >= $user_nodnixes_min) {
-			$user_nodnixes_mult = ($user_nodnixes_count+1-$user_nodnixes_min)
-				/ ($user_nodnixes_full+1-$user_nodnixes_min);
+			$user_nodnixes_mult = ($user_nodnixes_count+1-$user_nodnixes_min) /
+				($user_nodnixes_full+1-$user_nodnixes_min);
 		}
 		my $weight = 0;
 		my(@match, $clout, $created_at, $karma, $tokens, $uid_mults);
-		if ($debug_uids->{$newtag_uid}) {
-			slashdLog("$class starting uid=%d user_nodnixes_mult=%.3f", $newtag_uid, $user_nodnixes_mult);
+		if ($self->{debug}) {
+			print STDERR ref($self) . sprintf(" starting uid=%d user_nodnixes_mult=%.3f\n",
+				$newtag_uid, $user_nodnixes_mult);
 		}
 		if ($user_nodnixes_mult > 0) {
 			@match = grep { $_->{newtag_uid} == $newtag_uid } @$hr_ar;
 			my $match0 = $match[0];
 			($clout, $created_at, $karma, $tokens) =
 				($match0->{clout}, $match0->{created_at_ut}, $match0->{karma}, $match0->{tokens});
-			$uid_mults = $class->get_mults(\@match);
-			$uid_mults->{'-1'} = $class->get_mult_timebeforepub(\@match);
-			$weight = $class->get_total_weight($uid_mults, $clout, $created_at, $karma, $tokens)
+			$uid_mults = $self->get_mults(\@match);
+			$uid_mults->{'-1'} = $self->get_mult_timebeforepub(\@match);
+			$weight = $self->get_total_weight($tags_peerclout, $uid_mults,
+				$clout, $created_at, $karma, $tokens, $newtag_uid)
 				* $user_nodnixes_mult;
 		}
 		push @$insert_ar, {
 			uid =>		$newtag_uid,
 			clout =>	$weight,
 		};
-		if ($debug_uids->{$newtag_uid}) {
-			$debug = 1;
-			slashdLog(sprintf("$class uid=%d user_nodnixes_mult=%.3f weight=%.6f mults: %s",
+		if ($self->{debug}) {
+			use Data::Dumper;
+			print STDERR sprintf("%s uid=%d user_nodnixes_mult=%.3f weight=%.6f mults: %s\n",
+				ref($self),
 				$newtag_uid, $user_nodnixes_mult,
-				$class->get_total_weight($uid_mults, $clout, $created_at, $karma, $tokens),
-				Dumper($uid_mults)));
-			$debug = 0;
+				$weight,
+				Dumper($uid_mults));
 		}
 		++$i;
-		if ($i % 1000 == 0) {
-			slashdLog("$class process_nextgen processed $i (uid $newtag_uid, matched " . scalar(@match) . ")");
+		if ($i % 100 == 0) {
+			print STDERR scalar(localtime) . " " . ref($self) . " process_nextgen processed $i (uid $newtag_uid, matched " . scalar(@match) . ")\n";
 		}
+		--$self->{debug} if $self->{debug_uids}{$newtag_uid};
 		Time::HiRes::sleep(0.01);
 	}
 
@@ -157,13 +181,14 @@
 }
 
 sub count_uid_nodnix {
-	my($class, $hr_ar) = @_;
+	my($self, $hr_ar) = @_;
+	$self->{nodc} = $self->{nixc} = { };
 	my %uid_needed = ( );
 	for my $hr (@$hr_ar) {
 		my $uid = $hr->{sourcetag_uid};
-		$uid_needed{$uid} = 1 if !exists $nodc->{$uid};
+		$uid_needed{$uid} = 1 if !exists $self->{nodc}{$uid};
 		$uid = $hr->{newtag_uid};
-		$uid_needed{$uid} = 1 if !exists $nodc->{$uid};
+		$uid_needed{$uid} = 1 if !exists $self->{nodc}{$uid};
 	}
 	return unless keys %uid_needed;
 	my $reader = getObject('Slash::DB', { db_type => 'reader' });
@@ -175,29 +200,29 @@
 		my $nod_hr = $reader->sqlSelectAllKeyValue(
 			'uid, COUNT(*)',
 			'tags',
-			"tagnameid='$tagnameid->{nod}' AND uid IN ($uid_str)
-			 AND created_at >= DATE_SUB(NOW(), INTERVAL $months_back MONTH)",
+			"tagnameid='$self->{nodid}' AND uid IN ($uid_str)
+			 AND created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)",
 			'GROUP BY uid');
 		my $nix_hr = $reader->sqlSelectAllKeyValue(
 			'uid, COUNT(*)',
 			'tags',
-			"tagnameid='$tagnameid->{nix}' AND uid IN ($uid_str)
-			 AND created_at >= DATE_SUB(NOW(), INTERVAL $months_back MONTH)",
+			"tagnameid='$self->{nixid}' AND uid IN ($uid_str)
+			 AND created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)",
 			'GROUP BY uid');
 		for my $uid (@uid_chunk) {
-			$nodc->{$uid} = $nod_hr->{$uid} || 0;
-			$nixc->{$uid} = $nix_hr->{$uid} || 0;
+			$self->{nodc}{$uid} = $nod_hr->{$uid} || 0;
+			$self->{nixc}{$uid} = $nix_hr->{$uid} || 0;
 		}
 		sleep 1 if @uids_needed;
 	}
 }
 
 sub get_mults {
-	my($class, $match_ar) = @_;
+	my($self, $match_ar) = @_;
 
 	my $uid_mults = { };
 	for my $hr (@$match_ar) {
-		my $mult = $class->get_mult($hr);
+		my $mult = $self->get_mult($hr);
 		$uid_mults->{ $hr->{sourcetag_uid} } ||= [ ];
 		push @{$uid_mults->{ $hr->{sourcetag_uid} }}, $mult;
 	}
@@ -205,15 +230,17 @@
 }
 
 sub get_mult {
-	my($class, $hr) = @_;
+	my($self, $hr) = @_;
 
 	my $mult = $hr->{simil};
+	my $slashdb = getCurrentDB();
+	my $globj_types = $slashdb->getGlobjTypes();
 
 	# If this tag-match is too old, it earns the new user less credit.
 	my $older_tag = $hr->{sourcetag_created_at_ut};
 	$older_tag = $hr->{newtag_created_at_ut} if $hr->{newtag_created_at_ut} < $older_tag;
 	my $tag_age = time - $older_tag;
-	my $max_days = $months_back * 30 + 1;
+	my $max_days = $self->{months_back} * 30 + 1;
 	if ($tag_age < 7 * 86400) {
 		# tags within the past week get full credit
 	} elsif ($tag_age < 30 * 86400) {
@@ -254,7 +281,7 @@
 	}
 
 	# Tagging different types gets different mults.
-	my $type = $globjtypes->{ $hr->{gtid} };
+	my $type = $globj_types->{ $hr->{gtid} };
 	if ($type eq 'comments') {
 		# fair bit of credit for matching mods on comments
 		# XXX may need to adjust this if it turns out that we're
@@ -270,18 +297,18 @@
 	# rare choice (for either user) is considered more indicative.
 	my($su,  $nu)  = ($hr->{sourcetag_uid},       $hr->{newtag_uid});
 	my($stn, $ntn) = ($hr->{sourcetag_tagnameid}, $hr->{newtag_tagnameid});
-	my($nodid, $nixid) = ($stn == $tagnameid->{nod}, $stn == $tagnameid->{nix});
+	my($nodid, $nixid) = ($stn == $self->{nodid}, $stn == $self->{nixid});
 	if (    ( $stn == $nodid || $stn == $nixid )
 	&&      ( $ntn == $nodid || $ntn == $nixid ) ) {
 		my($su, $nu) = ($hr->{sourcetag_uid}, $hr->{newtag_uid});
-		my $snod = $nodc->{$su};
-		my $snix = $nixc->{$su};
-		my $nnod = $nodc->{$nu};
-		my $nnix = $nixc->{$nu};
+		my $snod = $self->{nodc}{$su};
+		my $snix = $self->{nixc}{$su};
+		my $nnod = $self->{nodc}{$nu};
+		my $nnix = $self->{nixc}{$nu};
 		my $sfrac = ($stn == $nodid ? $snix : $snod) / ($snod+$snix+1);
 		my $nfrac = ($ntn == $nodid ? $nnix : $nnod) / ($nnod+$nnix+1);
-		if ($debug) {
-			slashdLog("$class get_mult su='$su' nu='$nu' sfrac='$sfrac' nfrac='$nfrac'");
+		if ($self->{debug}) {
+			print STDERR ref($self) . " get_mult su='$su' nu='$nu' sfrac='$sfrac' nfrac='$nfrac'\n";
 		}
 		$mult *= $sfrac * $nfrac;
 	}
@@ -290,15 +317,15 @@
 }
 
 sub get_mult_timebeforepub {
-	my($class, $match_ar) = @_;
+	my($self, $match_ar) = @_;
 	
 	my $tbp_mults = [ ];
 	for my $hr (@$match_ar) {
 		next unless $hr->{duration} == -1 && defined $hr->{timebeforepub};
 		my $nodnix;
-		if ($hr->{sourcetag_tagnameid} == $tagnameid->{nod}) {
+		if ($hr->{sourcetag_tagnameid} == $self->{nodid}) {
 			$nodnix = 1;
-		} elsif ($hr->{sourcetag_tagnameid} == $tagnameid->{nix}) {
+		} elsif ($hr->{sourcetag_tagnameid} == $self->{nixid}) {
 			$nodnix = -1;
 		} else {
 			next;
@@ -324,7 +351,8 @@
 sub get_total_weight {
 		# uid_mults is a hashref where the key is the source uid and
 		# the value is an arrayref of mults from that uid
-	my($class, $uid_mults, $clout, $created_at, $karma, $tokens) = @_;
+	my($self, $tags_peerclout, $uid_mults,
+		$clout, $created_at, $karma, $tokens, $new_uid) = @_;
 		
 	return 0 if $clout == 0 || $tokens < -1000 || $karma < -10;
 
@@ -338,20 +366,22 @@
 	# correlations with other users' tags.
 	if ($uid_mults->{'-1'}) {
 		if (@{$uid_mults->{'-1'}}) {
-			my @balanced = $class->balance_weight_vectors(@{$uid_mults->{'-1'}});
+			print STDERR "get_total_weight for $new_uid calling balance_weight_vectors -1\n" if $self->{debug};
+			my @balanced = $self->balance_weight_vectors(@{$uid_mults->{'-1'}});
 			push @total_mults, $constants->{tags_tagpeerval_postingbonus}
-				* $class->sum_weight_vectors(@balanced);
+				* $self->sum_weight_vectors(@balanced);
 			$any_weight = 1;
 		}
 		delete $uid_mults->{'-1'};
 	}
 	
 	# Start by sorting source uids by decreasing weight.
-	my @source_uids = sort { $tags_peerweight->{$b} <=> $tags_peerweight->{$a} } keys %$uid_mults;
+	my @nodef = grep { !defined $tags_peerclout->{$_} } keys %$uid_mults; $#nodef = 20 if $#nodef > 20; print STDERR "get_total_weight for $new_uid nodef: '@nodef'\n" if @nodef;
+	my @source_uids = sort { $tags_peerclout->{$b} <=> $tags_peerclout->{$a} } keys %$uid_mults;
 
 	# If all source uids have weight 0, we know the answer quickly.
 	for my $uid (@source_uids) {
-		if ($tags_peerweight->{$uid} > 0) {
+		if ($tags_peerclout->{$uid} > 0) {
 			$any_weight = 1;
 			last;
 		}
@@ -360,21 +390,21 @@
 
 	# Get the mult for each of those
 	for my $uid (@source_uids) {
-		my @balanced = $class->balance_weight_vectors(@{$uid_mults->{$uid}});
-		push @total_mults, $tags_peerweight->{$uid} * $class->sum_weight_vectors(@balanced);
-		if ($debug) {
-			my @t2 = map { sprintf("%.5g", @_) } @total_mults;
-			slashdLog("$class source_uid=$uid ($tags_peerweight->{$uid}) total_mults='@t2'");
+	print STDERR "get_total_weight for $new_uid calling balance_weight_vectors $uid\n" if $self->{debug};
+		my @balanced = $self->balance_weight_vectors(@{$uid_mults->{$uid}});
+		push @total_mults, $tags_peerclout->{$uid} * $self->sum_weight_vectors(@balanced);
+		if ($self->{debug}) {
+			my @t2 = map { sprintf("%.6g", $_) } @total_mults;
+			print STDERR "get_total_weight for $new_uid source_uid=$uid (clout $tags_peerclout->{$uid}), total_mults='@t2' from balanced '@balanced'\n";
 		}
 	}
 
 	# Then (using the same decreasing-multipliers algorithm) get the
 	# total of all those mults.
-	my @balanced = $class->balance_weight_vectors(@total_mults);
-	my $total = $class->sum_weight_vectors(@balanced);
-	if ($debug) {
-		slashdLog("$class total=$total");
-	}
+	print STDERR "get_total_weight for $new_uid calling balance_weight_vectors total\n" if $self->{debug};
+	my @balanced = $self->balance_weight_vectors(@total_mults);
+	my $total = $self->sum_weight_vectors(@balanced);
+	print STDERR ref($self) . " total=$total for uid $new_uid\n" if $self->{debug};
 	
 	# If this user was created recently, less weight for them.
 	my $daysold = (time - $created_at)/86400;
@@ -415,11 +445,11 @@
 }
 
 sub balance_weight_vectors {
-	my $class = shift @_;
-	my @w = sort { abs($b) <=> abs($a) || $b > $a } @_;
+	my($self, @w) = @_;
+	@w = sort { abs($b) <=> abs($a) || $b > $a } @w;
 	my $w_pos_mag = 0; for my $w (@w) { $w_pos_mag += $w if $w > 0 };
 	my $w_neg_mag = 0; for my $w (@w) { $w_neg_mag -= $w if $w < 0 };
-	return @_ if !$w_pos_mag && !$w_neg_mag;
+	return @w if !$w_pos_mag && !$w_neg_mag;
 
 	my @ret;
 	# Swinging more than 60-40% one way or the other reduces the
@@ -427,63 +457,53 @@
 	my $total = $w_pos_mag+$w_neg_mag;
 	if ($w_pos_mag > $total * 0.60) {
 		my $neg_reduc_factor = $w_neg_mag*3/$w_pos_mag;
-		@ret = map { $_ < 0 ? $_*$neg_reduc_factor : $_ } @_;
+		@ret = map { $_ < 0 ? $_*$neg_reduc_factor : $_ } @w;
 	} elsif ($w_neg_mag > $total * 0.60) {
 		my $pos_reduc_factor = $w_pos_mag*3/$w_neg_mag;
-		@ret = map { $_ > 0 ? $_*$pos_reduc_factor : $_ } @_;
+		@ret = map { $_ > 0 ? $_*$pos_reduc_factor : $_ } @w;
 	} else {
 		# No change.
-		@ret = @_;
+		@ret = @w;
 	}
-	if ($debug) {
-		my @w2 = map { sprintf("%5d", @_) } @w;   $#w2 = 4 if $#w2 > 4;
-		my @r2 = map { sprintf("%5d", @_) } @ret; $#r2 = 4 if $#r2 > 4;
-		slashdLog(sprintf("$class balance_weight_vectors pos=%.5g neg=%.5g from '%s' to '%s'",
-			$w_pos_mag, $w_neg_mag, join(' ', @w2), join(' ', @r2)));
+	if ($self->{debug} || $w_pos_mag > 10_000 || $w_neg_mag > 10_000) {
+		my @w2 = @w;   $#w2 = 4 if $#w2 > 4;
+		my @r2 = @ret; $#r2 = 4 if $#r2 > 4;
+		print STDERR sprintf("%s balance_weight_vectors posmag=%0.5g negmag=%0.5g from '%s' to '%s'\n",
+			ref($self), $w_pos_mag, $w_neg_mag, join(' ', @w2), join(' ', @r2));
 	}
 	return @ret;
 }
 
 sub sum_weight_vectors {
-	my $class = shift @_;
-	my @w = sort { abs($b) <=> abs($a) || $b > $a } @_;
+	my($self, @v) = @_;
+	my @w = sort { abs($b) <=> abs($a) || $b > $a } @v;
 	$#w = 50 if $#w > 50; # beyond this point contributions are tiny
 	my $weight = 0;
 	my $cur_magnitude = 1;
 	for my $w (@w) {
-		$cur_magnitude *= $cumfrac;
+		$cur_magnitude *= $self->{cumfrac};
 		$weight += $cur_magnitude * $w;
 	}
 	$weight = 0 if $weight < 0;
-	if ($debug) {
-		slashdLog("$class sum_weight_vectors weight='$weight' w='@w'");
+	if ($self->{debug}) {
+		print STDERR ref($self) . " sum_weight_vectors weight='$weight' w='@w'\n";
 	}
 	return $weight;
 }
 
-sub insert_nextgen {
-	my($class, $g, $insert_ar) = @_;
-	my $slashdb = getCurrentDB();
-	# XXX Should turn off autocommit for this loop
-	for my $hr (@$insert_ar) {
-		$hr->{gen} = $g;
-		$slashdb->sqlInsert('tags_peerclout', $hr);
-	}
-}
-
 sub update_tags_peerclout {
-	my($class, $insert_ar) = @_;
+	my($self, $insert_ar, $tags_peerclout) = @_;
 	for my $hr (@$insert_ar) {
 		$tags_peerclout->{ $hr->{uid} } = $hr->{clout};
 	}
 }
 
-sub copy_peerweight_sql {
-	my($class) = $_;
+sub copy_peerclout_sql {
+	my($self) = @_;
 	my $slashdb = getCurrentDB();
 	$slashdb->sqlDo("SET AUTOCOMMIT=0");
-        $slashdb->sqlDo("UPDATE users_clout SET clout=NULL WHERE clid='$clid'");
-        $slashdb->sqlDo("INSERT INTO users_clout (clout_id, uid, clid, clout) SELECT NULL, uid, '$clid', clout FROM tags_peerclout WHERE clid='$clid'");
+        $slashdb->sqlDo("UPDATE users_clout SET clout=NULL WHERE clid='$self->{clid}'");
+        $slashdb->sqlDo("REPLACE INTO users_clout (clout_id, uid, clid, clout) SELECT NULL, uid, '$self->{clid}', clout FROM tags_peerclout WHERE clid='$self->{clid}'");
 	$slashdb->sqlDo("COMMIT");
 	$slashdb->sqlDo("SET AUTOCOMMIT=1");
 }

Modified: slashjp/trunk/plugins/Tags/Clout.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/Clout.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -6,15 +6,39 @@
 package Slash::Clout;
 
 use strict;
+use warnings;
 use Slash;
-use Slash::Clout::Describe;
-use Slash::Clout::Vote;
-use Slash::Clout::Moderate;
+use Slash::Utility;
+use Slash::Tags;
+#use Slash::Clout::Describe;
+#use Slash::Clout::Vote;
+#use Slash::Clout::Moderate;
 
+use base 'Slash::DB::Utility';
+use base 'Slash::DB';
+
 use vars qw($VERSION);
 
 ($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
 
+sub init {
+	my($self) = @_;
+
+	$self->{months_back} = 4; # default
+	my $slashdb = getCurrentDB();
+        my $info = $slashdb->getCloutInfo();
+        for my $clid (keys %$info) {
+                $self->{clid} = $clid if $info->{$clid}{class} eq ref($self);
+        }
+        warn "cannot find clid for $self" if !$self->{clid};
+
+	my $constants = getCurrentStatic();
+	my $tags_reader = getObject('Slash::Tags', { db_type => 'reader' });
+	$self->{nodid} = $tags_reader->getTagnameidCreate($constants->{tags_upvote_tagname}   || 'nod');
+	$self->{nixid} = $tags_reader->getTagnameidCreate($constants->{tags_downvote_tagname} || 'nix');
+	1;
+}
+
 #sub insert_nextgen {
 #        my($g, $insert_ar) = @_;
 #        my $slashdb = getCurrentDB();

Modified: slashjp/trunk/plugins/Tags/Tags.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Tags.pm	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/Tags.pm	2007-10-31 05:54:43 UTC (rev 234)
@@ -26,8 +26,7 @@
 	my($class, $user) = @_;
 	my $self = {};
 
-	my $plugin = getCurrentStatic('plugin');
-	return unless $plugin->{Tags};
+	return undef unless $class->isInstalled();
 
 	bless($self, $class);
 	$self->{virtual_user} = $user;
@@ -36,6 +35,12 @@
 	return $self;
 }
 
+sub isInstalled {
+	my($class) = @_;
+	my $constants = getCurrentStatic();
+	return $constants->{plugin}{Tags} || 0;
+}
+
 ########################################################
 
 # createTag's first argument is a hashref with four sets of
@@ -617,7 +622,8 @@
 			# XXX this stub is good enough for now but we may
 			# need the whole actual getUser() user at some
 			# future time
-			$uid_clout_hr->{$uid} = $clout_info->{class}->getUserClout(\%user_stub);
+			my $clout = getObject($clout_info->{class}, { db_type => 'reader' });
+			$uid_clout_hr->{$uid} = $clout->getUserClout(\%user_stub);
 		}
 	}
 

Modified: slashjp/trunk/plugins/Tags/tags_updateclouts.pl
===================================================================
--- slashjp/trunk/plugins/Tags/tags_updateclouts.pl	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/tags_updateclouts.pl	2007-10-31 05:54:43 UTC (rev 234)
@@ -34,9 +34,12 @@
 	$globj_types = $slashdb->getGlobjTypes();
 	$clout_types = $slashdb->getCloutTypes();
 	$clout_info  = $slashdb->getCloutInfo();
+	my $total_inserts = 0;
 
 	for my $clid (sort { $a <=> $b } grep { /^\d+$/ } keys %$clout_types) {
 		my $class = $clout_info->{$clid}{class};
+		my $clout = getObject($class);
+		next unless $clout;
 		sleep 5;
 		$tags_peerclout = $slashdb->sqlSelectAllKeyValue(
 			'uid, clout',
@@ -49,21 +52,38 @@
 			while (1) {
 				my $lastgen_count = $slashdb->sqlCount('tags_peerclout',
 					"clid=$clid AND gen=$g");
+				slashdLog("gen $g for $clout_types->{$clid}: $lastgen_count");
 				last unless $lastgen_count;
-				my $hr_ar = $class->get_nextgen($g);
-				slashdLog("$class gen $g produces " . scalar(@$hr_ar) . " rows");
-				my $insert_ar = $class->process_nextgen($hr_ar);
+				my $hr_ar = $clout->get_nextgen($g);
+				slashdLog("$class gen $g produces " . scalar(defined($hr_ar) ? @$hr_ar : 0) . " rows");
+				my $insert_ar = $clout->process_nextgen($hr_ar, $tags_peerclout);
+				slashdLog("$class gen $g insert_ar count: " . scalar(@$insert_ar));
+				$total_inserts += scalar(@$insert_ar);
 				++$g;
-				for my $hr (@$insert_ar) { $hr->{clid} = $clid }
-				$class->insert_nextgen($g, $insert_ar);
-				$class->update_tags_peerclout($insert_ar);
+				my $total_rows = insert_nextgen($tags_peerclout, $clid, $g, $insert_ar);
+				slashdLog("$class inserted $total_rows rows");
 				sleep 5;
 			}
-			$class->copy_peerclout_sql();
+			$clout->copy_peerclout_sql();
 		}
 
 	}
+
+	return "$total_inserts inserts";
 };
 
+sub insert_nextgen {
+	my($tags_peerclout, $clid, $gen, $insert_ar) = @_;
+	my $slashdb = getCurrentDB();
+	my $rows = 0;
+	for my $hr (@$insert_ar) {
+                ($hr->{clid}, $hr->{gen}) = ($clid, $gen);
+if (!$rows) { use Data::Dumper; my $hd = Dumper($hr); $hd =~ s/\s+/ /g; print STDERR "insert hr: $hd\n"; }
+                $rows += $slashdb->sqlInsert('tags_peerclout', $hr);
+                $tags_peerclout->{ $hr->{uid} } = $hr->{clout};
+        }
+	return $rows;
+}
+
 1;
 

Modified: slashjp/trunk/plugins/Tags/templates/tagsstorydivadmin;misc;default
===================================================================
--- slashjp/trunk/plugins/Tags/templates/tagsstorydivadmin;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/templates/tagsstorydivadmin;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -17,7 +17,7 @@
 
 [% PROCESS ajax_reskey_tag reskey_label => 'admin_commands-reskey-' _ sidenc, reskey_name => 'ajax_admin' %]
 <input type="text" id="tags_admin_commands-[% sidenc %]" name="tags_admin_commands-[% sidenc %]" value="" size=50 maxlength=60 onkeyup="handleEnter(event, adminTagsCommands, '[% sidenc %]')">
-<input type="button" value="Admin" onclick="adminTagsCommands('[% sidenc %]','stories')" class="button"> <span id="taghist-[% sidenc %]"><a href="javascript:tagsHistory('[% sidenc %]','stories')">[History]</a></span>
+<input type="button" value="Admin" onclick="adminTagsCommands('[% sidenc %]','stories')" class="button"> <span id="taghist-[% sidenc %]"><a href="#" onclick="tagsHistory('[% sidenc %]','stories'); return false">[History]</a></span>
 
 <div>[% tags_admin_str %]</div>
 

Modified: slashjp/trunk/plugins/Tags/templates/tagsstorydivtagbox;misc;default
===================================================================
--- slashjp/trunk/plugins/Tags/templates/tagsstorydivtagbox;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/templates/tagsstorydivtagbox;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -17,13 +17,13 @@
 [% IF user.tags_canread_stories %]
 <div id="tagbox-[% sidenc %]" class="tags">
 
-<div id="tagbox-title-[% sidenc %]" class="tagtitleclosed">&nbsp;[% IF user.tags_canwrite_stories %]<a href="javascript:tagsToggleStoryDiv('[% sidenc %]','[% user.is_admin %]');">[% ELSIF user.is_anon %]<a href="[% gSkin.rootdir %]/login.pl">[% ELSE %]<a href="[% gSkin.rootdir %]/subscribe.pl">[% END %]<span class="tagsheader" id="toggletags-button-[% sidenc %]">[+]</span></a>
+<div id="tagbox-title-[% sidenc %]" class="tagtitleclosed">&nbsp;[% IF user.tags_canwrite_stories %]<a href="#" onclick="tagsToggleStoryDiv('[% sidenc %]','[% user.is_admin %]'); return false">[% ELSIF user.is_anon %]<a href="[% gSkin.rootdir %]/login.pl">[% ELSE %]<a href="[% gSkin.rootdir %]/subscribe.pl">[% END %]<span class="tagsheader" id="toggletags-button-[% sidenc %]">[+]</span></a>
 [% IF tags_top.size %]
 	[% FOR t = tags_top -%]
 		<span class="tagname"><a href="/tags/[% t | strip_html %]">[% t | strip_html %]</a></span>[% IF !loop.last() || story.is_future %], [% END -%]
 	[%- END %]
 [%- END %]
-[%- IF user.tags_canwrite_stories && story.is_future %]<span class="tagmenu"><a onClick="clickCompleter(this, '[% sidenc %]','[% user.is_admin %]','stories', 4, {action1:completer_setTag})">feedback</a></span>[% END %]
+[%- IF user.tags_canwrite_stories && story.is_future %]<span class="tagmenu"><a onClick="clickCompleter(this, '[% sidenc %]','[% user.is_admin %]','stories', 4, {action1:completer_setTag}); return false">feedback</a></span>[% END %]
 <i>(<a href="/faq/tags.shtml">tagging beta</a>)</i>
 </div>
 

Modified: slashjp/trunk/plugins/Tags/templates/tagsurldivadmin;misc;default
===================================================================
--- slashjp/trunk/plugins/Tags/templates/tagsurldivadmin;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/templates/tagsurldivadmin;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -17,7 +17,7 @@
 
 [% PROCESS ajax_reskey_tag reskey_label => 'admin_commands-reskey-' _ id, reskey_name => 'ajax_admin' %]
 <input type="text" id="tags_admin_commands-[% id %]" name="tags_admin_commands-[% id %]" value="" size=50 maxlength=60>
-<input type="button" value="Admin" onclick="adminTagsCommands('[% id %]','urls')" class="button"> <span id="taghist-[% id %]"><a href="javascript:tagsHistory('[% id %]','urls')">[History]</a></span>
+<input type="button" value="Admin" onclick="adminTagsCommands('[% id %]','urls')" class="button"> <span id="taghist-[% id %]"><a href="#" onclick="tagsHistory('[% id %]','urls'); return false">[History]</a></span>
 
 <div>[% tags_admin_str %]</div>
 

Modified: slashjp/trunk/plugins/Tags/templates/tagsurldivtagbox;misc;default
===================================================================
--- slashjp/trunk/plugins/Tags/templates/tagsurldivtagbox;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/plugins/Tags/templates/tagsurldivtagbox;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -17,10 +17,10 @@
 
 <div id="tagbox-[% url_id %]" class="tags">
 
-<div id="tagbox-title-[% url_id %]" class="tagtitleclosed">&nbsp;[% IF user.tags_canwrite_stories %]<a href="javascript:tagsToggleStoryDiv('[% url_id %]','[% user.is_admin %]','urls');">[% ELSIF user.is_anon %]<a href="[% gSkin.rootdir %]/login.pl">[% ELSE %]<a href="[% gSkin.rootdir %]/subscribe.pl">[% END %]<span class="tagsheader" id="toggletags-button-[% url_id %]">[+]</span></a>
+<div id="tagbox-title-[% url_id %]" class="tagtitleclosed">&nbsp;[% IF user.tags_canwrite_stories %]<a href="#" onclick="tagsToggleStoryDiv('[% url_id %]','[% user.is_admin %]','urls'); return false">[% ELSIF user.is_anon %]<a href="[% gSkin.rootdir %]/login.pl">[% ELSE %]<a href="[% gSkin.rootdir %]/subscribe.pl">[% END %]<span class="tagsheader" id="toggletags-button-[% url_id %]">[+]</span></a>
 [% IF tags_top.size %]
 	[% FOR t = tags_top -%]
-		<span class="tagname">[% IF user.tags_canwrite_stories %]<a href="javascript:tagsOpenAndEnter('[% url_id %]','[% t %]','[% user.is_admin %]','urls')">[% END %][% t | strip_html %][% IF user.tags_canwrite_stories %]</a>[% END %]</span>[% IF !loop.last() %], [% END -%]
+		<span class="tagname">[% IF user.tags_canwrite_stories %]<a href="#" onclick="tagsOpenAndEnter('[% url_id %]','[% t %]','[% user.is_admin %]','urls'); return false">[% END %][% t | strip_html %][% IF user.tags_canwrite_stories %]</a>[% END %]</span>[% IF !loop.last() %], [% END -%]
 	[%- END %]
 [% END %]
 <i>(<a href="/faq/tags.shtml">tagging beta</a>)</i>
@@ -32,7 +32,7 @@
 	[% IF tags_example.size %]
 		<div>Examples:
 		[% FOR t = tags_example -%]
-			<span class="tagname"><a href="javascript:tagsOpenAndEnter('[% url_id %]','[% t %]','[% user.is_admin %]','urls')">[% t | strip_html %]</a></span>[% IF !loop.last() %], [% END -%]
+			<span class="tagname"><a href="#" onclick="tagsOpenAndEnter('[% url_id %]','[% t %]','[% user.is_admin %]','urls'); return false">[% t | strip_html %]</a></span>[% IF !loop.last() %], [% END -%]
 		[%- END %]
 		</div>
 	[% END %]

Modified: slashjp/trunk/sql/mysql/defaults.sql
===================================================================
--- slashjp/trunk/sql/mysql/defaults.sql	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/sql/mysql/defaults.sql	2007-10-31 05:54:43 UTC (rev 234)
@@ -737,6 +737,7 @@
 INSERT INTO vars (name, value, description) VALUES ('admin_story_lookahead_default', 365*86400, 'In the admin.pl storylist, how many seconds to look into the future for all stories by default (but see skins_admin_story_lookahead_mainpage)');
 INSERT INTO vars (name, value, description) VALUES ('admin_story_lookahead_infinite', '0', 'In the admin.pl storylist, always show all future stories no matter how far in the future?');
 INSERT INTO vars (name, value, description) VALUES ('admin_story_lookahead_mainpage', 72*3600, 'In the admin.pl storylist, how many seconds to look into the future for stories on the mainpage');
+INSERT INTO vars (name, value, description) VALUES ('admin_use_blob_for_upload', '1', 'Use blobs for fileuploading - 1 for yes, 0 for no or file-based uploading');
 INSERT INTO vars (name, value, description) VALUES ('admin_warn_primaryskid', '', 'Warn admin if a story is saved with the following primaryskids (skids delimited by |)');
 INSERT INTO vars (name, value, description) VALUES ('admin_timeout','30','time in minutes before idle admin session ends');
 INSERT INTO vars (name, value, description) VALUES ('adminmail','admin****@examp*****','All admin mail goes here');
@@ -829,7 +830,7 @@
 INSERT INTO vars (name, value, description) VALUES ('cur_performance_stats_lastid', '0', 'accesslogid to start searching at');
 INSERT INTO vars (name, value, description) VALUES ('cur_performance_stats_weeks', '8', 'number of weeks back to compare current stats to');
 INSERT INTO vars (name, value, description) VALUES ('currentqid',1,'The Current Question on the homepage pollbooth');
-INSERT INTO vars (name, value, description) VALUES ('cvs_tag_currentcode','T_2_5_0_180','The current cvs tag that the code was updated to - this does not affect site behavior but may be useful for your records');
+INSERT INTO vars (name, value, description) VALUES ('cvs_tag_currentcode','T_2_5_0_181','The current cvs tag that the code was updated to - this does not affect site behavior but may be useful for your records');
 INSERT INTO vars (name, value, description) VALUES ('datadir','/usr/local/slash/www.example.com','What is the root of the install for Slash');
 INSERT INTO vars (name, value, description) VALUES ('db_auto_increment_increment','1','If your master DB uses auto_increment_increment, i.e. multiple master replication, echo its value into this var');
 INSERT INTO vars (name, value, description) VALUES ('dbsparklines_disp','0','Display dbsparklines in the currentAdminUsers box?');

Modified: slashjp/trunk/sql/mysql/slashschema_create.sql
===================================================================
--- slashjp/trunk/sql/mysql/slashschema_create.sql	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/sql/mysql/slashschema_create.sql	2007-10-31 05:54:43 UTC (rev 234)
@@ -520,6 +520,7 @@
 	fhid mediumint(8) unsigned default NULL,
 	file varchar(255) default NULL,
 	action enum('upload','thumbnails') default NULL,
+	blobid VARCHAR(32) DEFAULT "" NOT NULL,
 	PRIMARY KEY  (fqid)
 ) ENGINE=InnoDB;
 
@@ -1073,6 +1074,8 @@
 	stoid mediumint unsigned NOT NULL,
 	filetype ENUM("file", "image", "audio") not null default "file",
 	name varchar(255) default '' NOT NULL,
+	width smallint unsigned not null default 0,
+	height smallint unsigned not null default 0,
 	PRIMARY KEY (sfid),
 	INDEX stoid(stoid)
 ) ENGINE=InnoDB;
@@ -1114,6 +1117,7 @@
 	del tinyint DEFAULT '0' NOT NULL,
 	weight float DEFAULT '0' NOT NULL, 
 	signature varchar(32) NOT NULL,
+	mediatype enum("text", "none", "video", "image", "audio") default "none" NOT NULL,
 	PRIMARY KEY (subid),
 	UNIQUE signature (signature),
 	KEY emaildomain (emaildomain),

Modified: slashjp/trunk/sql/mysql/upgrades
===================================================================
--- slashjp/trunk/sql/mysql/upgrades	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/sql/mysql/upgrades	2007-10-31 05:54:43 UTC (rev 234)
@@ -4877,8 +4877,6 @@
 # 2007-09-26
 UPDATE vars SET value = 'T_2_5_0_176' WHERE name = 'cvs_tag_currentcode';
 
-# PUDGE LAST UPDATED HERE
-
 # For plugins/Tags
 UPDATE tagboxes SET clid=2 WHERE name='FirstMover';
 
@@ -4903,9 +4901,7 @@
 # 2007-10-11
 UPDATE vars SET value = 'T_2_5_0_179' WHERE name = 'cvs_tag_currentcode';
 
-# SLASHDOT LAST UPDATED HERE
 
-
 # default prefs for new /. accounts
 INSERT INTO string_param (type, code, name) VALUES ('otherusersparam','discussion2','slashdot');
 INSERT INTO string_param (type, code, name) VALUES ('otherusersparam','d2_comment_q','5'); # medium
@@ -4943,5 +4939,32 @@
 # 2007-10-16
 UPDATE vars SET value = 'T_2_5_0_180' WHERE name = 'cvs_tag_currentcode';
 
+# SLASHDOT LAST UPDATED HERE
+
+INSERT INTO string_param (type, code, name) VALUES ('mediatypes','none','None');
+INSERT INTO string_param (type, code, name) VALUES ('mediatypes','video','Video');
+INSERT INTO string_param (type, code, name) VALUES ('mediatypes','image','Image');
+INSERT INTO string_param (type, code, name) VALUES ('mediatypes','audio','Audio');
+INSERT INTO string_param (type, code, name) VALUES ('mediatypes','text','Text');
+
+ALTER TABLE submissions ADD COLUMN mediatype enum("none", "text", "video","image","audio") default "none" NOT NULL;
+
+# For plugins/FireHose
+ALTER TABLE firehose ADD COLUMN mediatype enum("none", "text", "video","image","audio") default "none" NOT NULL;
+
+ALTER TABLE file_queue ADD COLUMN blobid VARCHAR(32) DEFAULT "" NOT NULL;
+ALTER TABLE story_static_files ADD COLUMN width smallint unsigned not null default 0;  
+ALTER TABLE story_static_files ADD COLUMN height smallint unsigned not null default 0;
+
+INSERT INTO vars (name, value, description) VALUES ('admin_use_blob_for_upload', '1', 'Use blobs for fileuploading - 1 for yes, 0 for no or file-based uploading');
+
+UPDATE string_param SET name = '9' WHERE type = 'otherusersparam' AND code = 'd2_comment_q'; # large
+
+
+# 2007-10-25
+UPDATE vars SET value = 'T_2_5_0_181' WHERE name = 'cvs_tag_currentcode';
+
 # SLASHCODE/USEPERL LAST UPDATED HERE
 
+# PUDGE LAST UPDATED HERE
+

Modified: slashjp/trunk/themes/slashcode/htdocs/comments.css
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/comments.css	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/htdocs/comments.css	2007-10-31 05:54:43 UTC (rev 234)
@@ -138,6 +138,16 @@
 .hide { display: none   }
 .show { display: inline }
 
+.oldcomment {
+	opacity: .65;
+	filter: alpha(opacity=65);
+}
+.newcomment {
+}
+.currcomment {
+	opacity: .50;
+	filter: alpha(opacity=50);
+}
 
 .comment > .hidden  {
 	display: none;

Modified: slashjp/trunk/themes/slashcode/htdocs/images/comments.js
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/images/comments.js	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/htdocs/images/comments.js	2007-10-31 05:54:43 UTC (rev 234)
@@ -13,6 +13,8 @@
 var update_comments = {};
 var root_comments_hash = {};
 var last_updated_comments = [];
+var last_updated_comments_index = -1;
+var current_cid = 0;
 var more_comments_num;
 var behaviors = {
 	'default': { ancestors: 'none', parent: 'none', children: 'none', descendants: 'none', siblings: 'none', sameauthor: 'none' }, 
@@ -64,6 +66,7 @@
 			} else if (viewmodevalue[mode] >= viewmodevalue['full']) {
 				var cd = fetchEl('comment_otherdetails_' + cid);
 				if (!cd.innerHTML) {
+					cd.innerHTML = '<br><b><big>Loading ...</big></b>';
 					fetch_comments.push(cid);
 					fetch_comments_pieces[cid] = 1;
 					doshort = 1;
@@ -72,7 +75,7 @@
 		}
 		if (doshort)
 			setShortSubject(cid, mode, cl);
-		existingdiv.className = mode;
+		existingdiv.className = existingdiv.className.replace(/full|hidden|oneline/, mode);
 	}
 
 	if (placeholder)
@@ -144,6 +147,13 @@
 	if ((alone && alone == 2) || (!alone && viewmodevalue[displaymode[abscid]] == viewmodevalue['full']))
 		cid = '-' + abscid;
 
+	if (abscid == cid) { // expanding == selecting
+		setCurrentComment(cid);
+		if (checkAdTimer(cid))
+			adTimerInsert = cid;
+	}
+
+
 // this doesn't work
 //	var statusdiv = $('comment_status_' + abscid);
 //	statusdiv.innerHTML = 'Working ...';
@@ -152,22 +162,24 @@
 //	if (!user_is_admin) // XXX: for now, admins-only, for testing
 //		mods = 1;
 
-	if (!alone && mods) {
-		if (mods == 1 || ((mods == 3) && (abscid == cid)) || ((mods == 4) && (abscid != cid))) {
-			shift_down = 0;
-			alt_down   = 0;
-		} else if (mods == 2 || ((mods == 3) && (abscid != cid)) || ((mods == 4) && (abscid == cid))) {
-			shift_down = 1;
-			alt_down   = 0;
-		} else if (mods == 5) {
-			shift_down = 1;
-			alt_down   = 1;
-		}
-	}
+// 	if (!alone && mods) {
+// 		if (mods == 1 || ((mods == 3) && (abscid == cid)) || ((mods == 4) && (abscid != cid))) {
+// 			shift_down = 0;
+// 			alt_down   = 0;
+// 		} else if (mods == 2 || ((mods == 3) && (abscid != cid)) || ((mods == 4) && (abscid == cid))) {
+// 			shift_down = 1;
+// 			alt_down   = 0;
+// 		} else if (mods == 5) {
+// 			shift_down = 1;
+// 			alt_down   = 1;
+// 		}
+// 	}
+// 
+// 	if (shift_down && alt_down)
+// 		alone = 1;
+// 
+// 	resetModifiers();
 
-	if (shift_down && alt_down)
-		alone = 1;
-
 	if (alone && alone == 1) {
 		var thismode = abscid == cid ? 'full' : 'oneline';
 		updateDisplayMode(abscid, thismode, 1);
@@ -177,8 +189,6 @@
 	updateCommentTree(abscid);
 	finishCommentUpdates();
 
-//	resetModifiers();
-
 //	statusdiv.innerHTML = '';
 
 	if (!commentIsInWindow(abscid)) {
@@ -270,7 +280,7 @@
 		else
 			return kidhiddens + 1;
 	} else if (kidhiddens) {
-		var kidstring = '<a href="javascript:revealKids(' + cid + ')">' + kidhiddens;
+		var kidstring = '<a href="#" onclick="revealKids(' + cid + '); return false">' + kidhiddens;
 		if (kidhiddens == 1) {
 			kidstring += ' hidden comment</a>';
 		} else {
@@ -431,10 +441,12 @@
 			var parent = comments[pid];
 			parent['kids'].push(cid);
 
-			// XXX: not QUITE right, but works for now ...
-			// ideally this would stick in a previous </ul>
-			// rather than adding a new one -- pudge
-			tree.innerHTML = tree.innerHTML + '<ul>' + html + '</ul>';
+			var commtree = $('commtree_' + pid);
+			if (commtree) {
+				commtree.innerHTML = commtree.innerHTML + html;
+			} else {
+				tree.innerHTML = tree.innerHTML + '<ul id="commtree_' + pid + '">' + html + '</ul>';
+			}
 		}
 
 	} else {
@@ -523,7 +535,7 @@
 	var comment = fetchEl('comment_' + cid);
 	if (!comment) { return }
 
-	var defmode = comment.className;
+	var defmode = comment.className.match(/full|hidden|oneline/);
 	if (!defmode) { return }
 
 	futuredisplaymode[cid] = prehiddendisplaymode[cid] = displaymode[cid] = defmode;
@@ -636,7 +648,7 @@
 	}).join(';');
 }
 
-function ajaxFetchComments(cids, option, thresh) {
+function ajaxFetchComments(cids, option, thresh, highlight) {
 	if (cids && !cids.length)
 		return;
 
@@ -645,6 +657,9 @@
 
 	var params = [];
 	params['op']              = 'comments_fetch';
+
+	var newoldstuff = cids ? 0 : 1;
+
 	if (cids) {
 		params['cids']    = cids;
 	} else {
@@ -689,7 +704,8 @@
 			}
 
 			var update = response.update_data;
-			if (update && update.new_cids_order) {
+			var do_update = (update && update.new_cids_order) ? 1 : 0;
+			if (do_update) {
 				var root;
 				var pids = {};
 				for (var i = 0; i < update.new_cids_order.length; i++) {
@@ -737,32 +753,39 @@
 					loadNamedElement('comment_sig_' + cids[i]);
 					loadNamedElement('comment_otherdetails_' + cids[i]);
 					loadNamedElement('comment_sub_' + cids[i]);
+					loadNamedElement('comment_top_' + cids[i]);
 				}
 				setShortSubject(cids[i]);
 			}
 
-			if (update && update.new_cids_order) {
-				for (var i = 0; i < last_updated_comments.length; i++) {
-					var this_cid = last_updated_comments[i];
-					var this_id  = $('tree_' + this_cid);
-					if (this_id)
-						this_id.className = this_id.className.replace('newcomment', '');
+			if (do_update) {
+				if (newoldstuff) {
+					for (var i = 0; i < last_updated_comments.length; i++) {
+						var this_cid = last_updated_comments[i];
+						var this_id  = fetchEl('comment_top_' + this_cid);
+						if (this_id)
+							this_id.className = this_id.className.replace(' newcomment', ' oldcomment');
+					}
+					last_updated_comments = [];
+					last_updated_comments_index = -1;
 				}
-				last_updated_comments = [];
-					
+
 				for (var i = 0; i < update.new_cids_order.length; i++) {
 					var this_cid = update.new_cids_order[i];
-					if (placeholder_no_update[this_cid])
-						continue;
-					var mode = determineMode(this_cid);
-					updateDisplayMode(this_cid, mode, 1);
-					currents[displaymode[this_cid]]++;
-					updateComment(this_cid, mode);
+					if (!placeholder_no_update[this_cid]) {
+						var mode = determineMode(this_cid);
+						updateDisplayMode(this_cid, mode, 1);
+						currents[displaymode[this_cid]]++;
+						updateComment(this_cid, mode);
+					}
 
-					var this_id  = $('tree_' + this_cid);
-					this_id.className = this_id.className + ' newcomment';
-					last_updated_comments.push(this_cid);
+					var this_id  = fetchEl('comment_top_' + this_cid);
+					if (this_id) {
+						this_id.className = this_id.className.replace(' oldcomment', ' newcomment');
+						last_updated_comments.push(this_cid);
+					}
 				}
+
 				// later we may need to find a known point and scroll
 				// to it, but for now we don't want to do this -- pudge
 				//if (!commentIsInWindow(update.new_cids_order[0])) {
@@ -783,7 +806,25 @@
 			}
 
 			updateHiddens(cids);
+			if (do_update && highlight && last_updated_comments.length) {
+				last_updated_comments_index = last_updated_comments_index + 1;
+				setFocusComment(last_updated_comments[0], 1);
+			}
 			boxStatus(0);
+
+			if (0 && adTimerInsert) {
+				var tree = $('tree_' + adTimerInsert);
+				if (tree) {
+					var commtree = $('commtree_' + adTimerInsert);
+					var html = '<li id="comment_ad_' + adTimerInsert + '" class="inlinead"> SLASHDOT AD! </li>';
+					if (commtree) {
+						commtree.innerHTML = html + commtree.innerHTML;
+					} else {
+						tree.innerHTML = tree.innerHTML + '<ul id="commtree_' + adTimerInsert + '">' + html + '</ul>';
+					}
+				}
+				adTimerInsert = 0;
+			}
 		}
 	};
 
@@ -977,6 +1018,23 @@
 	//window.onbeforeunload = function () { savePrefs() };
 	//window.onunload = function () { savePrefs() };
 
+	var noshow_comments_hash = {};
+	for (var i = 0; i < noshow_comments.length; i++) { noshow_comments_hash[noshow_comments[i]] = 1 }
+	for (var cid in comments) {
+		if (!noshow_comments_hash[cid])
+			last_updated_comments.push(cid);
+	}
+	last_updated_comments = last_updated_comments.sort(function (a, b) { return (a - b) });
+
+	if (1 || user_is_admin) {
+		if (window.addEventListener) // DOM method for binding an event
+			window.addEventListener('keydown', keyHandler, false);
+		else if (window.attachEvent) // IE exclusive method for binding an event
+			window.attachEvent('onkeydown', keyHandler)
+		else if (document.getElementById) // support older modern browsers
+			document.body.onkeydown = keyHandler;
+	}
+
 	if (more_comments_num)
 		updateMoreNum(more_comments_num);
 	updateTotals();
@@ -1004,22 +1062,21 @@
 	alt_down   = 0;
 }
 
-function doModifiers () {
-	return;
-	var ev = window.event;
+function doModifiers (e) {
+	e = e || window.event;
 	shift_down = 0;
 	alt_down   = 0;
 
-	if (ev) {
-		if (ev.modifiers) {
+	if (e) {
+		if (e.modifiers) {
 			if (e.modifiers & Event.SHIFT_MASK)
 				shift_down = 1;
 			if (e.modifiers & Event.ALT_MASK)
 				alt_down = 1;
 		} else {
-			if (ev.shiftKey)
+			if (e.shiftKey)
 				shift_down = 1;
-			if (ev.altKey)
+			if (e.altKey)
 				alt_down = 1;
 		}
 	}
@@ -1541,9 +1598,124 @@
 
 
 
+var adTimerSecs;
+var adTimerClicks;
+var adTimerInsert;
+var adTimerSecsMax   = 10;
+var adTimerClicksMax = 5;
+var adTimerSeen = {};
 
+resetAdTimer();
 
+function checkAdTimer (cid) {
+	clickAdTimer();
 
+	if (cid && adTimerSeen[cid])
+		return 0;
+
+	var ad = 0;
+	if (adTimerClicks >= adTimerClicksMax)
+		ad = 1;
+	else {
+		var secs = getSeconds() - adTimerSecs;
+		if (secs >= adTimerSecsMax)
+			ad = 1;
+	}
+
+	if (!ad)
+		return 0;
+
+	if (cid)
+		adTimerSeen[cid] = 1;
+
+	resetAdTimer();
+	return 1;
+}
+
+function resetAdTimer () {
+	adTimerSecs   = getSeconds();
+	adTimerClicks = 0;
+}
+
+function clickAdTimer () {
+	adTimerClicks = adTimerClicks + 1;
+}
+
+function getSeconds () {
+	return new Date().getTime()/1000;
+}
+
+
+function setCurrentComment (cid) {
+	if (current_cid) {
+		var this_id  = fetchEl('comment_top_' + current_cid);
+		if (this_id) {
+			this_id.className = this_id.className.replace(' newcomment', ' oldcomment');
+			this_id.className = this_id.className.replace(' currcomment', '');
+		}
+	}
+
+
+	var this_id  = fetchEl('comment_top_' + cid);
+	if (this_id) {
+		this_id.className = this_id.className + ' currcomment';
+	}
+	current_cid = cid;
+}
+
+
+function keyHandler(e) {
+	e = e || window.event;
+
+	if (e) {
+		// don't handle for forms ... "type" should handle all our cases here
+		if (e.target && e.target.type)
+			return;
+
+		var c = e.keyCode;
+		if (c) {
+			var key = String.fromCharCode(c);
+			if (key == 'J' || key == 'K' || key == 'W' || key == 'S') {
+				if (last_updated_comments.length) {
+					var i = last_updated_comments_index;
+					var l = last_updated_comments.length - 1;
+					var update = 0;
+					if (key == 'J' || key == 'S') {
+						update = 1;
+						if (i <= 0)
+							i = l;
+						else
+							i = i - 1;
+					} else if (key == 'K' || key == 'W') {
+						if (i >= l) {
+							update = 2;
+							ajaxFetchComments(0, 1, '', 1);
+						} else {
+							update = 1;
+							i = i + 1;
+						}
+					}
+
+					if (update) {
+						doModifiers(e);
+						var this_shift_down = shift_down;
+						resetModifiers();
+						if (this_shift_down && current_cid) { // if shift, collapse previously selected
+							setFocusComment('-' + current_cid, 1);
+						}
+						if (update == 1) {
+							last_updated_comments_index = i;
+							setFocusComment(last_updated_comments[i], 1);
+						}
+					}
+				}
+			}
+		}
+	}
+
+}
+
+
 function dummyComment(cid) {
 	var html = '<li id="tree_--CID--" class="comment">\
 <div id="comment_status_--CID--" class="commentstatus"></div>\

Modified: slashjp/trunk/themes/slashcode/htdocs/images/comments2.js
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/images/comments2.js	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/htdocs/images/comments2.js	2007-10-31 05:54:43 UTC (rev 234)
@@ -81,7 +81,7 @@
 
 function renderCommentOneLine(cid) { 
 	var comment = comments[cid];
-	var retval = flipLink(cid, 'oneline') + '<a href="javascript:setFocusComment('+cid+');">';
+	var retval = flipLink(cid, 'oneline') + '<a href="#" onclick="setFocusComment('+cid+'); return false">';
 
 	retval = retval + comment['subject']+'</a> by '+comment['nickname'];
 
@@ -92,7 +92,7 @@
 
 function renderCommentFull(cid) {
 	var comment = comments[cid];
-	return '<div class="commentTop"> '+flipLink(cid,'full')+'<div class="title"><h4><a name="14620800">'+comment['subject']+'</a></h4>                    (Score: '+comment['points']+', XXXXX) </div> <div class="details">                    by '+comment['nickname']+ ' on '+comment['date']+' (<a href="javascript:setFocusComment('+cid+');">'+cid+'</a>) </div></div>            <div class="commentBody">  '+comment['comment']+'  </div>'+ replyTo(cid);
+	return '<div class="commentTop"> '+flipLink(cid,'full')+'<div class="title"><h4><a name="14620800">'+comment['subject']+'</a></h4>                    (Score: '+comment['points']+', XXXXX) </div> <div class="details">                    by '+comment['nickname']+ ' on '+comment['date']+' (<a href="#" onclick="setFocusComment('+cid+'); return false">'+cid+'</a>) </div></div>            <div class="commentBody">  '+comment['comment']+'  </div>'+ replyTo(cid);
 }
 
 function renderComment(cid, mode) {

Modified: slashjp/trunk/themes/slashcode/tasks/process_file_queue.pl
===================================================================
--- slashjp/trunk/themes/slashcode/tasks/process_file_queue.pl	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/tasks/process_file_queue.pl	2007-10-31 05:54:43 UTC (rev 234)
@@ -7,6 +7,7 @@
 use File::Path;
 use File::Temp;
 use File::Copy;
+use Image::Size;
 use Slash::Constants ':slashd';
 
 use strict;
@@ -28,6 +29,9 @@
 			$file_queue_cmds = $slashdb->getNextFileQueueCmds();
 		}
 		$cmd = shift @$file_queue_cmds;
+		if ($cmd->{blobid}) {
+			$cmd->{file} = blobToFile($cmd->{blobid});
+		}
 		if($cmd) {
 			handleFileCmd($cmd);
 		}
@@ -39,7 +43,36 @@
 sub handleFileCmd {
 	my($cmd) = @_;
 	my $slashdb = getCurrentDB();
+	if ($cmd->{action} eq "thumbnails") {
+		slashdLog("Creating Thumbnails");
+		my $files = uploadFile($cmd);
+		$files ||= [];
+		slashdLog("after upload file");
+		foreach (@$files) {
+			slashdLog("thumbing $_");
+			my ($name, $path) = fileparse($_);
+			my ($namebase, $suffix) = $name =~ /^(\w+\-\d+)\.(\w+)$/;
+			my $thumb = $namebase . "-thumb." . $suffix;
+			my $thumbsm = $namebase . "-thumbsm." . $suffix;
+			slashdLog("About to create thumb $path$thumb");
+			system("convert -size 100x100 $path$name $path$thumb");
+			my $data = {
+				stoid => $cmd->{stoid},
+				name => $thumb
+			};
+			addStoryFile($data, $path);
+
+			slashdLog("About to create thumbsms $path$thumbsm");
+			system("convert -size 50x50 $path$name $path$thumbsm");
+			$data = {
+				stoid => $cmd->{stoid},
+				name => $thumbsm
+			};
+			addStoryFile($data, $path);
+		}
+	}
 	if ($cmd->{action} eq "upload") {
+		slashdLog("handling upload\n");
 		uploadFile($cmd);
 	}
 	$slashdb->deleteFileQueueCmd($cmd->{fqid});
@@ -78,37 +111,57 @@
     return $file =~ /^\/tmp\/upload\/\w+(\.\w+)?$/
 }
 
+sub blobToFile {
+	my($blobid) = @_;
+	my $blob = getObject("Slash::Blob");
+	my $blob_ref = $blob->get($blobid);
+	my($suffix) = $blob_ref->{filename} =~ /(\.\w+$)/;
+	$suffix = lc($suffix);
+	my ($ofh, $tmpname) = mkstemps("/tmp/upload/fileXXXXXX", $suffix );
+	print $ofh $blob_ref->{data};
+	close $ofh;
+	return $tmpname;
+}
+
 sub uploadFile {
 	my($cmd) = @_;
 	my @suffixlist = ();
 	my $slashdb = getCurrentDB();
 	my $story = $slashdb->getStory($cmd->{stoid});
+	my @files;
+
+	my $file = $cmd->{file};
+
 	if ($story->{sid}) {
 		my $destpath = getStoryFileDir($story->{sid});
 		makeFileDir($destpath);
 		my ($prefix) = $story->{sid} =~ /^\d\d\/\d\d\/\d\d\/(\d+)$/;
 		
-		my ($name,$path,$suffix) = fileparse($cmd->{file}, @ suffixlist);
+		my ($name,$path,$suffix) = fileparse($file, @ suffixlist);
 	        ($suffix) = $name =~ /(\.\w+)$/;
-		if (verifyFileLocation($cmd->{file})) {
-			my $destfile = copyFileToLocation($cmd->{file}, $destpath, $prefix);
+		if (verifyFileLocation($file)) {
+			my $destfile = copyFileToLocation($file, $destpath, $prefix);
+			push @files, $destfile if $destfile;
 			my $name = fileparse($destfile);
 			my $data = {
 				stoid => $cmd->{stoid},
 				name => $name
 			};
 
-			$slashdb->addStoryStaticFile($data);
+			addStoryFile($data, "$destpath/");
 		}
 
+
 	}
 	if ($cmd->{fhid}) {
 		my $destpath = getFireHoseFileDir($cmd->{fhid});
 		makeFileDir($destpath);
 		my $numdir = sprintf("%09d",$cmd->{fhid});
 		my ($prefix) = $numdir =~ /\d\d\d\d\d\d(\d\d\d)/;
-		copyFileToLocation($cmd->{file}, $destpath, $prefix);
+		my $destfile = copyFileToLocation($cmd->{file}, $destpath, $prefix);
+		push @files, $destfile if $destfile;
 	}
+	return \@files;
 }
 
 sub copyFileToLocation {
@@ -139,4 +192,16 @@
 	return $ret_val;
 }
 
+sub addStoryFile {
+	my($data, $path) = @_;
+	print "Add story file\n";
+	my $slashdb = getCurrentDB();
+	slashdLog("addStoryFile $path $data->{name}");
+	if ($data->{name} =~ /\.(png|gif|jpg)$/i && $path) {
+		($data->{width}, $data->{height}) = imgsize("$path$data->{name}");
+		slashdLog("addStoryFile $data->{width} $data->{height}");
+	}
+	$slashdb->addStoryStaticFile($data);
+}
+
 1;

Modified: slashjp/trunk/themes/slashcode/templates/dispComment;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/dispComment;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/dispComment;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -27,14 +27,14 @@
 <div id="comment_status_[% cid %]" class="commentstatus"></div>
 <div id="comment_[% cid %]"[% IF discussion2 %] class="[% class %]"[% END %]>
 [% END; IF !options.noshow %]
-	<div class="commentTop">
+	<div id="comment_top_[% cid %]" class="commentTop newcomment">
 		<div class="title">
 			[% IF discussion2 %]
-			<h4><a id="comment_link_[% cid %]" name="comment_link_[% cid %]" href="[% gSkin.rootdir %]/comments.pl?sid=[% sid %]&amp;cid=[% cid %]" onclick="return setFocusComment([% cid %])">[% subject %]</a></h4>
+			<h4><a id="comment_link_[% cid %]" name="comment_link_[% cid %]" href="[% gSkin.rootdir %]/comments.pl?sid=[% sid %]&amp;cid=[% cid %]" onclick="return setFocusComment([% cid %])">[% subject %]</a>
 			[% ELSE %]
-			<h4><a name="[% cid %]">[% subject %]</a></h4>
+			<h4><a name="[% cid %]">[% subject %]</a>
 			[%- END %]
-			[% UNLESS user.noscores %]<span id="comment_score_[% cid %]" class="score">(Score:[% IF points.length; points; ELSE; "?"; END %][% IF reasons && reason %], [% reasons.$reason.name %][% END %])</span>[% END %]
+			[% UNLESS user.noscores %]<span id="comment_score_[% cid %]" class="score">(Score:[% IF points.length; points; ELSE; "?"; END %][% IF reasons && reason %], [% reasons.$reason.name %][% END %])</span>[% END %]</h4>
 		</div>
 		<div class="details">
 			by

Modified: slashjp/trunk/themes/slashcode/templates/dispCommentDetails;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/dispCommentDetails;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/dispCommentDetails;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -26,7 +26,7 @@
 				cid     => cid,
 				subject => ('#' _ cid),
 				subject_only => 1
-			}, 1) %])[% END %]
+			}, 1, { noextra => 1 }) %])[% END %]
 			<small>
 			[% has_homepage = homepage && homepage.length > 8;
 				has_journal = journal_last_entry_date.search('[1-9]');

Modified: slashjp/trunk/themes/slashcode/templates/dispStory;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/dispStory;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/dispStory;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -151,7 +151,7 @@
 	[% title %]  [% IF story.commentcount %][% IF thresh_commentcount && story.commentcount != thresh_commentcount %][% thresh_commentcount %] of [% END %][% story.commentcount %] comment[% IF story.commentcount > 1 %]s[% END %][% END %] 
 	[% IF user.is_admin %]<a href="[% gSkin.rootdir -%]/admin.pl?op=edit&amp;sid=[% story.sid %]">(edit)</a>[% END %]
 	[% IF expandable %]
-	<a href="javascript:toggleIntro('intro-[% story.stoid %]','togglest-[% story.stoid %]');"><span id="togglest-[% story.stoid %]">[+]</span></a>
+	<a href="#" onclick="toggleIntro('intro-[% story.stoid %]','togglest-[% story.stoid %]'); return false"><span id="togglest-[% story.stoid %]">[+]</span></a>
 	[% END %]
 	[% IF getintro %]
 	<div class="introhide" id="intro-[% story.stoid %]">

Modified: slashjp/trunk/themes/slashcode/templates/edit_comment;comments;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/edit_comment;comments;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/edit_comment;comments;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -237,7 +237,8 @@
 				</ul>
 
 				<p>
-					Problems regarding accounts or comment posting should be sent to <a href="mailto:[% constants.adminmail | strip_attribute %]">[% constants.siteadmin_name %]</a>.
+					If you are having a problem with accounts or comment posting,
+					please <a href="mailto:[% constants.adminmail | strip_attribute %]">yell for help</a>.
 				</p>
 			</div>	
 		</fieldset>

Modified: slashjp/trunk/themes/slashcode/templates/ipid_display;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/ipid_display;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/ipid_display;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -12,7 +12,7 @@
 __name__
 ipid_display
 __template__
-<br>IPID:
+IPID:
 <a href="[%
 gSkin.rootdir %]/users.pl?op=userinfo&amp;userfield=[%
 data.ipid %]&amp;fieldname=ipid">[% data.ipid_vis %]</a>&nbsp;&nbsp;SubnetID:

Modified: slashjp/trunk/themes/slashcode/templates/linkComment;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/linkComment;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/linkComment;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -22,8 +22,8 @@
 __name__
 linkComment
 __template__
-<a href="[% gSkin.rootdir %]/comments.pl?sid=[% sid 
-                                              %]&amp;op=[% op;
+<a href="[% gSkin.rootdir %]/comments.pl?sid=[% sid;
+IF op.defined                                 %]&amp;op=[% op; END;
 IF threshold.defined                          %]&amp;threshold=[% threshold; END;
 IF commentsort.defined                        %]&amp;commentsort=[% commentsort; END;
 IF mode.defined                               %]&amp;mode=[% mode; END;

Modified: slashjp/trunk/themes/slashcode/templates/messages;users;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/messages;users;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/messages;users;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -119,8 +119,8 @@
 
 [% CASE 'tilded_box_msg' %]
 	<p>If you find a problem, or have a reasonable suggestion
-	for new RSS feeds, please contact
-	<a href="mailto:[% constants.adminmail | strip_attribute %]">[% constants.siteadmin_name %]</a>.
+	for new RSS feeds, please
+	<a href="mailto:[% constants.adminmail | strip_attribute %]">email us</a>.
 
 	<p></td></tr></table>
 
@@ -130,11 +130,8 @@
 [% realemail | strip_literal %].
 
 If this is not correct, if you did not request this change,
-please contact the site administrator immediately.
+please email us immediately at [% constants.adminmail %].
 
-	[% constants.siteadmin_name %]
-	[% constants.adminmail %]
-
 [% CASE 'saveuseradmin_saveduser' %]
 	Saved [% field %] [% id %] user settings
 

Modified: slashjp/trunk/themes/slashcode/templates/printCommComments;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/printCommComments;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/printCommComments;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -101,7 +101,17 @@
 	[% lcp %]
 
 [% IF discussion2 && !cid %]
-<div class="prev-next"><a href="javascript:ajaxFetchComments(0,1)"><span id="more_comments_num_a" class="hide">Check for more</span></a></div>
+<div class="prev-next"><a href="#" onclick="ajaxFetchComments(0,1); return false"><span id="more_comments_num_a" class="hide">Check for more</span></a>
+	[% UNLESS user.state.discussion_archived || user.state.discussion_future_nopost %]
+		| [% Slash.linkComment({
+			sid          => sid,
+			cid          => cid,
+			op           => 'reply',
+			subject      => 'Reply',
+			subject_only => 1
+		});
+	END %]
+</div>
 [% END %]
 
 [% IF moderate_form %]

Modified: slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -178,9 +178,9 @@
 				[% END %]
 		<span class="ccw-header-links">
     [% IF discussion2 && !cid && !pid %]
-        <a href="javascript:ajaxFetchComments(0,1)"><span id="more_comments_num_b"></span> More</a> | 
+        <a href="#" onclick="ajaxFetchComments(0,1); return false"><span id="more_comments_num_b"></span> More</a> | 
     [% END; IF user.is_admin && user.d2prefs_debug %]
-        <a href="javascript:showPrefs('reading')">Prefs</a>
+        <a href="#" onclick="showPrefs('reading'); return false">Prefs</a>
     [% ELSIF user.is_anon;
    	PROCESS userlogin_cover
    		return_url = gSkin.rootdir _ '/comments.pl?sid=' _ sid %]
@@ -191,14 +191,13 @@
 
 		[% UNLESS user.state.discussion_archived || user.state.discussion_future_nopost %]
 			| [% Slash.linkComment({
-				sid => sid,
-				cid => cid,
-				op  => 'reply',
-				subject => 'Reply',
+				sid          => sid,
+				cid          => cid,
+				op           => 'reply',
+				subject      => 'Reply',
 				subject_only => 1
-				});
-			%]
-    [% END %]
+			}) %]
+		[% END %]
 		</span>
 		<span title="Toggle window location" onclick="toggleDisplayOptions()" class="close">/</span>
 				</h4>
@@ -225,18 +224,18 @@
             <div id="ccw-full-panel" class="ccw-panel">
               <div class="ccw-panel-border"></div>
               <div id="ccw-full-count-pos" class="ccw-core-pos ccw-count-pos">
-                <span id="ccw-full-count-text" class="ccw-count-text"><span id="currentFull"></span><span id="ccw-full-phrase"> Full</span></span>
+                <span id="ccw-full-count-text" class="ccw-count-text"><span id="currentFull"></span><span id="ccw-full-phrase">&nbsp;Full</span></span>
               </div>
             </div>
             <div id="ccw-abbr-panel" class="ccw-panel">
               <div class="ccw-panel-border"></div>
               <div id="ccw-abbr-count-pos" class="ccw-core-pos ccw-count-pos">
-                <span id="ccw-abbr-count-text" class="ccw-count-text"><span id="currentOneline"></span><span id="ccw-abbr-phrase"> Abbreviated</span></span>
+                <span id="ccw-abbr-count-text" class="ccw-count-text"><span id="currentOneline"></span><span id="ccw-abbr-phrase">&nbsp;Abbreviated</span></span>
               </div>
             </div>
             <div id="ccw-hide-panel" class="ccw-panel">
               <div id="ccw-hide-count-pos" class="ccw-core-pos ccw-count-pos">
-                <span id="ccw-hide-count-text" class="ccw-count-text"><span id="currentHidden"></span><span id="ccw-hide-phrase"> Hidden</span></span>
+                <span id="ccw-hide-count-text" class="ccw-count-text"><span id="currentHidden"></span><span id="ccw-hide-phrase">&nbsp;Hidden</span></span>
               </div>
             </div>
           </div>
@@ -264,9 +263,9 @@
 		</div>
 		<div class="commentControlFooter">
     [% IF discussion2 && !cid && !pid %]
-        <a href="javascript:ajaxFetchComments(0,1)"><span id="more_comments_num_c"></span> More</a> | 
+        <a href="#" onclick="ajaxFetchComments(0,1); return false"><span id="more_comments_num_c"></span> More</a> | 
     [% END; IF user.is_admin && user.d2prefs_debug %]
-        <a href="javascript:showPrefs('reading')">Prefs</a>
+        <a href="#" onclick="showPrefs('reading'); return false">Prefs</a>
     [% ELSIF user.is_anon;
    	PROCESS userlogin_cover
    		return_url = gSkin.rootdir _ '/comments.pl?sid=' _ sid %]
@@ -276,13 +275,12 @@
     [% END %]
 		[% UNLESS user.state.discussion_archived || user.state.discussion_future_nopost %]
 			| [% Slash.linkComment({
-				sid => sid,
-				cid => cid,
-				op  => 'reply',
-				subject => 'Reply',
+				sid          => sid,
+				cid          => cid,
+				op           => 'reply',
+				subject      => 'Reply',
 				subject_only => 1
-				});
-			%]
+			}) %]
 		[% END %]
 		</div>
 		<div id="commentControlBoxStatus" class="hide"><b>Loading ... Please wait.</b></div>
@@ -296,7 +294,7 @@
 <div id="modal_cover" style="display:none" onclick="hide_modal_box()"></div>
 <div id="modal_box" style="display:none">
         <div class="generaltitle" >
-                <div class="title"><h3><div id="preference_title"></div> <a href="javascript:hide_modal_box()"><img src="[% gSkin.imagedir %]/images/sic_close.png" alt="Close"></a></h3></div>
+                <div class="title"><h3><div id="preference_title"></div> <a href="#" onclick="hide_modal_box(); return false"><img src="[% gSkin.imagedir %]/images/sic_close.png" alt="Close"></a></h3></div>
         </div>
         <div id="modal_box_content">Content here</div>
 </div>

Modified: slashjp/trunk/themes/slashcode/templates/userlogin_cover;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/userlogin_cover;misc;default	2007-10-31 05:43:45 UTC (rev 233)
+++ slashjp/trunk/themes/slashcode/templates/userlogin_cover;misc;default	2007-10-31 05:54:43 UTC (rev 234)
@@ -18,7 +18,7 @@
 <div id="login_box" style="display:none">
 [% PROCESS titlebar
 	title => "Please Log In to Continue" _
-		'<a href="javascript:hide_login_box()" class="close" title="Close this box"><img id="login_box_close" src="' _
+		'<a href="#" onclick="hide_login_box(); return false" class="close" title="Close this box"><img id="login_box_close" src="' _
 		gSkin.imagedir _ '/images/sic_close.png" alt="Close"></a>'
 %]
 <div id="login_box_content">


Slashdotjp-dev メーリングリストの案内
アーカイブの一覧に戻る