[Slashdotjp-dev 1214] [742] merged from upstream/2.5.0.218 branch

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2008年 9月 9日 (火) 22:07:58 JST


Revision: 742
          http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=slashdotjp&view=rev&rev=742
Author:   tach
Date:     2008-09-09 22:07:58 +0900 (Tue, 09 Sep 2008)

Log Message:
-----------
merged from upstream/2.5.0.218 branch

Modified Paths:
--------------
    slashjp/trunk/Bundle/Makefile.PL
    slashjp/trunk/Bundle/Slash.pm
    slashjp/trunk/INSTALL
    slashjp/trunk/Makefile
    slashjp/trunk/Slash/Apache/Apache.pm
    slashjp/trunk/Slash/Apache/Banlist/Banlist.pm
    slashjp/trunk/Slash/Apache/Banlist/Makefile.PL
    slashjp/trunk/Slash/Apache/Log/Log.pm
    slashjp/trunk/Slash/Apache/Log/Makefile.PL
    slashjp/trunk/Slash/Apache/TemplatePages/Makefile.PL
    slashjp/trunk/Slash/Apache/TemplatePages/TemplatePages.pm
    slashjp/trunk/Slash/Apache/User/PasswordSalt/Makefile.PL
    slashjp/trunk/Slash/Apache/User/PasswordSalt/PasswordSalt.pm
    slashjp/trunk/Slash/Apache/User/User.pm
    slashjp/trunk/Slash/Client/Makefile.PL
    slashjp/trunk/Slash/Client/lib/Slash/Client/Journal.pm
    slashjp/trunk/Slash/Client/lib/Slash/Client.pm
    slashjp/trunk/Slash/Constants/Constants.pm
    slashjp/trunk/Slash/Constants/Makefile.PL
    slashjp/trunk/Slash/Custom/ApacheCompress/ApacheCompress.pm
    slashjp/trunk/Slash/Custom/ApacheCompress/Makefile.PL
    slashjp/trunk/Slash/Custom/ApacheRegistryFilter/ApacheRegistryFilter.pm
    slashjp/trunk/Slash/Custom/ApacheRegistryFilter/Makefile.PL
    slashjp/trunk/Slash/Custom/ApacheSSI/ApacheSSI.pm
    slashjp/trunk/Slash/Custom/ApacheSSI/Makefile.PL
    slashjp/trunk/Slash/Custom/Bulkmail/Makefile.PL
    slashjp/trunk/Slash/Custom/ParUserAgent/Makefile.PL
    slashjp/trunk/Slash/Custom/ParUserAgent/ParUserAgent.pm
    slashjp/trunk/Slash/DB/DB.pm
    slashjp/trunk/Slash/DB/Makefile.PL
    slashjp/trunk/Slash/DB/MySQL/Makefile.PL
    slashjp/trunk/Slash/DB/MySQL/MySQL.pm
    slashjp/trunk/Slash/DB/Oracle/Makefile.PL
    slashjp/trunk/Slash/DB/Oracle/Oracle.pm
    slashjp/trunk/Slash/DB/PostgreSQL/Makefile.PL
    slashjp/trunk/Slash/DB/PostgreSQL/PostgreSQL.pm
    slashjp/trunk/Slash/DB/Static/Makefile.PL
    slashjp/trunk/Slash/DB/Static/MySQL/Makefile.PL
    slashjp/trunk/Slash/DB/Static/MySQL/MySQL.pm
    slashjp/trunk/Slash/DB/Static/Oracle/Makefile.PL
    slashjp/trunk/Slash/DB/Static/Oracle/Oracle.pm
    slashjp/trunk/Slash/DB/Static/PostgreSQL/Makefile.PL
    slashjp/trunk/Slash/DB/Static/PostgreSQL/PostgreSQL.pm
    slashjp/trunk/Slash/DB/Utility/Makefile.PL
    slashjp/trunk/Slash/DB/Utility/Utility.pm
    slashjp/trunk/Slash/Display/Display.pm
    slashjp/trunk/Slash/Display/Makefile.PL
    slashjp/trunk/Slash/Display/Plugin/Makefile.PL
    slashjp/trunk/Slash/Display/Plugin/Plugin.pm
    slashjp/trunk/Slash/Display/Provider/Makefile.PL
    slashjp/trunk/Slash/Display/Provider/Provider.pm
    slashjp/trunk/Slash/Hook/Hook.pm
    slashjp/trunk/Slash/Hook/Makefile.PL
    slashjp/trunk/Slash/Hook/Sample/Makefile.PL
    slashjp/trunk/Slash/Hook/Sample/Sample.pm
    slashjp/trunk/Slash/Install/Install.pm
    slashjp/trunk/Slash/Install/Makefile.PL
    slashjp/trunk/Slash/Makefile.PL
    slashjp/trunk/Slash/Slash.pm
    slashjp/trunk/Slash/Slashboxes/Makefile.PL
    slashjp/trunk/Slash/Slashboxes/Slashboxes.pm
    slashjp/trunk/Slash/Test/Makefile.PL
    slashjp/trunk/Slash/Test/Test.pm
    slashjp/trunk/Slash/Utility/Access/Access.pm
    slashjp/trunk/Slash/Utility/Access/Makefile.PL
    slashjp/trunk/Slash/Utility/Anchor/Anchor.pm
    slashjp/trunk/Slash/Utility/Anchor/Makefile.PL
    slashjp/trunk/Slash/Utility/Comments/Comments.pm
    slashjp/trunk/Slash/Utility/Comments/Makefile.PL
    slashjp/trunk/Slash/Utility/Data/Data.pm
    slashjp/trunk/Slash/Utility/Data/Makefile.PL
    slashjp/trunk/Slash/Utility/Display/Display.pm
    slashjp/trunk/Slash/Utility/Display/Makefile.PL
    slashjp/trunk/Slash/Utility/Environment/Environment.pm
    slashjp/trunk/Slash/Utility/Environment/Makefile.PL
    slashjp/trunk/Slash/Utility/Makefile.PL
    slashjp/trunk/Slash/Utility/System/Makefile.PL
    slashjp/trunk/Slash/Utility/System/System.pm
    slashjp/trunk/Slash/Utility/Utility.pm
    slashjp/trunk/Slash/XML/Atom/Atom.pm
    slashjp/trunk/Slash/XML/Atom/Makefile.PL
    slashjp/trunk/Slash/XML/Makefile.PL
    slashjp/trunk/Slash/XML/RSS/Makefile.PL
    slashjp/trunk/Slash/XML/RSS/RSS.pm
    slashjp/trunk/Slash/XML/XML.pm
    slashjp/trunk/bin/runtask
    slashjp/trunk/debian/changelog
    slashjp/trunk/docs/INSTALL.pod
    slashjp/trunk/plugins/Admin/Admin/Makefile.PL
    slashjp/trunk/plugins/Admin/Admin/PopupTree.pm
    slashjp/trunk/plugins/Admin/Admin.pm
    slashjp/trunk/plugins/Admin/Makefile.PL
    slashjp/trunk/plugins/Admin/admin.pl
    slashjp/trunk/plugins/Admin/templates/commentlog;admin;default
    slashjp/trunk/plugins/Admin/templates/data;admin;default
    slashjp/trunk/plugins/Admin/templates/editStory;admin;default
    slashjp/trunk/plugins/Admin/templates/peer_weights;admin;default
    slashjp/trunk/plugins/Admin/templates/static_files;admin;default
    slashjp/trunk/plugins/Ajax/Makefile.PL
    slashjp/trunk/plugins/Ajax/PLUGIN
    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/nodnix.js
    slashjp/trunk/plugins/Ajax/htdocs/images/sd_autocomplete.js
    slashjp/trunk/plugins/Ajax/htdocs/images/sd_calendar.js
    slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js
    slashjp/trunk/plugins/Ajax/htdocs/images/slashbox.js
    slashjp/trunk/plugins/Ajax/htdocs/preferences.pl
    slashjp/trunk/plugins/Ajax/templates/edit_comment;ajax;default
    slashjp/trunk/plugins/Ajax/templates/hc_comment;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_admin;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_authors;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_home;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_main;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_sectional;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_slashboxes;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_user;ajax;default
    slashjp/trunk/plugins/Blob/Blob.pm
    slashjp/trunk/plugins/Blob/Makefile.PL
    slashjp/trunk/plugins/BlockProxyNet/Makefile.PL
    slashjp/trunk/plugins/Bookmark/Bookmark.pm
    slashjp/trunk/plugins/Bookmark/Makefile.PL
    slashjp/trunk/plugins/Bookmark/bookmark.pl
    slashjp/trunk/plugins/Console/Console.pm
    slashjp/trunk/plugins/Console/Makefile.PL
    slashjp/trunk/plugins/Console/console.pl
    slashjp/trunk/plugins/Console/templates/display;console;default
    slashjp/trunk/plugins/Daypass/Daypass.pm
    slashjp/trunk/plugins/Daypass/Makefile.PL
    slashjp/trunk/plugins/Dilemma/Dilemma.pm
    slashjp/trunk/plugins/Dilemma/Makefile.PL
    slashjp/trunk/plugins/Email/Email.pm
    slashjp/trunk/plugins/Email/Makefile.PL
    slashjp/trunk/plugins/Events/Events.pm
    slashjp/trunk/plugins/Events/Makefile.PL
    slashjp/trunk/plugins/FAQ/Makefile.PL
    slashjp/trunk/plugins/FAQSlashdot/Makefile.PL
    slashjp/trunk/plugins/FAQSlashdot/faq/badges.shtml
    slashjp/trunk/plugins/FAQSlashdot/faq/editorial.shtml
    slashjp/trunk/plugins/FAQSlashdot/faq/firehose.shtml
    slashjp/trunk/plugins/FAQSlashdot/faq/index.shtml
    slashjp/trunk/plugins/FireHose/FireHose.pm
    slashjp/trunk/plugins/FireHose/Makefile.PL
    slashjp/trunk/plugins/FireHose/PLUGIN
    slashjp/trunk/plugins/FireHose/firehose.css
    slashjp/trunk/plugins/FireHose/firehose.pl
    slashjp/trunk/plugins/FireHose/firehose_backend.pl
    slashjp/trunk/plugins/FireHose/firehose_get_thumbnails.pl
    slashjp/trunk/plugins/FireHose/firehose_reject_old.pl
    slashjp/trunk/plugins/FireHose/mysql_dump.sql
    slashjp/trunk/plugins/FireHose/mysql_schema.sql
    slashjp/trunk/plugins/FireHose/set_color_ranges.pl
    slashjp/trunk/plugins/FireHose/templates/admin_extras;misc;default
    slashjp/trunk/plugins/FireHose/templates/adv_pref_firehose;misc;default
    slashjp/trunk/plugins/FireHose/templates/data;firehose;default
    slashjp/trunk/plugins/FireHose/templates/daybreak;firehose;default
    slashjp/trunk/plugins/FireHose/templates/dispFireHose;firehose;default
    slashjp/trunk/plugins/FireHose/templates/dispTopicFireHose;misc;default
    slashjp/trunk/plugins/FireHose/templates/fhadvprefpane;misc;default
    slashjp/trunk/plugins/FireHose/templates/fireHoseForm;misc;default
    slashjp/trunk/plugins/FireHose/templates/firehose_options;misc;default
    slashjp/trunk/plugins/FireHose/templates/firehose_pages;misc;default
    slashjp/trunk/plugins/FireHose/templates/firehose_tabs;misc;default
    slashjp/trunk/plugins/FireHose/templates/firehose_tags_top;misc;default
    slashjp/trunk/plugins/FireHose/templates/firehose_usage;misc;default
    slashjp/trunk/plugins/FireHose/templates/formatHoseIntro;misc;default
    slashjp/trunk/plugins/FireHose/templates/formatHoseTitle;misc;default
    slashjp/trunk/plugins/FireHose/templates/list;firehose;default
    slashjp/trunk/plugins/FireHose/templates/nodnix_menus;firehose;default
    slashjp/trunk/plugins/FireHose/templates/paginate;firehose;default
    slashjp/trunk/plugins/FireHose/templates/portalmap;firehose;default
    slashjp/trunk/plugins/FireHose/templates/reject;firehose;default
    slashjp/trunk/plugins/FireHose/templates/reject_firehose;misc;default
    slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivadmin;misc;default
    slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivtagbox;misc;default
    slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivuser;misc;default
    slashjp/trunk/plugins/FireHose/templates/tagsnodnixuser;misc;default
    slashjp/trunk/plugins/FireHose/templates/view;firehose;default
    slashjp/trunk/plugins/Hof/Hof.pm
    slashjp/trunk/plugins/Hof/Makefile.PL
    slashjp/trunk/plugins/HumanConf/HumanConf.pm
    slashjp/trunk/plugins/HumanConf/Makefile.PL
    slashjp/trunk/plugins/HumanConf/Static/Makefile.PL
    slashjp/trunk/plugins/HumanConf/Static/Static.pm
    slashjp/trunk/plugins/HumanConf/hc_maintain_pool.pl
    slashjp/trunk/plugins/HumanConf/mysql_dump
    slashjp/trunk/plugins/Journal/Journal.pm
    slashjp/trunk/plugins/Journal/Makefile.PL
    slashjp/trunk/plugins/Login/login.pl
    slashjp/trunk/plugins/Login/templates/data;login;default
    slashjp/trunk/plugins/Messages/DB/MySQL/Makefile.PL
    slashjp/trunk/plugins/Messages/DB/MySQL/MySQL.pm
    slashjp/trunk/plugins/Messages/Makefile.PL
    slashjp/trunk/plugins/Messages/Messages.pm
    slashjp/trunk/plugins/Messages/templates/storynew;messages;default
    slashjp/trunk/plugins/Messages/templates/storynew_msg_subj;messages;default
    slashjp/trunk/plugins/Metamod/Makefile.PL
    slashjp/trunk/plugins/Metamod/Metamod.pm
    slashjp/trunk/plugins/Metamod/PLUGIN
    slashjp/trunk/plugins/Metamod/Static/Makefile.PL
    slashjp/trunk/plugins/Metamod/Static/Static.pm
    slashjp/trunk/plugins/Metamod/metamod.pl
    slashjp/trunk/plugins/Metamod/mysql_dump.sql
    slashjp/trunk/plugins/Metamod/mysql_schema.sql
    slashjp/trunk/plugins/Metamod/process_metamod.pl
    slashjp/trunk/plugins/Metamod/templates/data;metamod;default
    slashjp/trunk/plugins/Metamod/templates/dispTheComments;metamod;default
    slashjp/trunk/plugins/Metamod/templates/isEligible;metamod;default
    slashjp/trunk/plugins/Moderation/Makefile.PL
    slashjp/trunk/plugins/Moderation/Moderation.pm
    slashjp/trunk/plugins/Moderation/PLUGIN
    slashjp/trunk/plugins/Moderation/moderate.pl
    slashjp/trunk/plugins/Moderation/mysql_dump.sql
    slashjp/trunk/plugins/Moderation/mysql_schema.sql
    slashjp/trunk/plugins/Moderation/process_moderation.pl
    slashjp/trunk/plugins/NewsVac/Makefile.PL
    slashjp/trunk/plugins/NewsVac/NewsVac.pm
    slashjp/trunk/plugins/OAI/Makefile.PL
    slashjp/trunk/plugins/OAI/OAI.pm
    slashjp/trunk/plugins/Page/Makefile.PL
    slashjp/trunk/plugins/Page/Page.pm
    slashjp/trunk/plugins/PollBooth/Makefile.PL
    slashjp/trunk/plugins/PollBooth/PollBooth.pm
    slashjp/trunk/plugins/PollBooth/ResKey.pm
    slashjp/trunk/plugins/PollBooth/templates/pollplug;misc;default
    slashjp/trunk/plugins/Rating/Makefile.PL
    slashjp/trunk/plugins/Rating/Rating.pm
    slashjp/trunk/plugins/Relocate/Makefile.PL
    slashjp/trunk/plugins/Relocate/Relocate.pm
    slashjp/trunk/plugins/Remarks/Makefile.PL
    slashjp/trunk/plugins/Remarks/Remarks.pm
    slashjp/trunk/plugins/ResKey/Makefile.PL
    slashjp/trunk/plugins/ResKey/ResKey/Checks/ACL.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/AnonNoPost.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoPost.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoPostAnon.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoSubmit.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/Spammer.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/Duration.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/HumanConf.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/Moderate.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/Post.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/ProxyScan.pm
    slashjp/trunk/plugins/ResKey/ResKey/Checks/User.pm
    slashjp/trunk/plugins/ResKey/ResKey/Key.pm
    slashjp/trunk/plugins/ResKey/ResKey.pm
    slashjp/trunk/plugins/ResKey/mysql_dump.sql
    slashjp/trunk/plugins/SOAP/Makefile.PL
    slashjp/trunk/plugins/SOAP/SOAP.pm
    slashjp/trunk/plugins/ScheduleShifts/Makefile.PL
    slashjp/trunk/plugins/ScheduleShifts/ScheduleShifts.pm
    slashjp/trunk/plugins/Search/Makefile.PL
    slashjp/trunk/plugins/Search/SOAP/Makefile.PL
    slashjp/trunk/plugins/Search/SOAP/SOAP.pm
    slashjp/trunk/plugins/Search/Search.pm
    slashjp/trunk/plugins/SearchToo/Makefile.PL
    slashjp/trunk/plugins/SearchToo/SearchToo/Classic.pm
    slashjp/trunk/plugins/SearchToo/SearchToo/Indexer.pm
    slashjp/trunk/plugins/SearchToo/SearchToo/Kinosearch.pm
    slashjp/trunk/plugins/SearchToo/SearchToo/Plucene.pm
    slashjp/trunk/plugins/SearchToo/SearchToo.pm
    slashjp/trunk/plugins/SearchToo/schema.sql
    slashjp/trunk/plugins/SearchToo/search_index.pl
    slashjp/trunk/plugins/Stats/Makefile.PL
    slashjp/trunk/plugins/Stats/PLUGIN
    slashjp/trunk/plugins/Stats/Stats.pm
    slashjp/trunk/plugins/Stats/Writer/Makefile.PL
    slashjp/trunk/plugins/Stats/Writer/Writer.pm
    slashjp/trunk/plugins/Stats/adminmail.pl
    slashjp/trunk/plugins/Stats/mysql_dump
    slashjp/trunk/plugins/Stats/stats.pl
    slashjp/trunk/plugins/Stats/templates/display;adminmail;default
    slashjp/trunk/plugins/Submit/mysql_schema.sql
    slashjp/trunk/plugins/Submit/submit.pl
    slashjp/trunk/plugins/Submit/templates/displayForm;submit;default
    slashjp/trunk/plugins/Subscribe/Makefile.PL
    slashjp/trunk/plugins/Subscribe/Static/Makefile.PL
    slashjp/trunk/plugins/Subscribe/Static/Static.pm
    slashjp/trunk/plugins/Subscribe/Subscribe.pm
    slashjp/trunk/plugins/TagDataView/Makefile.PL
    slashjp/trunk/plugins/TagDataView/PLUGIN
    slashjp/trunk/plugins/TagDataView/TagDataView.pm
    slashjp/trunk/plugins/TagDataView/mysql_schema.sql
    slashjp/trunk/plugins/TagDataView/tagdataview.pl
    slashjp/trunk/plugins/TagDataView/templates/display;tagdataview;default
    slashjp/trunk/plugins/TagModeration/Makefile.PL
    slashjp/trunk/plugins/TagModeration/PLUGIN
    slashjp/trunk/plugins/TagModeration/TagModeration.pm
    slashjp/trunk/plugins/TagModeration/mysql_dump.sql
    slashjp/trunk/plugins/TagModeration/mysql_schema.sql
    slashjp/trunk/plugins/TagModeration/process_tagmoderation.pl
    slashjp/trunk/plugins/Tags/Clout/Describe.pm
    slashjp/trunk/plugins/Tags/Clout/Makefile.PL
    slashjp/trunk/plugins/Tags/Clout/Moderate.pm
    slashjp/trunk/plugins/Tags/Clout/Vote.pm
    slashjp/trunk/plugins/Tags/Clout.pm
    slashjp/trunk/plugins/Tags/Makefile.PL
    slashjp/trunk/plugins/Tags/Tagbox.pm
    slashjp/trunk/plugins/Tags/Tags.pm
    slashjp/trunk/plugins/Tags/mysql_dump.sql
    slashjp/trunk/plugins/Tags/mysql_schema.sql
    slashjp/trunk/plugins/Tags/tagbox.pl
    slashjp/trunk/plugins/Tags/tags_tagnamecache.pl
    slashjp/trunk/plugins/Tags/tags_udc.pl
    slashjp/trunk/plugins/Tags/tags_updateclouts.pl
    slashjp/trunk/plugins/Tags/templates/recenttagnamesbox;misc;default
    slashjp/trunk/plugins/Tags/templates/usertagnames;users;default
    slashjp/trunk/plugins/Tags/templates/usertagsforname;users;default
    slashjp/trunk/plugins/Validator/Makefile.PL
    slashjp/trunk/plugins/YASS/Makefile.PL
    slashjp/trunk/plugins/YASS/YASS.pm
    slashjp/trunk/plugins/Zoo/Makefile.PL
    slashjp/trunk/plugins/Zoo/Zoo.pm
    slashjp/trunk/sbin/portald
    slashjp/trunk/sbin/slashd
    slashjp/trunk/sql/mysql/defaults.sql
    slashjp/trunk/sql/mysql/slashschema_create.sql
    slashjp/trunk/sql/mysql/upgrades
    slashjp/trunk/tagboxes/CommentScoreReason/CommentScoreReason.pm
    slashjp/trunk/tagboxes/CommentScoreReason/Makefile.PL
    slashjp/trunk/tagboxes/CommentScoreReason/TAGBOX
    slashjp/trunk/tagboxes/CommentScoreReason/mysql_dump.sql
    slashjp/trunk/tagboxes/Despam/Despam.pm
    slashjp/trunk/tagboxes/Despam/Makefile.PL
    slashjp/trunk/tagboxes/Despam/TAGBOX
    slashjp/trunk/tagboxes/Despam/mysql_dump.sql
    slashjp/trunk/tagboxes/FHActivity/FHActivity.pm
    slashjp/trunk/tagboxes/FHActivity/Makefile.PL
    slashjp/trunk/tagboxes/FHActivity/TAGBOX
    slashjp/trunk/tagboxes/FHActivity/mysql_dump.sql
    slashjp/trunk/tagboxes/FHEditorPop/FHEditorPop.pm
    slashjp/trunk/tagboxes/FHEditorPop/Makefile.PL
    slashjp/trunk/tagboxes/FHEditorPop/TAGBOX
    slashjp/trunk/tagboxes/FHEditorPop/mysql_dump.sql
    slashjp/trunk/tagboxes/FHPopularity/FHPopularity.pm
    slashjp/trunk/tagboxes/FHPopularity/Makefile.PL
    slashjp/trunk/tagboxes/FHPopularity/TAGBOX
    slashjp/trunk/tagboxes/FHPopularity/mysql_dump.sql
    slashjp/trunk/tagboxes/FHPopularity2/FHPopularity2.pm
    slashjp/trunk/tagboxes/FHPopularity2/Makefile.PL
    slashjp/trunk/tagboxes/FHPopularity2/TAGBOX
    slashjp/trunk/tagboxes/FHPopularity2/mysql_dump.sql
    slashjp/trunk/tagboxes/FireHoseScores/FireHoseScores.pm
    slashjp/trunk/tagboxes/FireHoseScores/Makefile.PL
    slashjp/trunk/tagboxes/FireHoseScores/TAGBOX
    slashjp/trunk/tagboxes/FireHoseScores/mysql_dump.sql
    slashjp/trunk/tagboxes/RecentTags/Makefile.PL
    slashjp/trunk/tagboxes/RecentTags/RecentTags.pm
    slashjp/trunk/tagboxes/RecentTags/TAGBOX
    slashjp/trunk/tagboxes/RecentTags/mysql_dump.sql
    slashjp/trunk/tagboxes/TagCountUser/Makefile.PL
    slashjp/trunk/tagboxes/TagCountUser/TagCountUser.pm
    slashjp/trunk/tagboxes/Top/Makefile.PL
    slashjp/trunk/tagboxes/Top/Top.pm
    slashjp/trunk/themes/slashcode/THEME
    slashjp/trunk/themes/slashcode/htdocs/article.pl
    slashjp/trunk/themes/slashcode/htdocs/badge.js
    slashjp/trunk/themes/slashcode/htdocs/badge.pl
    slashjp/trunk/themes/slashcode/htdocs/comments.pl
    slashjp/trunk/themes/slashcode/htdocs/help.pl
    slashjp/trunk/themes/slashcode/htdocs/images/comments.js
    slashjp/trunk/themes/slashcode/htdocs/images/dumper.js
    slashjp/trunk/themes/slashcode/htdocs/users.pl
    slashjp/trunk/themes/slashcode/htdocs/users2.pl
    slashjp/trunk/themes/slashcode/tasks/delete_accesslog.pl
    slashjp/trunk/themes/slashcode/tasks/im_messages.pl
    slashjp/trunk/themes/slashcode/tasks/process_file_queue.pl
    slashjp/trunk/themes/slashcode/tasks/rotate_semirandom_block.pl
    slashjp/trunk/themes/slashcode/tasks/url_checker.pl
    slashjp/trunk/themes/slashcode/templates/autocomplete;misc;default
    slashjp/trunk/themes/slashcode/templates/dispComment;misc;default
    slashjp/trunk/themes/slashcode/templates/dispCommentDetails;misc;default
    slashjp/trunk/themes/slashcode/templates/edit_comment;comments;default
    slashjp/trunk/themes/slashcode/templates/firehose_related;misc;default
    slashjp/trunk/themes/slashcode/templates/help_anon;misc;default
    slashjp/trunk/themes/slashcode/templates/help_main;misc;default
    slashjp/trunk/themes/slashcode/templates/html-header;misc;default
    slashjp/trunk/themes/slashcode/templates/preview_comm;comments;default
    slashjp/trunk/themes/slashcode/templates/printCommComments;misc;default
    slashjp/trunk/themes/slashcode/templates/printCommentsLinks;misc;default
    slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default
    slashjp/trunk/themes/slashcode/templates/userFireHose;users;default
    slashjp/trunk/themes/slashcode/templates/userInfo2;users;default
    slashjp/trunk/themes/slashcode/templates/userboxes2;misc;default
    slashjp/trunk/themes/slashcode/templates/userlogin_cover;misc;default

Added Paths:
-----------
    slashjp/trunk/Slash/Tools/
    slashjp/trunk/bin/purge-read-log
    slashjp/trunk/plugins/Ajax/htdocs/images/api.js
    slashjp/trunk/plugins/Ajax/htdocs/images/jquery/
    slashjp/trunk/plugins/Ajax/htdocs/images/responder.tagui.js
    slashjp/trunk/plugins/Ajax/htdocs/images/t/
    slashjp/trunk/plugins/Ajax/htdocs/images/tagui.css
    slashjp/trunk/plugins/Ajax/htdocs/images/tagui.js
    slashjp/trunk/plugins/Ajax/templates/combined_tags;misc;default
    slashjp/trunk/plugins/Ajax/templates/tag_display;misc;default
    slashjp/trunk/plugins/Ajax/templates/tag_widget;misc;default
    slashjp/trunk/plugins/FireHose/firehose_track_volume.pl
    slashjp/trunk/plugins/FireHose/templates/init_tagui;firehose;default
    slashjp/trunk/plugins/FireHose/templates/tag_widget;firehose;default
    slashjp/trunk/plugins/Stats/templates/topic_stats;stats;default
    slashjp/trunk/tagboxes/DiscussionScore/
    slashjp/trunk/tagboxes/Metamod/
    slashjp/trunk/themes/slashcode/htdocs/images/spinner_grey.gif
    slashjp/trunk/utils/update_storable_network.plx

Removed Paths:
-------------
    slashjp/trunk/plugins/Ajax/htdocs/images/jquery-1.2.3.js
    slashjp/trunk/plugins/FireHose/templates/tagstack;firehose;default

Property Changed:
----------------
    slashjp/trunk/INSTALL.solaris
    slashjp/trunk/Slash/Client/Makefile.PL
    slashjp/trunk/Slash/Constants/Constants.pm
    slashjp/trunk/Slash/Constants/MANIFEST
    slashjp/trunk/Slash/Constants/Makefile.PL
    slashjp/trunk/Slash/Custom/Bulkmail/Bulkmail.pm
    slashjp/trunk/Slash/Custom/Bulkmail/MANIFEST
    slashjp/trunk/Slash/Custom/Bulkmail/Makefile.PL
    slashjp/trunk/Slash/Custom/Makefile.PL
    slashjp/trunk/Slash/Test/MANIFEST
    slashjp/trunk/Slash/Test/Makefile.PL
    slashjp/trunk/Slash/Test/Test.pm
    slashjp/trunk/Slash/Utility/Access/Access.pm
    slashjp/trunk/Slash/Utility/Access/MANIFEST
    slashjp/trunk/Slash/Utility/Access/Makefile.PL
    slashjp/trunk/Slash/Utility/Anchor/Anchor.pm
    slashjp/trunk/Slash/Utility/Anchor/MANIFEST
    slashjp/trunk/Slash/Utility/Anchor/Makefile.PL
    slashjp/trunk/Slash/Utility/Data/Data.pm
    slashjp/trunk/Slash/Utility/Data/MANIFEST
    slashjp/trunk/Slash/Utility/Data/Makefile.PL
    slashjp/trunk/Slash/Utility/Display/Display.pm
    slashjp/trunk/Slash/Utility/Display/MANIFEST
    slashjp/trunk/Slash/Utility/Display/Makefile.PL
    slashjp/trunk/Slash/Utility/Environment/Environment.pm
    slashjp/trunk/Slash/Utility/Environment/MANIFEST
    slashjp/trunk/Slash/Utility/Environment/Makefile.PL
    slashjp/trunk/Slash/Utility/System/MANIFEST
    slashjp/trunk/Slash/Utility/System/Makefile.PL
    slashjp/trunk/Slash/Utility/System/System.pm
    slashjp/trunk/Slash/XML/Atom/Atom.pm
    slashjp/trunk/Slash/XML/RSS/MANIFEST
    slashjp/trunk/Slash/XML/RSS/Makefile.PL
    slashjp/trunk/Slash/XML/RSS/RSS.pm
    slashjp/trunk/docs/slasherd.pdf
    slashjp/trunk/docs/slashguide.pod
    slashjp/trunk/docs/slashtables.pod
    slashjp/trunk/plugins/Email/Makefile.PL
    slashjp/trunk/plugins/Email/templates/email_subj;email;default
    slashjp/trunk/plugins/Events/Events.pm
    slashjp/trunk/plugins/Events/Makefile.PL
    slashjp/trunk/plugins/Events/PLUGIN
    slashjp/trunk/plugins/Events/templates/editevent;eventsadmin;default
    slashjp/trunk/plugins/Events/templates/events;misc;default
    slashjp/trunk/plugins/Events/templates/eventsadmin;misc;default
    slashjp/trunk/plugins/Events/templates/index;eventsadmin;default
    slashjp/trunk/plugins/Events/templates/listevents;eventsadmin;default
    slashjp/trunk/plugins/FAQ/Makefile.PL
    slashjp/trunk/plugins/FAQSlashdot/Makefile.PL
    slashjp/trunk/plugins/HumanConf/Makefile.PL
    slashjp/trunk/plugins/HumanConf/templates/data;humanconf;default
    slashjp/trunk/plugins/Journal/templates/friendsview;journal;default
    slashjp/trunk/plugins/Journal/templates/journalhead;journal;default
    slashjp/trunk/plugins/Journal/templates/messagenew;journal;default
    slashjp/trunk/plugins/Journal/templates/messagenew_subj;journal;default
    slashjp/trunk/plugins/Journal/templates/meta;journal;default
    slashjp/trunk/plugins/Journal/templates/pagination;journal;default
    slashjp/trunk/plugins/Journal/templates/searchusers;journal;default
    slashjp/trunk/plugins/Journal/templates/slashdot;journal;default
    slashjp/trunk/plugins/Messages/DB/Makefile.PL
    slashjp/trunk/plugins/Messages/DB/MySQL/MANIFEST
    slashjp/trunk/plugins/Messages/DB/MySQL/Makefile.PL
    slashjp/trunk/plugins/Messages/DB/MySQL/MySQL.pm
    slashjp/trunk/plugins/Messages/MANIFEST
    slashjp/trunk/plugins/Messages/Makefile.PL
    slashjp/trunk/plugins/Messages/Messages.pm
    slashjp/trunk/plugins/Messages/PLUGIN
    slashjp/trunk/plugins/Messages/dump
    slashjp/trunk/plugins/Messages/mysql_schema
    slashjp/trunk/plugins/Messages/templates/commnew;comments;default
    slashjp/trunk/plugins/Messages/templates/commnew_sub;comments;default
    slashjp/trunk/plugins/Messages/templates/dailyheadlines;messages;default
    slashjp/trunk/plugins/Messages/templates/dailynews;messages;default
    slashjp/trunk/plugins/Messages/templates/data;messages;default
    slashjp/trunk/plugins/Messages/templates/display;messages;default
    slashjp/trunk/plugins/Messages/templates/display_prefs;messages;default
    slashjp/trunk/plugins/Messages/templates/emailsponsor;messages;default
    slashjp/trunk/plugins/Messages/templates/html_invalid;misc;default
    slashjp/trunk/plugins/Messages/templates/html_invalid_subj;misc;default
    slashjp/trunk/plugins/Messages/templates/journrep;comments;default
    slashjp/trunk/plugins/Messages/templates/journrep_subj;comments;default
    slashjp/trunk/plugins/Messages/templates/journuserboxes;misc;default
    slashjp/trunk/plugins/Messages/templates/list_messages;messages;default
    slashjp/trunk/plugins/Messages/templates/messagenew;submit;default
    slashjp/trunk/plugins/Messages/templates/messagenew_subj;submit;default
    slashjp/trunk/plugins/Messages/templates/mod_msg;comments;default
    slashjp/trunk/plugins/Messages/templates/mod_msg_subj;comments;default
    slashjp/trunk/plugins/Messages/templates/msg_email;messages;default
    slashjp/trunk/plugins/Messages/templates/msg_email_subj;messages;default
    slashjp/trunk/plugins/Messages/templates/msg_m2;messages;default
    slashjp/trunk/plugins/Messages/templates/msg_m2_subj;messages;default
    slashjp/trunk/plugins/Messages/templates/msg_web_subj;messages;default
    slashjp/trunk/plugins/Messages/templates/reply_msg;comments;default
    slashjp/trunk/plugins/Messages/templates/reply_msg_subj;comments;default
    slashjp/trunk/plugins/Messages/templates/unmod_msg;comments;default
    slashjp/trunk/plugins/Messages/templates/unmod_msg_subj;comments;default
    slashjp/trunk/plugins/NewsVac/Makefile.PL
    slashjp/trunk/plugins/NewsVac/newsvac.pod
    slashjp/trunk/plugins/Page/Makefile.PL
    slashjp/trunk/plugins/Page/Page.pm
    slashjp/trunk/plugins/Remarks/templates/data;remarks;default
    slashjp/trunk/plugins/Remarks/templates/display;remarks;default
    slashjp/trunk/plugins/ResKey/MANIFEST
    slashjp/trunk/plugins/ResKey/Makefile.PL
    slashjp/trunk/plugins/ResKey/PLUGIN
    slashjp/trunk/plugins/ResKey/templates/data;reskey;default
    slashjp/trunk/plugins/ScheduleShifts/Makefile.PL
    slashjp/trunk/plugins/ScheduleShifts/ScheduleShifts.pm
    slashjp/trunk/plugins/Search/templates/pagination;search;default
    slashjp/trunk/plugins/SearchToo/MANIFEST
    slashjp/trunk/plugins/SearchToo/Makefile.PL
    slashjp/trunk/plugins/SearchToo/PLUGIN
    slashjp/trunk/plugins/SearchToo/SearchToo/Makefile.PL
    slashjp/trunk/plugins/SearchToo/dump
    slashjp/trunk/plugins/SearchToo/templates/commentsearch;searchtoo;default
    slashjp/trunk/plugins/SearchToo/templates/data;searchtoo;default
    slashjp/trunk/plugins/SearchToo/templates/nosearch;searchtoo;default
    slashjp/trunk/plugins/SearchToo/templates/pagination;searchtoo;default
    slashjp/trunk/plugins/SearchToo/templates/searchform;searchtoo;default
    slashjp/trunk/plugins/SearchToo/templates/searchrss;searchtoo;default
    slashjp/trunk/plugins/SearchToo/templates/storysearch;searchtoo;default
    slashjp/trunk/plugins/Stats/templates/csv;stats;default
    slashjp/trunk/plugins/Stats/templates/graphs;stats;default
    slashjp/trunk/plugins/Submit/templates/formatSub;submit;default
    slashjp/trunk/plugins/Submit/templates/mergeSub;submit;default
    slashjp/trunk/plugins/Validator/templates/html_invalid;misc;default
    slashjp/trunk/plugins/Validator/templates/html_invalid_subj;misc;default
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-html40-19980424/html40.tgz
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml-lat1.ent
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml-special.ent
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml-symbol.ent
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml.soc
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml1-frameset.dtd
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml1-strict.dtd
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml1-transitional.dtd
    slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml1.dcl
    slashjp/trunk/plugins/Zoo/templates/confirm;zoo;default
    slashjp/trunk/plugins/Zoo/templates/zoohead;zoo;default
    slashjp/trunk/tagboxes/TagCountUser/TagCountUser.pm
    slashjp/trunk/tagboxes/Top/Top.pm
    slashjp/trunk/themes/slashcode/htdocs/slashguide.shtml
    slashjp/trunk/themes/slashcode/templates/bannedtext_rss;misc;default
    slashjp/trunk/themes/slashcode/templates/formbox;misc;default
    slashjp/trunk/themes/slashcode/templates/linkrel;misc;default
    slashjp/trunk/themes/slashcode/templates/newdiscussion;comments;default
    slashjp/trunk/themes/slashcode/templates/pagination;comments;default
    slashjp/trunk/themes/slashcode/templates/udiscuss_list;comments;default


-------------- next part --------------
Modified: slashjp/trunk/Bundle/Makefile.PL
===================================================================
--- slashjp/trunk/Bundle/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Bundle/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 
 WriteMakefile(
 	'NAME'		=> 'Bundle::Slash',
-	'VERSION_FROM'	=> 'Slash.pm',
 	'clean'	=> {
 		'FILES'	=> 'Bundle-Slash-*'
 	},

Modified: slashjp/trunk/Bundle/Slash.pm
===================================================================
--- slashjp/trunk/Bundle/Slash.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Bundle/Slash.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,5 @@
 package Bundle::Slash;
 
-#
-# $Id$
-#
-
 $Bundle::Slash::VERSION = '2.52';
 
 1;
@@ -134,6 +130,10 @@
 and thus not installed by default, but which may become required as
 you edit your site configuration, are: Cache::Memcached Silly::Werder
 GD GD::Text GD::Graph Apache::SSI Apache::RegistryFilter GraphViz
-Net::IRC Proc::ProcessTable Net::Jabber File::Type
+Net::IRC Proc::ProcessTable Net::Jabber File::Type Linux::Pid
+File::Type Apache::SSI String::Similarity Devel::Size Devel::FindGlobals
+Slash::Client JavaScript::Minifier Template::Plugin::GD Net::Telnet
+Finance::Quote Net::OSCAR Date::ICal WWW::Mechanize
+Plucene::Document SOAP::Lite
 
 =cut

Modified: slashjp/trunk/INSTALL
===================================================================
--- slashjp/trunk/INSTALL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/INSTALL	2008-09-09 13:07:58 UTC (rev 742)
@@ -120,9 +120,12 @@
         might:
 
                 GRANT SELECT, INSERT, UPDATE, DELETE, LOCK TABLES, CREATE, DROP,
-                INDEX, ALTER, PROCESS ON slash.* TO 'slash'@'localhost'
+                INDEX, ALTER ON slash.* TO 'slash'@'localhost'
                 IDENTIFIED BY (quoted password);
 
+                GRANT PROCESS ON *.* TO 'slash'@'localhost' IDENTIFIED BY
+                (quoted password);
+
         In this case, 'slash' would also be the name of your MySQL user as
         described in "Types of Users" below. You'll have to give your MySQL
         user to DBIx::Password when you install and configure it, so don't
@@ -356,7 +359,8 @@
         proceeding. Note that Net::Cmd has a history of being a little
         broken in its tests; if it fails on tests 8 and 9 of t/require, then
         it's OK; just do "force install Net::Cmd" and repeat "install
-        Bundle::LWP".
+        Bundle::LWP". On Mac OS X and possibly other operating systems, if
+        LWP's live/https tests fail, "install Net::SSL" manually and retry.
 
         Assuming you chose to install the LWP, then after it's been
         configured successfully, again, "exit" the CPAN and reinvoke it.


Property changes on: slashjp/trunk/INSTALL.solaris
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Makefile
===================================================================
--- slashjp/trunk/Makefile	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Makefile	2008-09-09 13:07:58 UTC (rev 742)
@@ -41,11 +41,15 @@
 SUBDIRS = `find . -maxdepth 1 -name CVS -prune -o -type d -name [a-zA-Z]\* -print`
 
 # Perl scripts, grouped by directory.
-BINFILES = `find bin -name CVS -prune -o -name [a-zA-Z]\* -type f -print`
-SBINFILES = `find sbin -name CVS -prune -o -name [a-zA-Z]\* -type f -print`
-THEMEFILES = `find themes -name CVS -prune -o -name [a-zA-z]\*.pl -print`
-PLUGINFILES = `find plugins -name CVS -prune -o -name [a-zA-Z]\*.pl -print`
-TAGBOXFILES = `find tagboxes -name CVS -prune -o -name [a-zA-Z]\*.pl -print`
+BINFILES = `find bin -name CVS -prune -o -name .git -prune -o -name [a-zA-Z]\* -type f -print`
+SBINFILES = `find sbin -name CVS -prune -o -name .git -prune -o -name [a-zA-Z]\* -type f -print`
+THEMEFILES = `find themes -name CVS -prune -o -name .git -prune -o -name [a-zA-z]\*.pl -print`
+PLUGINFILES = `find plugins themes/*/plugins -name CVS -prune -o -name .git -prune -o -name [a-zA-Z]\*.pl -print`
+TAGBOXFILES = `find tagboxes themes/*/tagboxes -name CVS -prune -o -name .git -prune -o -name [a-zA-Z]\*.pl -print`
+PLUGINSTALL = `find . -name CVS -prune -o -name .git -prune -o -type d -print | egrep 'plugins/[a-zA-Z]+$$'`
+TAGINSTALL = `find . -name CVS -prune -o -name .git -prune -o -type d -print | egrep 'tagboxes/[a-zA-Z]+$$'`
+PLUGINDIRS = `find . -name CVS -prune -o -name .git -prune -o -type d -print | egrep 'plugins$$'`
+TAGBOXDIRS = `find . -name CVS -prune -o -name .git -prune -o -type d -print | egrep 'tagboxes$$'`
 
 # What do we use to invoke perl?
 REPLACEWITH = `$(PERL) -MConfig -e 'print quotemeta($$Config{startperl})' | sed 's/@/\\@/g'`
@@ -59,7 +63,7 @@
 INSTALLSITELIB=`$(PERL) -MConfig -e 'print "$(BUILDROOT)/$$Config{installsitelib}"'`
 INSTALLMAN3DIR=`$(PERL) -MConfig -e 'print "$(BUILDROOT)/$$Config{installman3dir}"'`
 
-.PHONY : all plugins tagboxes slash install
+.PHONY : all pluginsandtagboxes slash install
 
 #   install the shared object file into Apache 
 # We should run a script on the binaries to get the right
@@ -74,45 +78,30 @@
 		(cd Slash; $(PERL) Makefile.PL INSTALLSITEARCH=$(INSTALLSITEARCH) INSTALLSITELIB=$(INSTALLSITELIB) INSTALLMAN3DIR=$(INSTALLMAN3DIR); $(MAKE) install UNINST=1); \
 	fi
 
-plugins: 
-	@echo "=== INSTALLING SLASH PLUGINS ==="
-	@(cd plugins; \
-	 for a in $(SUBDIRS); do \
-	 	(cd $$a; \
+pluginsandtagboxes:
+	@echo "=== INSTALLING SLASH PLUGINS AND TAGBOXES ==="
+	@(pluginstall=$(PLUGINSTALL); \
+	taginstall=$(TAGINSTALL); \
+	for f in $$pluginstall $$taginstall; do \
+		(cd $$f; \
 		 echo == $$PWD; \
 		 if [ -f Makefile.PL ]; then \
 		 	if [ ! "$(RPM)" ] ; then \
 				$(PERL) Makefile.PL; \
 				$(MAKE) install UNINST=1;\
+				$(MAKE) realclean; \
 			else \
 				echo " - Performing an RPM build."; \
 				$(PERL) Makefile.PL INSTALLSITEARCH=$(INSTALLSITEARCH) INSTALLSITELIB=$(INSTALLSITELIB) INSTALLMAN3DIR=$(INSTALLMAN3DIR); \
 				$(MAKE) install UNINST=1; \
+				$(MAKE) realclean; \
 			fi; \
 		 fi); \
 	done)
 
-tagboxes: 
-	@echo "=== INSTALLING SLASH TAGBOXES ==="
-	@(cd tagboxes; \
-	 for a in $(SUBDIRS); do \
-	 	(cd $$a; \
-		 echo == $$PWD; \
-		 if [ -f Makefile.PL ]; then \
-		 	if [ ! "$(RPM)" ] ; then \
-				$(PERL) Makefile.PL; \
-				$(MAKE) install UNINST=1;\
-			else \
-				echo " - Performing an RPM build."; \
-				$(PERL) Makefile.PL INSTALLSITEARCH=$(INSTALLSITEARCH) INSTALLSITELIB=$(INSTALLSITELIB) INSTALLMAN3DIR=$(INSTALLMAN3DIR); \
-				$(MAKE) install UNINST=1; \
-			fi; \
-		 fi); \
-	done)
-
 all: install
 
-install: slash plugins tagboxes
+install: slash pluginsandtagboxes
 
 	# Create all necessary directories.
 	$(INSTALL) -d \
@@ -146,10 +135,15 @@
 	# supports that option; however, its use is strongly discouraged, as it
 	# does not correctly copy special files, symbolic links or FIFOs. 
 	#
-	(cd plugins; $(MAKE) clean) 
-	$(CP) -r plugins/* $(SLASH_PREFIX)/plugins
-	(cd tagboxes; $(MAKE) clean) 
-	$(CP) -r tagboxes/* $(SLASH_PREFIX)/tagboxes
+	@(pluginstall=$(PLUGINSTALL); \
+	taginstall=$(TAGINSTALL); \
+	for f in $$pluginstall; do \
+		($(CP) -r $$f $(SLASH_PREFIX)/plugins); \
+	done; \
+	for f in $$taginstall; do \
+		($(CP) -r $$f $(SLASH_PREFIX)/tagboxes); \
+	done)
+
 	# Now all the themes
 	$(CP) -r themes/* $(SLASH_PREFIX)/themes
 	

Modified: slashjp/trunk/Slash/Apache/Apache.pm
===================================================================
--- slashjp/trunk/Slash/Apache/Apache.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/Apache.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Apache;
 
@@ -18,11 +17,10 @@
 
 require DynaLoader;
 require AutoLoader;
-use vars qw($REVISION $VERSION @ISA $USER_MATCH $DAYPASS_MATCH);
+use vars qw($VERSION @ISA $USER_MATCH $DAYPASS_MATCH);
 
 @ISA		= qw(DynaLoader);
 $VERSION   	= '2.003000';  # v2.3.0
-($REVISION)	= ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
 
 $USER_MATCH = qr{ \buser=(?!	# must have user, but NOT ...
 	(?: nobody | %[20]0 )?	# nobody or space or null or nothing ...
@@ -249,11 +247,14 @@
 # use a closure to store the regex that matches incoming IP number.
 {
 my $trusted_ip_regex = undef;
+my $trusted_header = undef;
 sub ProxyRemoteAddr ($) {
 	my($r) = @_;
 
-	if (!defined($trusted_ip_regex)) {
-		$trusted_ip_regex = getCurrentStatic("x_forwarded_for_trust_regex");
+	# Set up the variables that are loaded only once.
+	if (!defined($trusted_ip_regex) || !defined($trusted_header)) {
+		my $constants = getCurrentStatic();
+		$trusted_ip_regex = $constants->{clientip_xff_trust_regex};
 		if ($trusted_ip_regex) {
 			# Avoid a little processing each time by doing
 			# the regex parsing just once.
@@ -265,16 +266,29 @@
 			# If defined but false, disable.
 			$trusted_ip_regex = '0';
 		}
+		$trusted_header = $constants->{clientip_trust_header} || '';
 	}
-	return OK if $trusted_ip_regex eq '0';
 
-	# Since any client can forge X-Forwarded-For, we ignore it...
-	return OK unless $r->connection->remote_ip =~ $trusted_ip_regex;
+	# If the actual IP the connection came from is not trusted, we
+	# skip the following processing.  An untrusted client could send
+	# any header with any value.
+	if ($trusted_ip_regex eq '0'
+		|| $r->connection->remote_ip !~ $trusted_ip_regex) {
+		return OK;
+	}
 
-	# ...unless the connection comes from a trusted source.
-	my $xf = $r->header_in('X-Forward-Pound') || $r->header_in('X-Forwarded-For');
-	if (my($ip) = $xf =~ /([^,\s]+)$/) {
-		$r->connection->remote_ip($ip);
+	# The connection comes from a trusted IP.  Use either the
+	# specified header (which presumably the trusted IP overwrites
+	# or modifies) and pull from it the last IP on its list (so
+	# presumably if the trusted IP does merely modify the header,
+	# it appends the actual original IP to its value).
+	my $xf = undef;
+	$xf = $r->header_in($trusted_header) if $trusted_header;
+	$xf ||= $r->header_in('X-Forwarded-For');
+	if ($xf) {
+		if (my($ip) = $xf =~ /([\d.]+)$/) {
+			$r->connection->remote_ip($ip);
+		}
 	}
 
 	return OK;
@@ -290,13 +304,17 @@
 	# That probably didn't work so let's get that data the hard way.
 	my $r = Apache->request;
 	return 0 if !$r;
+
+	my $x = $r->header_in('X-SFINC-SSL');
+	return 1 if $x && $x eq 'true';
+
 	my $subr = $r->lookup_uri($r->uri);
 	if ($subr) {
 		my $se = $subr->subprocess_env('HTTPS');
 		return 1 if $se && $se eq 'on'; # https is on
 	}
 
-	my $x = $r->header_in('X-SSL-On');
+	$x = $r->header_in('X-SSL-On');
 	return 1 if $x && $x eq 'yes'; 
 
 	# We're out of ideas.  If the above didn't work we must not be

Modified: slashjp/trunk/Slash/Apache/Banlist/Banlist.pm
===================================================================
--- slashjp/trunk/Slash/Apache/Banlist/Banlist.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/Banlist/Banlist.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 # This handler is called in the fourth Apache phase, access control.
 
@@ -15,10 +14,8 @@
 use Slash::Utility;
 use Slash::XML;
 
-use vars qw($VERSION);
+our $VERSION = $Slash::Constants::VERSION;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
-
 sub handler {
 	my($r) = @_;
 

Modified: slashjp/trunk/Slash/Apache/Banlist/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Apache/Banlist/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/Banlist/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Apache::Banlist',
-    'VERSION_FROM' => 'Banlist.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Apache/Log/Log.pm
===================================================================
--- slashjp/trunk/Slash/Apache/Log/Log.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/Log/Log.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,16 +1,14 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Apache::Log;
 
 use strict;
 use Slash::Utility;
 use Apache::Constants qw(:common);
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # AMY: Leela's gonna kill me.
 # BENDER: Naw, she'll probably have me do it.

Modified: slashjp/trunk/Slash/Apache/Log/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Apache/Log/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/Log/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Apache::Log',
-    'VERSION_FROM' => 'Log.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Apache/TemplatePages/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Apache/TemplatePages/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/TemplatePages/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Apache::TemplatePages',
-    'VERSION_FROM' => 'TemplatePages.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Apache/TemplatePages/TemplatePages.pm
===================================================================
--- slashjp/trunk/Slash/Apache/TemplatePages/TemplatePages.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/TemplatePages/TemplatePages.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Apache::TemplatePages;
 
@@ -9,9 +8,8 @@
 use Slash::Display;
 use Slash::Utility;
 use Apache::Constants qw(:common);
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # AMY: Leela's gonna kill me.
 # BENDER: Naw, she'll probably have me do it.

Modified: slashjp/trunk/Slash/Apache/User/PasswordSalt/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Apache/User/PasswordSalt/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/User/PasswordSalt/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,5 +2,4 @@
 
 WriteMakefile(
 	'NAME'	=> 'Slash::Apache::User::PasswordSalt',
-	'VERSION_FROM' => 'PasswordSalt.pm',
 );

Modified: slashjp/trunk/Slash/Apache/User/PasswordSalt/PasswordSalt.pm
===================================================================
--- slashjp/trunk/Slash/Apache/User/PasswordSalt/PasswordSalt.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/User/PasswordSalt/PasswordSalt.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: PasswordSalt.pm,v 1.2 2008/01/31 15:17:45 jamiemccarthy Exp $
 
 package Slash::Apache::User::PasswordSalt;
 
@@ -9,10 +8,8 @@
 use Carp;
 use File::Spec::Functions;
 use Slash::Utility::Environment;
-use vars qw($REVISION $VERSION);
 
-$VERSION   	= '2.003000';  # v2.3.0
-($REVISION)	= ' $Revision: 1.2 $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 
 #
@@ -106,7 +103,7 @@
 		my($package, $filename, $line, $subroutine) = @c;
 		# If we go back up the call chain to a package we know we can
 		# trust, then we can stop looking.
-		last if $package =~ /^(main|Apache::Registry|Apache::ROOT::.*)$/;
+		last if $package =~ /^(main|Apache::PerlRun|Apache::Registry|Apache::ROOT.*)$/;
 		if ($package =~ /^Template/ || $subroutine eq '(eval)') {
 			# This exits the entire script immediately.
 			confess(scalar(gmtime) . " $$ SuspiciousCaller for salt at package '$package'");

Modified: slashjp/trunk/Slash/Apache/User/User.pm
===================================================================
--- slashjp/trunk/Slash/Apache/User/User.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Apache/User/User.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Apache::User;
 
@@ -20,11 +19,10 @@
 use Slash::Display;
 use Slash::Utility;
 use URI ();
-use vars qw($REVISION $VERSION @ISA @QUOTES $USER_MATCH $request_start_time);
+use vars qw($VERSION @ISA @QUOTES $USER_MATCH $request_start_time);
 
 @ISA		= qw(DynaLoader);
 $VERSION   	= '2.003000';  # v2.3.0
-($REVISION)	= ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
 
 bootstrap Slash::Apache::User $VERSION;
 
@@ -171,13 +169,11 @@
 		# open proxies.	Check both the ipid and the subnetid (we
 		# can't use values in $user because that doesn't get set
 		# up until prepareUser is called, later in this function).
-		# XXXSRCID: really should have a separate 'openproxy'
-		# attribute instead of piggybacking off 'nopost'.
 		my $read_only = 0;
 		my $hostip = $r->connection->remote_ip;
 		my $srcids = get_srcids({ ip => $hostip });
-		$read_only = 1 if $reader->checkAL2($srcids, 'nopost')
-			|| $reader->checkAL2($srcids, 'nopostanon');
+		$read_only = 1 if $reader->checkAL2($srcids,
+			[qw( nopost nopostanon openproxy )]);
 
 		my $newpass;
 		if ($read_only || !$tmpuid) {
@@ -598,13 +594,6 @@
                 return OK;
         }
        
-        # This is a temporary addition!
-        if ($uri =~ m[^/(?:%5[eE]|\^)]) {
-                $r->uri('/users2.pl');
-                $r->filename($constants->{basedir} . '/users2.pl');
-                return OK;
-        }
- 
 	# journals for slashdot.jp
 	if ($uri =~ m!^/journals (?: /([^?]*) | /? ) (?: \?(.*) )? $!x) {
 		my($word, $query) = ($1, $2);
@@ -804,7 +793,7 @@
 	# returning it, we have to re-encode it with fixparam().  that
 	# will change if somehow Apache/mod_perl no longer decodes before
 	# returning the data. -- pudge
-	if ($saveuri =~ m[^/(?:%7[eE]|~)(.+)]) {
+	if (($saveuri =~ m[^/(?:%7[eE]|~)(.+)]) || ($saveuri =~ m[^/(?:%5[eE]|\^)(.+)])) {
 		my($string, $query) = ($1, '');
 		if ($string =~ s/\?(.+)$//) {
 			$query = $1;
@@ -836,25 +825,31 @@
 			$r->filename($constants->{basedir} . '/users.pl');
 
 		} elsif ($op eq 'journal') {
-			my $args = "op=display&nick=$nick&uid=$uid";
-			$extra .= '/' . $more;
-			if ($extra) {
-				if ($extra =~ /^(\d+)\/$/) {
-					$args .= "&id=$1";
-				}
-				if ($extra =~ s/^friends\///) {
-					$args =~ s/display/friendview/;
-				}
-				if ($extra =~ m{^ (rss|atom) / ? $}x) {
-					$args .= "&logtoken=$logtoken" if $logtoken;
-					$args .= "&content_type=$1";
-				}
-			}
-			$args .= "&$query";
-			$r->args($args);
-			$r->uri('/journal.pl');
-			$r->filename($constants->{basedir} . '/journal.pl');
+                        if ($saveuri =~ m[^/(?:%5[eE]|\^)(.+)]) {
+                                $r->args("nick=$nick&dp=journal&uid=$uid");
+                                $r->uri('/users2.pl');
+                                $r->filename($constants->{basedir} . '/users2.pl');
+                        } else {
+			        my $args = "op=display&nick=$nick&uid=$uid";
+			        $extra .= '/' . $more;
+			        if ($extra) {
+				        if ($extra =~ /^(\d+)\/$/) {
+					        $args .= "&id=$1";
+				        }
+				        if ($extra =~ s/^friends\///) {
+					        $args =~ s/display/friendview/;
+				        }
+				        if ($extra =~ m{^ (rss|atom) / ? $}x) {
+					        $args .= "&logtoken=$logtoken" if $logtoken;
+					        $args .= "&content_type=$1";
+				        }
+			        }
 
+			        $args .= "&$query";
+			        $r->args($args);
+			        $r->uri('/journal.pl');
+			        $r->filename($constants->{basedir} . '/journal.pl');
+                        }
 		} elsif ($op eq 'discussions') {
 			$r->args("op=creator_index&nick=$nick&uid=$uid");
 			$r->uri('/comments.pl');
@@ -866,15 +861,25 @@
 			$r->filename($constants->{basedir} . '/pubkey.pl');
 
 		} elsif ($op eq 'submissions') {
-			$r->args("nick=$nick&op=usersubmissions&uid=$uid");
-			$r->uri('/users.pl');
-			$r->filename($constants->{basedir} . '/users.pl');
-
+                        if ($saveuri =~ m[^/(?:%5[eE]|\^)(.+)]) {
+                                $r->args("nick=$nick&dp=submissions&uid=$uid");
+                                $r->uri('/users2.pl');
+                                $r->filename($constants->{basedir} . '/users2.pl');
+                        } else {
+			        $r->args("nick=$nick&op=usersubmissions&uid=$uid");
+			        $r->uri('/users.pl');
+			        $r->filename($constants->{basedir} . '/users.pl');
+                        }
 		} elsif ($op eq 'comments') {
-			$r->args("nick=$nick&op=usercomments&uid=$uid");
-			$r->uri('/users.pl');
-			$r->filename($constants->{basedir} . '/users.pl');
-
+                        if ($saveuri =~ m[^/(?:%5[eE]|\^)(.+)]) {
+                                $r->args("nick=$nick&dp=comments&uid=$uid");
+                                $r->uri('/users2.pl');
+                                $r->filename($constants->{basedir} . '/users2.pl');
+                        } else {
+			        $r->args("nick=$nick&op=usercomments&uid=$uid");
+			        $r->uri('/users.pl');
+			        $r->filename($constants->{basedir} . '/users.pl');
+                        }
 		} elsif ($op =~ /^(?:friends|fans|freaks|foes|zoo)$/) {
 			my $args = "op=$op&nick=$nick&uid=$uid";
 			$extra .= '/' . $more;
@@ -935,9 +940,15 @@
 			$r->filename($constants->{basedir} . '/users.pl');
 
 		} else {
-			$r->args("nick=$nick&uid=$uid");
-			$r->uri('/users.pl');
-			$r->filename($constants->{basedir} . '/users.pl');
+                        if ($saveuri =~ m[^/(?:%5[eE]|\^)(.+)]) {
+                                $r->args("nick=$nick&uid=$uid");
+                                $r->uri('/users2.pl');
+                                $r->filename($constants->{basedir} . '/users2.pl');
+                        } else {
+			        $r->args("nick=$nick&uid=$uid");
+			        $r->uri('/users.pl');
+			        $r->filename($constants->{basedir} . '/users.pl');
+                        }
 		}
 
 		return OK;

Modified: slashjp/trunk/Slash/Client/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Client/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Client/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 
 WriteMakefile(
 	'NAME'		=> 'Slash::Client',
-	'VERSION_FROM'	=> 'lib/Slash/Client.pm',
 	'clean'	=> {
 		'FILES'	=> 'Slash-Client-*'
 	},


Property changes on: slashjp/trunk/Slash/Client/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Client/lib/Slash/Client/Journal.pm
===================================================================
--- slashjp/trunk/Slash/Client/lib/Slash/Client/Journal.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Client/lib/Slash/Client/Journal.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Client::Journal;
 
@@ -184,6 +183,3 @@
 Slash::Client(3).
 
 
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/Slash/Client/lib/Slash/Client.pm
===================================================================
--- slashjp/trunk/Slash/Client/lib/Slash/Client.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Client/lib/Slash/Client.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Client;
 
@@ -200,8 +199,3 @@
 =head1 SEE ALSO
 
 Slash::Client::Journal(3).
-
-
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/Slash/Constants/Constants.pm
===================================================================
--- slashjp/trunk/Slash/Constants/Constants.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Constants/Constants.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Constants;
 
@@ -27,14 +26,14 @@
 
 use strict;
 use base 'Exporter';
-use vars qw(@ISA $VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS %CONSTANTS);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = '2.005001'; # v2.5.1
+our %CONSTANTS;
 
 constants();
- @ EXPORT		= qw();
- @ EXPORT_OK	= map { keys %{$CONSTANTS{$_}} } keys %CONSTANTS;
-%EXPORT_TAGS	= (
+our @EXPORT		= qw();
+our @EXPORT_OK	= map { keys %{$CONSTANTS{$_}} } keys %CONSTANTS;
+our %EXPORT_TAGS	= (
 	all	=> [@EXPORT_OK],
 	map { ($_, [keys %{$CONSTANTS{$_}}]) } keys %CONSTANTS
 );
@@ -43,7 +42,7 @@
 sub constants {
 	my($group, @syms, @nums);
 
-	while (<DATA>) {
+	for (readline(DATA)) {
 		if (/^=head2 (\w+)$/ || /^__END__$/) {
 			if ($group && @syms && @nums) {
 				@{$CONSTANTS{$group}}{@syms} = @nums;
@@ -214,7 +213,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/Constants/Constants.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/Slash/Constants/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Constants/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Constants/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Constants/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Constants',
-    'VERSION_FROM' => 'Constants.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Constants/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Custom/ApacheCompress/ApacheCompress.pm
===================================================================
--- slashjp/trunk/Slash/Custom/ApacheCompress/ApacheCompress.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/ApacheCompress/ApacheCompress.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 # this merely overrides a "broken" method in Apache::SSI,
 # where include directives don't work for mixing with Apache::Compress

Modified: slashjp/trunk/Slash/Custom/ApacheCompress/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Custom/ApacheCompress/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/ApacheCompress/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Custom::ApacheCompress',
-    'VERSION_FROM' => 'ApacheCompress.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Custom/ApacheRegistryFilter/ApacheRegistryFilter.pm
===================================================================
--- slashjp/trunk/Slash/Custom/ApacheRegistryFilter/ApacheRegistryFilter.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/ApacheRegistryFilter/ApacheRegistryFilter.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 # this merely overrides a "broken" method in Apache::SSI,
 # where include directives don't work for mixing with Apache::Compress

Modified: slashjp/trunk/Slash/Custom/ApacheRegistryFilter/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Custom/ApacheRegistryFilter/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/ApacheRegistryFilter/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Custom::ApacheRegistryFilter',
-    'VERSION_FROM' => 'ApacheRegistryFilter.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Custom/ApacheSSI/ApacheSSI.pm
===================================================================
--- slashjp/trunk/Slash/Custom/ApacheSSI/ApacheSSI.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/ApacheSSI/ApacheSSI.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 # this merely overrides a "broken" method in Apache::SSI,
 # where include directives don't work for mixing with Apache::Compress

Modified: slashjp/trunk/Slash/Custom/ApacheSSI/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Custom/ApacheSSI/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/ApacheSSI/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Custom::ApacheSSI',
-    'VERSION_FROM' => 'ApacheSSI.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Custom/Bulkmail/Bulkmail.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/Slash/Custom/Bulkmail/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Custom/Bulkmail/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Custom/Bulkmail/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/Bulkmail/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Custom::Bulkmail',
-    'VERSION_FROM' => 'Bulkmail.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Custom/Bulkmail/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/Slash/Custom/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Custom/ParUserAgent/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Custom/ParUserAgent/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/ParUserAgent/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Custom::ParUserAgent',
-    'VERSION_FROM' => 'ParUserAgent.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Custom/ParUserAgent/ParUserAgent.pm
===================================================================
--- slashjp/trunk/Slash/Custom/ParUserAgent/ParUserAgent.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Custom/ParUserAgent/ParUserAgent.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 # This overrides LWP::Parallel::UserAgent to allow multiple
 # proxies to be used with a single scheme, indeed with a

Modified: slashjp/trunk/Slash/DB/DB.pm
===================================================================
--- slashjp/trunk/Slash/DB/DB.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/DB.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,16 +1,14 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::DB;
 
 use strict;
 use DBIx::Password;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: Would you cram a sock in it, Bender?
 

Modified: slashjp/trunk/Slash/DB/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::DB',
-    'VERSION_FROM' => 'DB.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/DB/MySQL/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/MySQL/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/MySQL/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::DB::MySQL',
-    'VERSION_FROM' => 'MySQL.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/DB/MySQL/MySQL.pm
===================================================================
--- slashjp/trunk/Slash/DB/MySQL/MySQL.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/MySQL/MySQL.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::DB::MySQL;
 use strict;
@@ -12,17 +11,15 @@
 use Date::Format qw(time2str);
 use Data::Dumper;
 use Slash::Utility;
-use Storable qw(thaw freeze);
+use Storable qw(thaw nfreeze);
 use URI ();
 use Slash::Custom::ParUserAgent;
-use vars qw($VERSION $_proxy_port);
+use vars qw($_proxy_port);
 use base 'Slash::DB';
 use base 'Slash::DB::Utility';
 use Slash::Constants ':messages';
-use Encode;
-use Slash::LDAPDB;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # Fry: How can I live my life if I can't tell good from evil?
 
@@ -1293,20 +1290,22 @@
 		"NOW() > DATE_ADD(lasttime, INTERVAL $admin_timeout MINUTE)"
 	);
 
-	my($lasttitle, $last_sid, $last_subid, $last_fhid) = $self->sqlSelect(
-		'lasttitle, last_sid, last_subid, last_fhid',
+	my($lasttitle, $last_sid, $last_subid, $last_fhid, $last_action) = $self->sqlSelect(
+		'lasttitle, last_sid, last_subid, last_fhid, last_action',
 		'sessions',
 		"uid=$uid"
 	);
 
+	if(!$lasttitle) {
 	$self->sqlReplace('sessions', {
 		-uid		=> $uid,
-		-lasttime	=> 'NOW()',
 		lasttitle	=> $lasttitle    || '',
 		last_sid	=> $last_sid     || '',
 		last_subid	=> $last_subid   || '0',
-		last_fhid	=> $last_fhid	 || '0'
+		last_fhid	=> $last_fhid	 || '0',
+		last_action	=> $last_action	 || '',
 	});
+	}
 }
 
 ########################################################
@@ -1361,6 +1360,11 @@
 		$dat ||= $uri;
 	}
 
+	return if $op eq 'slashdot-it'
+		&& ( !$constants->{slashdotit_accesslog}
+			|| ( $constants->{slashdotit_accesslog} < 1
+				&& rand() > $constants->{slashdotit_accesslog} ) );
+
 	my $uid = $user->{uid} || $constants->{anonymous_coward_uid};
 	my $skin_name = getCurrentSkin('name');
 	# XXXSKIN - i think these are no longer special cases ...
@@ -1479,7 +1483,7 @@
 	# And just what was the admin doing? -Brian
 	$op = $form->{op} if $form->{op};
 	$status ||= $r->status;
-	my $form_freeze = freeze($form);
+	my $form_freeze = nfreeze($form);
 
 	$self->sqlInsert('accesslog_admin', {
 		host_addr	=> $r->connection->remote_ip,
@@ -1572,8 +1576,70 @@
 	return $rows;
 }
 
+
 ########################################################
 # Get user info from the users table.
+sub getUserCrossSiteAuthenticate {
+	my($self, $site, $params, $user) = @_;
+	$user ||= getCurrentUser();
+	my $gSkin = getCurrentSkin();
+
+	errorLog("xsite: wrong host"), return unless $site->{host} eq $gSkin->{hostname};
+
+	errorLog("xsite: no timestamp/nonce"), return unless $params->{tstamp} && $params->{'rand'};
+
+	errorLog("xsite: expired timestamp"), return unless ( ($params->{tstamp} + 60) >= time() );
+
+	unless ($self->sqlInsert('xsite_auth_log', {
+		site    => $site->{site},
+		ts      => $params->{tstamp},
+		nonce   => $params->{'rand'}
+	})) {
+		errorLog("xsite: duplicate nonce");
+		return;
+	};
+
+	my $new = 0;
+	my $uid = $self->sqlSelect('uid', 'users_param',
+		"name=" . $self->sqlQuote($site->{auth_param_name}) .
+		" AND value=" . $self->sqlQuote($params->{user_id})
+	);
+
+	if (!$uid) {
+		my $newnick = sprintf($site->{user_name_format}, $params->{shortname} || $params->{user_id});
+		my $matchname = nick2matchname($newnick);
+		my $email = '';
+
+		# no email for now, so skip checks for email (and matchname;
+		# we don't care if someone already has an "sfpudge", that
+		# should not stop us from making a "SF:pudge")
+		$uid = $self->createUser(
+			$matchname, '', $newnick, { skipchecks => 1 }
+		);
+		$new = 1;
+
+		if ($uid) {
+			# XXX consider disallowing these accounts from
+			# authenticating on other domains
+			my $data = {};
+			$data->{creation_ipid} = $user->{ipid};
+			$data->{ $site->{auth_param_name} } = $params->{user_id};
+			$data->{acl}{nopasswd} = 1;
+			$self->setUser($uid, $data);
+		}
+	}
+
+	return unless $uid; # dunno!
+
+	my $logtoken = $self->getLogToken($uid, 1);
+
+	# return UID alone in scalar context
+	return wantarray ? ($uid, $logtoken, $new) : $uid;
+}
+
+
+########################################################
+# Get user info from the users table.
 sub getUserAuthenticate {
 	my($self, $uid_try, $passwd, $kind, $temp_ok) = @_;
 	my($newpass, $cookpasswd);
@@ -2410,22 +2476,26 @@
 # while this is going on, we won't end up with a half created user.
 # -Brian
 sub createUser {
-	my($self, $matchname, $email, $newuser) = @_;
-	return unless $matchname && $email && $newuser;
+	my($self, $matchname, $email, $newuser, $opts) = @_;
+	return unless $matchname && $newuser;
+	$opts ||= {};
+	return if !$email && !$opts->{skipchecks};
 
 	$email =~ s/\s//g; # strip whitespace from emails
 
-	return if ($self->sqlSelect(
-		"uid", "users",
-		"matchname=" . $self->sqlQuote($matchname)
-	))[0] || $self->existsEmail($email);
+	if (!$opts->{skipchecks}) {
+		return if ($self->sqlSelect(
+			"uid", "users",
+			"matchname=" . $self->sqlQuote($matchname)
+		))[0] || $self->existsEmail($email);
+	}
 
 	$self->sqlDo("SET AUTOCOMMIT=0");
 
 	my $passwd = encryptPassword(changePassword());
 	$self->sqlInsert("users", {
 		uid		=> undef,
-		realemail	=> $email,
+		realemail	=> $email || '',
 		nickname	=> $newuser,
 		matchname	=> $matchname,
 		seclev		=> 1,
@@ -2522,6 +2592,9 @@
 ########################################################
 sub setSession {
 	my($self, $name, $value) = @_;
+	if (!$value->{lasttime}) {
+		$value->{'-lasttime'} = "NOW()"
+	}
 	$self->sqlUpdate('sessions', $value, 'uid=' . $self->sqlQuote($name));
 }
 
@@ -3513,6 +3586,16 @@
 		$change_hr->{introtext} =~ s/href=\"SELF\"/href="$link_url"/;
 	}
 
+	if (defined $change_hr->{media}) {
+		if($change_hr->{media} && $change_hr->{media} =~ /<(embed|object)/i) {
+			$change_hr->{mediatype} = "video";
+		} elsif ($change_hr->{media} && $change_hr->{media} =~ /<img/i) {
+			$change_hr->{mediatype} = "image";
+		} else {
+			$change_hr->{mediatype} = "";
+		}
+	}
+
 	$change_hr->{is_archived} = $change_hr->{is_archived} ? 'yes' : 'no'
 		if defined $change_hr->{is_archived};
 	$change_hr->{in_trash} = $change_hr->{in_trash} ? 'yes' : 'no'
@@ -3531,7 +3614,7 @@
 	if (!exists($change_hr->{last_update})
 		&& !exists($change_hr->{-last_update})) {
 		my @non_cchp = grep !/^(commentcount|hitparade|hits)$/, keys %$change_hr;
-		@fh_update_fields = grep /^(title|uid|time|introtext|bodytext|primaryskid|tid|neverdisplay|media|thumb)$/, keys %$change_hr;
+		@fh_update_fields = grep /^(title|uid|time|introtext|bodytext|primaryskid|tid|neverdisplay|media|mediatype|thumb)$/, keys %$change_hr;
 		
 		if (@non_cchp > 0) {
 			$change_hr->{-last_update} = 'NOW()';
@@ -3560,6 +3643,13 @@
 
 	$change_hr->{day_published} = $change_hr->{'time'} if $change_hr->{'time'};
 
+	# what about stories set to ND?  this is not supported by our OAI code,
+	# i think, but let's update anyway -- pudge
+	if (grep /^(title|uid|time|introtext|bodytext|primaryskid|tid|neverdisplay)$/, keys %$change_hr) {
+		# this is the only place this ever changes
+		$change_hr->{-archive_last_update} = 'NOW()';
+	}
+
 	# Now we know exactly what columns have to change.  Figure out
 	# which tables they belong to.
 
@@ -4365,6 +4455,7 @@
 		"open_proxies",
 		"$col = $ip_q AND ts >= DATE_SUB(NOW(), INTERVAL $hours_back HOUR)");
 #print STDERR scalar(localtime) . " getKnownOpenProxy returning " . (defined($port) ? "'$port'" : "undef") . " for ip '$ip'\n";
+	# XXX also checkAL2(srcid, 'openproxy') here?
 	return $port;
 }
 
@@ -4380,6 +4471,7 @@
 	$xff = undef unless $xff && length($xff) >= 7
 		&& $xff =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
 	$duration = undef if !$duration;
+	# XXX also setAL2(srcid, 'openproxy', {some admin uid}) here?
 #print STDERR scalar(localtime) . " setKnownOpenProxy doing sqlReplace ip '$ip' port '$port'\n";
 	return $self->sqlReplace("open_proxies", {
 		ip =>	$ip,
@@ -5130,6 +5222,7 @@
 my %_al2_types_by_id = ( );
 sub getAL2TypeById {
 	my($self, $al2tid) = @_;
+	return undef if !$al2tid;
 	# Return from cache if available.
 	return $_al2_types_by_id{$al2tid} if defined($_al2_types_by_id{$al2tid});
 	# Need to scan the hash.
@@ -5192,6 +5285,7 @@
 		map { $self->getAL2TypeById($_) }
 		sort { $a <=> $b }
 		map { $al2types->{$_}{al2tid} }
+		grep { exists $al2types->{$_} }
 		keys %$type_hr;
 	for my $type (@types) {
 		# undef for a type field means "don't change or log anything"
@@ -5532,7 +5626,7 @@
 sub currentAdmin {
 	my($self) = @_;
 	my $aids = $self->sqlSelectAll(
-		'nickname,lasttime,lasttitle,last_subid,last_sid,sessions.uid,last_fhid',
+		'nickname,lasttime,lasttitle,last_subid,last_sid,sessions.uid,last_fhid,last_action',
 		'sessions,users',
 		'sessions.uid=users.uid GROUP BY sessions.uid'
 	);
@@ -5968,7 +6062,7 @@
 	# order is irrelevant -- pudge
 	my $order = $sign eq '<' ? 'DESC' : 'ASC';
 
-	$where .= " AND sid != '$story->{sid}'" if !$options->{no_story};
+	$where .= " AND sid != '$story->{sid}'" if !$options->{no_story} && $story->{sid};
 	my $timebase = $story ? $self->sqlQuote($story->{time}) : "NOW()";
 	$where .= " AND DATE_SUB($timebase, INTERVAL $options->{hours_back} HOUR) " if $options->{hours_back};
 	$where .= " AND DATE_ADD($timebase, INTERVAL $options->{hours_forward} HOUR) " if $options->{hours_forward};
@@ -6311,11 +6405,10 @@
 	for my $cid (keys %$more_comment_text) {
 		my $abbreviate = $abbreviate_ok && $comments->{$cid}{class} eq 'oneline';
 		my $original_text = $more_comment_text->{$cid};
+		my $this_max_len = $abbreviate ? $abbreviate_len : $max_len;
 		if (	   $possible_chop
 			&& !($opt->{cid} && $opt->{cid} eq $cid)
-			&& $comments->{$cid}{len} > (
-				$abbreviate ? $abbreviate_len : $max_len
-			)
+			&& ($comments->{$cid}{len} > ($this_max_len + 256))
 		) {
 			# We remove the domain tags so that strip_html will not
 			# consider </a blah> to be a non-approved tag.  We'll
@@ -6323,7 +6416,7 @@
 			# the comment down to size, then massage it to make sure
 			# we still have good HTML after the chop.
 			my $abbrev_text = parseDomainTags($more_comment_text->{$cid}, 0, 1, 1);
-			my $this_len = $max_len;
+			my $this_len = $this_max_len;
 			if ($abbreviate) {
 				my $str = $abbrev_text;
 				# based on revertQuote() ... we replace the unused
@@ -6368,6 +6461,7 @@
 				unless ($bail) {
 					$str =~ s/(?<!<)(<[^<>]+>)/'<<'.length($1).'>>'/ge;
 
+					# count up where we're at
 					my $plen = $this_len = 0;
 					while ($str =~ /([^<>]|<<(\d+)>>)/g) {
 						my $len1 = length $1;
@@ -6377,7 +6471,7 @@
 							$this_len += $len1;
 							$plen += $len1;
 						}
-						last if $plen >= $abbreviate_len;
+						last if $plen >= $this_max_len + 256; # rest getting cut anyway
 					}
 				}
 			}
@@ -6513,6 +6607,73 @@
 }
 
 #######################################################
+sub saveCommentReadLog {
+	my($self, $comments, $discussion_id, $uid) = @_;
+
+	$uid ||= getCurrentUser('uid');
+	return if isAnon($uid);
+
+	my($mcd, $mcdkey);
+	if (@$comments) {
+		$mcd = $self->getMCD;
+		$mcdkey = "$self->{_mcd_keyprefix}:cmr:$uid:$discussion_id";
+	}
+
+	if ($mcd) {
+		$mcd->delete($mcdkey);
+	}
+
+	# cache inserts?
+	for my $cid (@$comments) {
+		$self->sqlInsert('users_comments_read_log', {
+			uid            => $uid,
+			discussion_id  => $discussion_id,
+			cid            => $cid
+		}, { ignore => 1 });
+	}
+
+	if ($mcd) {
+		my $comments_read = $self->getCommentReadLog($discussion_id, $uid, 1);
+		$mcd->set($mcdkey, $comments_read) if $comments_read;
+	}
+
+	1;
+}
+
+#######################################################
+sub getCommentReadLog {
+	my($self, $discussion_id, $uid, $no_mcd) = @_;
+
+	$uid ||= getCurrentUser('uid');
+	return if isAnon($uid);
+
+	my($mcd, $mcdkey);
+	if (!$no_mcd) {
+		$mcd = $self->getMCD;
+		$mcdkey = "$self->{_mcd_keyprefix}:cmr:$uid:$discussion_id";
+	}
+
+	my $comments_read;
+	if ($mcd) {
+		$comments_read = $mcd->get($mcdkey);
+		return $comments_read if $comments_read;
+	}
+
+	$comments_read = $self->sqlSelectAllKeyValue(
+		'cid, 1',
+		'users_comments_read_log',
+		'uid=' . $self->sqlQuote($uid) .
+		' AND discussion_id=' . $self->sqlQuote($discussion_id)
+	) or return;
+
+	if ($mcd) {
+		$mcd->add($mcdkey, $comments_read);
+	}
+
+	return $comments_read;
+}
+
+#######################################################
 sub getSubmissionsByNetID {
 	my($self, $id, $field, $limit, $options) = @_;
 	my $mp_tid = getCurrentStatic('mainpage_nexus_tid');
@@ -7590,6 +7751,11 @@
 		$story->{sid} = createSid();
 		my $sid_ok = 0;
 		while ($sid_ok == 0) {
+			# we rely on logic in setStory() later to properly
+			# set up the data for a story, so we can't someday
+			# just change this to do an insert of all the story
+			# data, we do need to continue pass it through
+			# setStory()
 			$sid_ok = $self->sqlInsert('stories',
 				{ sid => $story->{sid} },
 				{ ignore => 1 } ); # don't need error messages
@@ -8229,7 +8395,8 @@
 		karma_adj =>			{ -10 => 'Terrible',	-1 => 'Bad',	    0 => 'Neutral',
 						   12 => 'Positive',	25 => 'Good',	99999 => 'Excellent' },
 		mod_up_points_needed =>		{ },
-		m2_consequences =>		{ 0.00 => [qw(  0    +2   -100 -1   )],
+						#          m2_f_t m2_u_t  m1_t m1_k
+		m2_consequences =>		{ 0.00 => [qw( -5    +2   -100 -1   )],
 						  0.15 => [qw( -2    +1    -40 -1   )],
 						  0.30 => [qw( -0.5  +0.5  -20  0   )],
 						  0.35 => [qw(  0     0    -10  0   )],
@@ -8238,7 +8405,7 @@
 						  0.70 => [qw(  0     0     +2  0   )],
 						  0.80 => [qw( +0.01 -1     +3  0   )],
 						  0.90 => [qw( +0.02 -2     +4  0   )],
-						  1.00 => [qw( +0.05  0     +5 +0.5 )],	},
+						  1.00 => [qw( +0.05 -5     +5 +0.5 )],	},
 		m2_consequences_repeats =>	{ 3 => -4, 5 => -12, 10 => -100 },
 		# 40=0|30=Mainpage|20=0|10=Sectional|0=0
 		topic_popup_weights	=>	{ 40 => 0, 30 => 'Mainpage', 20 => 0, 10 => 'Sectional', 0 => 0 },
@@ -8445,7 +8612,7 @@
 # prettier compromise.  I'm just saying. - Jamie
 sub autoUrl {
 	my($self, $section, @data) = @_;
-	my $data = join ' ', @data;
+	my $data = @data ? join(' ', @data) : '';
 	my $user = getCurrentUser();
 	my $form = getCurrentForm();
 
@@ -8812,7 +8979,7 @@
 sub getStoidFromSid {
 	my($self, $sid) = @_;
 	return undef if !$sid;
-	return undef if $sid !~ regexSid();
+	return undef if $sid !~ regexSid(1);
 	if (my $stoid = $self->{_sid_conversion_cache}{$sid}) {
 		return $stoid;
 	}
@@ -10390,7 +10557,7 @@
 		$hashref->{passwd} = encryptPassword($hashref->{passwd}, $uid);
 	}
 	if ($hashref->{people}) {
-		$hashref->{"-people"} = "0x" . unpack("H*", freeze($hashref->{people}));
+		$hashref->{"-people"} = "0x" . unpack("H*", nfreeze($hashref->{people}));
 		delete($hashref->{people});
 	}
 	if (exists $hashref->{slashboxes}) {
@@ -10936,9 +11103,10 @@
 			} else {
 				my $this_info = $clout_info->{$clid};
 				my $clout_obj = getObject($this_info->{class}, { db_type => 'reader' });
-				$this_clout = $clout_obj->getUserClout($answer);
+				$this_clout = $clout_obj->getUserClout($answer) if $clout_obj;
 			}
-			$answer->{clout}{ $clout_types->{$clid} } = $this_clout;
+			$answer->{clout}{ $clout_types->{$clid} } = $this_clout
+				if defined($this_clout);
 		}
 	} elsif (ref($params) eq 'ARRAY' && @$params) {
 		my $param_list = join(",", map { $self->sqlQuote($_) } @$params);
@@ -12082,7 +12250,6 @@
 
 # Given a globjid, returns its globj_type and target_id.  Returns
 # undef if the object does not exist.
-# XXX should REALLY optimize to work with a list
 # XXX should memcached
 
 sub getGlobjTarget {
@@ -12097,6 +12264,23 @@
 	return ($types->{$gtid}, $target_id);
 }
 
+# Given an arrayref of globjids, returns a hashref where each key is a
+# globjid and its value is an arrayref of its gtid,target_id.
+# XXX should memcached
+
+sub getGlobjTargets {
+	my($self, $globjid_ar) = @_;
+	return { } if !$globjid_ar || !@$globjid_ar;
+
+	my $target_hr = { };
+	my $in_str = join(',', grep /^\d+$/, @$globjid_ar);
+	my $ar_ar = $self->sqlSelectAll('globjid, gtid, target_id', 'globjs', "globjid IN ($in_str)");
+	for my $ar (@$ar_ar) {
+		$target_hr->{ $ar->[0] } = [ $ar->[1], $ar->[2] ];
+	}
+	return $target_hr;
+}
+
 # Returns the string associated with a single globj's admin note.
 # XXX should memcached
 
@@ -12523,11 +12707,14 @@
 
 	my $user = getCurrentUser();
 
+	return if !$submatch;
+
 	my $noid = $self->sqlSelect('noid','submissions_notes',
 		'submatch=' . $self->sqlQuote($submatch));
 
+
 	$self->sqlInsert('submissions_notes', {
-       		submatch        => $submatch,
+		submatch        => $submatch,
 		subnote         => $subnote,
 		uid             => $user->{uid},
                 '-time'         => 'NOW()',
@@ -12678,6 +12865,42 @@
 	return $answer;
 }
 
+sub isCommentPromoted {
+	my($self, $cid) = @_;
+	return $self->sqlCount("comment_promote_log", "cid=" . $self->sqlQuote($cid));
+}
+
+sub logCommentPromotion {
+	my($self, $cid) = @_;
+	$self->sqlInsert("comment_promote_log", { cid => $cid, -ts => "NOW()" });
+}
+
+sub createProject {
+	my($self, $data) = @_;
+	$self->sqlInsert("projects", $data);
+	my $pid = $self->getLastInsertId();
+	return $pid;
+}
+
+sub getProject {
+	my $answer = _genericGetCache({
+		table		=> 'projects',
+		table_prime	=> 'id',
+		arguments	=> \@_,
+	});
+	return $answer;
+}
+
+sub setProject {
+	_genericSet('projects', 'id', '', @_);
+}
+
+sub getProjectByName {
+	my ($self, $name) = @_;
+	my $name_q = $self->sqlQuote($name);
+	return $self->sqlSelectHashref("*","projects", "unixname=$name_q");
+}
+
 sub _getStorySelfLink {
 	my($self, $stoid, $change_hr) = @_; 
 	my $story = $self->getStory($stoid);

Modified: slashjp/trunk/Slash/DB/Oracle/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/Oracle/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Oracle/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::DB::Oracle',
-    'VERSION_FROM' => 'Oracle.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/DB/Oracle/Oracle.pm
===================================================================
--- slashjp/trunk/Slash/DB/Oracle/Oracle.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Oracle/Oracle.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,15 +1,15 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::DB::Oracle;
 
 use strict;
-use vars qw($VERSION @ISA);
+use vars qw(@ISA);
+use Slash::Constants ();
 
 @ISA = qw( Slash::DB::Utility );
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 1;
 

Modified: slashjp/trunk/Slash/DB/PostgreSQL/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/PostgreSQL/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/PostgreSQL/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::DB::PostgreSQL',
-    'VERSION_FROM' => 'PostgreSQL.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/DB/PostgreSQL/PostgreSQL.pm
===================================================================
--- slashjp/trunk/Slash/DB/PostgreSQL/PostgreSQL.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/PostgreSQL/PostgreSQL.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,19 +1,17 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::DB::PostgreSQL;
 use strict;
 use Slash::Utility;
 use URI ();
-use vars qw($VERSION);
 
 use base 'Slash::DB';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # BENDER: I hate people who love me.  And they hate me.
 

Modified: slashjp/trunk/Slash/DB/Static/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/Static/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Static/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,5 +4,4 @@
 WriteMakefile();
 #WriteMakefile(
 #    'NAME'	=> 'Slash::DB',
-#    'VERSION_FROM' => 'DB.pm', # finds $VERSION
-#);
+##);

Modified: slashjp/trunk/Slash/DB/Static/MySQL/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/Static/MySQL/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Static/MySQL/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::DB::Static::MySQL',
-    'VERSION_FROM' => 'MySQL.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/DB/Static/MySQL/MySQL.pm
===================================================================
--- slashjp/trunk/Slash/DB/Static/MySQL/MySQL.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Static/MySQL/MySQL.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::DB::Static::MySQL;
 
@@ -17,10 +16,9 @@
 use Encode 'encode_utf8';
 use Time::HiRes;
 use URI ();
-use vars qw($VERSION);
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: Hey, thinking hurts 'em! Maybe I can think of a way to use that.
 
@@ -883,7 +881,7 @@
 		&& $num_top_comments < $num_wanted
 	) {
 		my $comment = $self->sqlSelectArrayRef(
-			"stories.sid, title, cid, subject, date, nickname, comments.points, comments.reason",
+			"stories.sid, title, cid, subject, date, nickname, comments.points, comments.reason, date",
 			"comments, stories, story_text, users",
 			"cid=$cids->[$num_top_comments]->[0]
 				AND stories.stoid = story_text.stoid
@@ -1088,6 +1086,17 @@
 	return \%index;
 }
 
+sub getSkinIndex {
+	my($self) = @_;
+	my @skins;
+	my $skins = $self->getSkins;
+	foreach (sort {$skins->{$a}{title} cmp $skins->{$b}{title}} keys %$skins) {
+		next if $skins->{$_}{skinindex} eq "no";
+		push @skins, $skins->{$_};
+	}
+	return \@skins;
+}
+
 # XXXSRCID This needs to actually be, like, written.
 sub recalcAL2 {
         my($self, $srcid) = @_;
@@ -1836,12 +1845,12 @@
 		my $lookback_id = $max_id - $rowsback;
 		$lookback_id = 1 if $lookback_id < 1;
 		# We don't count images, and we only count rss hits if
-		# they are dynamic.
+		# they are dynamic.  We don't count badge hits at all.
 		my($count, $time) = $self->sqlSelect(
 			"COUNT(*), UNIX_TIMESTAMP(MAX(ts)) - UNIX_TIMESTAMP(MIN(ts))",
 			"accesslog",
 			"id >= $lookback_id
-			 AND op != 'image'
+			 AND op NOT IN ('image', 'slashdot-it')
 			 AND (op != 'rss' OR static = 'no')");
 		if (!$count || $count < 10) {
 			# Very small count;  site is almost unused.
@@ -1922,20 +1931,31 @@
 }
 
 sub getUrlsNeedingFirstCheck {
-	my($self) = @_;
-	return $self->sqlSelectAllHashrefArray("*", "urls", "last_attempt IS NULL", "ORDER BY url_id ASC");
+	my($self, $options) = @_;
+	my $constants = getCurrentStatic();
+	$options ||= {};
+	$options->{limit} ||= 50;
+
+	my($extra_tables,$extra_where) = ('','');
+
+	if ($options->{limit_to_firehose} && $constants->{plugin}{FireHose}) {
+		$extra_tables = ",firehose";
+		$extra_where = "AND urls.url_id=firehose.url_id";
+	}
+	return $self->sqlSelectAllHashrefArray("*", "urls $extra_tables", "last_attempt IS NULL $extra_where", "ORDER BY urls.url_id ASC LIMIT $options->{limit}");
 }
 
 sub getUrlsNeedingRefresh {
-	my($self, $limit) = @_;
-	$limit ||= 50;
+	my($self, $options) = @_;
+	$options ||= {};
+	$options->{limit} ||= 50;
 	return $self->sqlSelectAllHashrefArray(
 		"*", 
 		"urls", 
 		"last_attempt IS NOT NULL 
 		 AND believed_fresh_until IS NOT NULL 
 		 AND believed_fresh_until < NOW()", 
-		"ORDER BY believed_fresh_until ASC LIMIT $limit"
+		"ORDER BY believed_fresh_until ASC LIMIT $options->{limit}"
 	);
 }
 

Modified: slashjp/trunk/Slash/DB/Static/Oracle/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/Static/Oracle/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Static/Oracle/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::DB::Static::Oracle',
-    'VERSION_FROM' => 'Oracle.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/DB/Static/Oracle/Oracle.pm
===================================================================
--- slashjp/trunk/Slash/DB/Static/Oracle/Oracle.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Static/Oracle/Oracle.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::DB::Static::Oracle;
 use strict;
@@ -9,9 +8,8 @@
 use Slash::DB::Utility;
 use Slash::Utility;
 use URI ();
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 1;
 

Modified: slashjp/trunk/Slash/DB/Static/PostgreSQL/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/Static/PostgreSQL/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Static/PostgreSQL/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::DB::Static::PostgreSQL',
-    'VERSION_FROM' => 'PostgreSQL.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/DB/Static/PostgreSQL/PostgreSQL.pm
===================================================================
--- slashjp/trunk/Slash/DB/Static/PostgreSQL/PostgreSQL.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Static/PostgreSQL/PostgreSQL.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,17 +1,15 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::DB::Static::PostgreSQL;
 use strict;
-use vars qw($VERSION);
 use Slash::Utility;
 
 use base 'Slash::DB::PostgreSQL';
 use base 'Slash::DB::Static::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: Whoa, slow down. You're going a mile a minute.
 

Modified: slashjp/trunk/Slash/DB/Utility/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/DB/Utility/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Utility/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::DB::Utility',
-    'VERSION_FROM' => 'Utility.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/DB/Utility/Utility.pm
===================================================================
--- slashjp/trunk/Slash/DB/Utility/Utility.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/DB/Utility/Utility.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::DB::Utility;
 
@@ -10,9 +9,8 @@
 use Slash::Utility;
 use DBIx::Password;
 use Time::HiRes;
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: Bender, if this is some kind of scam, I don't get it.  You already
 # have my power of attorney.

Modified: slashjp/trunk/Slash/Display/Display.pm
===================================================================
--- slashjp/trunk/Slash/Display/Display.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Display/Display.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Display;
 
@@ -48,11 +47,11 @@
 use Template 2.07;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT @EXPORT_OK $CONTEXT %FILTERS $TEMPNAME);
+use vars qw($CONTEXT %FILTERS $TEMPNAME);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(slashDisplay slashDisplayName);
- @ EXPORT_OK = qw(get_template);
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(slashDisplay slashDisplayName);
+our @EXPORT_OK = qw(get_template);
 my(%objects);
 
 # FRY: That doesn't look like an L at all. Unless you count lowercase.
@@ -178,6 +177,8 @@
 	)};
 
 	local $TEMPNAME = 'anon';
+	my $tmpl_id_attr = '';
+	my $tmpl_name_attr = '';
 	unless (ref $name) {
 		# we don't want to have to call this here, but because
 		# it is cached the performance hit is generally light,
@@ -195,6 +196,9 @@
 
 		$TEMPNAME = "ID $tempdata->{tpid}, " .
 			"$name;$tempdata->{page};$tempdata->{skin}";
+
+		$tmpl_id_attr = " template-id=\"$tempdata->{tpid}\"";
+		$tmpl_name_attr = " template-name=\"$name;$tempdata->{page};$tempdata->{skin}\"";
 	}
 
 	# copy parent data structure so it is not modified,
@@ -225,10 +229,12 @@
 	# template_show_comments == 1		show them if !$opt->{Nocomm}
 	# template_show_comments == 2		always show them - debug only!
 
+	my $tmpl_span_attrs = $tmpl_id_attr . $tmpl_name_attr . ' style="display:none"';
+
 	my $show_comm = $constants->{template_show_comments} ? 1 : 0;
 	$show_comm &&= 0 if $opt->{Nocomm} && $constants->{template_show_comments} < 2;
 	$show_comm &&= 0 if $user->{mobile} && $constants->{template_show_comments} < 2;
-	$out = "\n\n<!-- start template: $TEMPNAME -->\n\n$out\n\n<!-- end template: $TEMPNAME -->\n\n"
+	$out = "\n\n<span class=\"start-template\"$tmpl_span_attrs></span>\n\n$out\n\n<span class=\"end-template\"$tmpl_span_attrs></span>\n\n"
 		if $show_comm;
 
 	if ($err) {

Modified: slashjp/trunk/Slash/Display/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Display/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Display/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Display',
-    'VERSION_FROM' => 'Display.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Display/Plugin/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Display/Plugin/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Display/Plugin/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Display::Plugin',
-    'VERSION_FROM' => 'Plugin.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Display/Plugin/Plugin.pm
===================================================================
--- slashjp/trunk/Slash/Display/Plugin/Plugin.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Display/Plugin/Plugin.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Display::Plugin;
 
@@ -57,13 +56,12 @@
 =cut
 
 use strict;
-use vars qw($VERSION $AUTOLOAD);
+use vars qw($AUTOLOAD);
 use Slash ();
-use Slash::Constants ();
 use Slash::Utility ();
 use base qw(Template::Plugin);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # BENDER: Forget your stupid theme park!  I'm gonna make my own!
 # With hookers!  And blackjack!  In fact, forget the theme park!
@@ -72,16 +70,25 @@
 sub _populate {
 	return if %subs;
 	# mmmmmm, agic
+	# we are taking all the symbols to exported from certain packages,
+	# and adding them as coderefs to @subs.  then in AUTOLOAD below,
+	# when that symbol is called, we put it in its proper TT context,
+	# and execute it.  simple!
 	no strict 'refs';
-	for my $pkg (qw(Slash Slash::Utility)) {
-		@subs{@{"${pkg}::EXPORT"}} =
-			map { *{"${pkg}::$_"}{CODE} } @{"${pkg}::EXPORT"};
+	for my $pkg (qw(Slash Slash::Utility)) {       # for these packages ...
+	                                               # (read rest bottom-to-top):
+		@subs{@{"${pkg}::EXPORT"}} =           # save the coderefs for later!
+			map  { *{"${pkg}::$_"}{CODE} } # ... get the coderef
+			grep { *{"${pkg}::$_"}{CODE} } # if they have a coderef ...
+			@{"${pkg}::EXPORT"};           # get the syms from @EXPORT
 	}
 
-	# all constants in EXPORT_OK
+	# Slash::Constants uses @EXPORT_OK, not @EXPORT
 	for my $pkg (qw(Slash::Constants)) {
 		@subs{@{"${pkg}::EXPORT_OK"}} =
-			map { *{"${pkg}::$_"}{CODE} } @{"${pkg}::EXPORT_OK"};
+			map  { *{"${pkg}::$_"}{CODE} }
+			grep { *{"${pkg}::$_"}{CODE} }
+			@{"${pkg}::EXPORT_OK"};
 	}
 
 	$subs{version} = sub { Slash->VERSION };
@@ -111,7 +118,8 @@
 sub AUTOLOAD {
 	# pull off first param before sending to function;
 	# that's the whole reason we have AUTOLOAD here,
-	# to de-OOP the call
+	# to de-OOP the call, since TT wants it to all be
+	# OOP-ified and we don't.
 	my $self = shift;
 	(my $name = $AUTOLOAD) =~ s/^.*://;
 	return if $name eq 'DESTROY';

Modified: slashjp/trunk/Slash/Display/Provider/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Display/Provider/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Display/Provider/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Display::Provider',
-    'VERSION_FROM' => 'Provider.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Display/Provider/Provider.pm
===================================================================
--- slashjp/trunk/Slash/Display/Provider/Provider.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Display/Provider/Provider.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Display::Provider;
 
@@ -30,13 +29,13 @@
 =cut
 
 use strict;
-use vars qw($VERSION $DEBUG);
+use vars qw($DEBUG);
 use base qw(Template::Provider);
 use File::Spec::Functions;
 use Slash::Utility::Environment;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
-$DEBUG     = $Template::Provider::DEBUG || 0 unless defined $DEBUG;
+our $VERSION = $Slash::Constants::VERSION;
+$DEBUG       = $Template::Provider::DEBUG || 0 unless defined $DEBUG;
 
 # BENDER: Oh, no room for Bender, huh?  Fine.  I'll go build my own lunar
 # lander.  With blackjack.  And hookers.  In fact, forget the lunar lander

Modified: slashjp/trunk/Slash/Hook/Hook.pm
===================================================================
--- slashjp/trunk/Slash/Hook/Hook.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Hook/Hook.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,20 +1,17 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Hook;
 use strict;
 use Slash::Utility::Environment; # avoid cross-caller issues
-use vars qw($VERSION);
 
 # Arrrr Matey...
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(slashHook);
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(slashHook);
 
 my %classes;
 

Modified: slashjp/trunk/Slash/Hook/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Hook/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Hook/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Hook',
-    'VERSION_FROM' => 'Hook.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Hook/Sample/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Hook/Sample/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Hook/Sample/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Hook::Sample',
-    'VERSION_FROM' => 'Sample.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Hook/Sample/Sample.pm
===================================================================
--- slashjp/trunk/Slash/Hook/Sample/Sample.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Hook/Sample/Sample.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Hook::Sample;
 use strict;
@@ -9,11 +8,10 @@
 use Slash;
 use Slash::DB;
 use Slash::Utility;
-use vars qw($VERSION);
 
 # Shake well, serve warm.
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 
 sub sample {

Modified: slashjp/trunk/Slash/Install/Install.pm
===================================================================
--- slashjp/trunk/Slash/Install/Install.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Install/Install.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Install;
 use strict;
@@ -12,12 +11,11 @@
 use File::Find;
 use File::Path;
 use File::Spec;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 
 # BENDER: Like most of life's problems, this one can be solved with bending.
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;

Modified: slashjp/trunk/Slash/Install/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Install/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Install/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Install',
-    'VERSION_FROM' => 'Install.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash',
-    'VERSION_FROM' => 'Slash.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Slash.pm
===================================================================
--- slashjp/trunk/Slash/Slash.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Slash.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash;
 
@@ -35,19 +34,14 @@
 use Time::HiRes;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-$VERSION   	= '2.005000';  # v2.5.0
-# note: those last two lines of functions will be moved elsewhere
- @ EXPORT		= qw(
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(
 	getData gensym displayStory displayRelatedStories dispStory
 	getOlderStories getOlderDays getOlderDaysFromDay
 );
 
 
-# this is the worst damned warning ever, so SHUT UP ALREADY!
-#$SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /Use of uninitialized value/ };
-
 # BENDER: Fry, of all the friends I've had ... you're the first.
 
 
@@ -462,6 +456,8 @@
 	
 	for ($start..$end) {
 		my $the_day = $slashdb->getDayFromDay($day, $_, $options);
+		next if $the_day == $today && $options->{skip_add_today} && !$options->{force};
+
 		if (($the_day < $today) || $options->{show_future_days}) {
 			push @$days, $the_day; 
 		}

Modified: slashjp/trunk/Slash/Slashboxes/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Slashboxes/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Slashboxes/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Slashboxes',
-    'VERSION_FROM' => 'Slashboxes.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Slashboxes/Slashboxes.pm
===================================================================
--- slashjp/trunk/Slash/Slashboxes/Slashboxes.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Slashboxes/Slashboxes.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: Slashboxes.pm,v 1.2 2007/02/21 02:49:11 pudge Exp $
 
 package Slash::Slashboxes;
 
@@ -11,10 +10,9 @@
 use Slash::Utility;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision: 1.2 $ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(getUserSlashboxes displaySlashboxes);
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(getUserSlashboxes displaySlashboxes);
 
 #################################################################
 sub getUserSlashboxes {


Property changes on: slashjp/trunk/Slash/Test/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Test/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Test/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Test/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Test',
-    'VERSION_FROM' => 'Test.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Test/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Test/Test.pm
===================================================================
--- slashjp/trunk/Slash/Test/Test.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Test/Test.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Test;
 
@@ -88,7 +87,7 @@
 
 use Data::Dumper;
 use File::Spec::Functions;
-use Storable qw(freeze thaw);
+use Storable qw(nfreeze thaw);
 
 use Slash;
 use Slash::Constants ':all';
@@ -98,17 +97,16 @@
 
 use strict;
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT = (
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT = (
 	@Slash::EXPORT,
 	@Slash::Constants::EXPORT_OK,
 	@Slash::Display::EXPORT,
 	@Slash::Utility::EXPORT,
 	@Slash::XML::EXPORT,
 	@Data::Dumper::EXPORT,
-	qw(freeze thaw),
+	qw(nfreeze thaw),
 	'slashTest',
 	'Display',
 	'Test',
@@ -191,6 +189,7 @@
 		my $object = getObject("Slash::$plugin");
 		if ($object) {
 			no strict 'refs';
+			no warnings 'once';
 			${"main::$name"} = $object;
 		}
 	}
@@ -283,7 +282,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/Test/Test.pm
___________________________________________________________________
Name: svn:executable
   - *

Copied: slashjp/trunk/Slash/Tools (from rev 741, slashjp/branches/upstream/2.5.0.218/Slash/Tools)

Modified: slashjp/trunk/Slash/Utility/Access/Access.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Access/Access.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Access/Access.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Utility::Access;
 
@@ -33,10 +32,9 @@
 use Slash::Constants qw(:web :people :messages);
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT	   = qw(
 	checkFormPost
 	formkeyError
 	formkeyHandler
@@ -463,7 +461,11 @@
 		if ($minimum_match) {
 			$number_match = "{$minimum_match,}";
 		} elsif ($ratio > 0) {
-			$number_match = "{" . int(length($text_to_test)*$ratio + 1) . ",}";
+			my $num = int(length($text_to_test)*$ratio + 1);
+			my $max = 2**15-1;
+			# temporary fix 2008-05-23
+			$num = $max if $num >= $max;
+			$number_match = "{$num,}";
 		} else {
 			$number_match = "";
 		}
@@ -595,6 +597,13 @@
 		$length = length($content_slice);
 		next if $length < 10;
 
+		# compress doesn't like wide characters.  this could in theory
+		# make it easier to run into a filter, with too many '_'
+		# characters being in a comment, but no one should be using
+		# that many wide characters in the standard English
+		# alphabet.  we can adjust filters if necessary. -- pudge
+		$content_slice =~ s/(.)/ord($1) > 2**8-1 ? '_' : $1/ge;
+
 		for (sort { $a <=> $b } keys %$limits) {
 			next unless $length >= $limits->{$_}->[0]
 				and $length <= $limits->{$_}->[1];
@@ -822,7 +831,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::Utility(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/Utility/Access/Access.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/Slash/Utility/Access/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Access/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Utility/Access/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Access/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Utility::Access',
-    'VERSION_FROM' => 'Access.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Utility/Access/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Anchor/Anchor.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Anchor/Anchor.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Anchor/Anchor.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Utility::Anchor;
 
@@ -35,10 +34,9 @@
 use Slash::Utility::Environment;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(
 	http_send
 	get_etag
 	header
@@ -755,7 +753,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::Utility(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/Utility/Anchor/Anchor.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/Slash/Utility/Anchor/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Anchor/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Utility/Anchor/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Anchor/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Utility::Anchor',
-    'VERSION_FROM' => 'Anchor.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Utility/Anchor/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Comments/Comments.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Comments/Comments.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Comments/Comments.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 package Slash::Utility::Comments;
 
@@ -32,13 +31,12 @@
 use Slash::Constants qw(:strip :people :messages);
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT		= qw(
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(
 	constrain_score dispComment displayThread printComments
 	jsSelectComments commentCountThreshold commentThresholds discussion2
-	selectComments preProcessReplyForm
+	selectComments preProcessReplyForm makeCommentBitmap parseCommentBitmap
 	getPoints preProcessComment postProcessComment prevComment saveComment
 );
 
@@ -76,6 +74,10 @@
 		delete $form->{cchp};
 	}
 
+	my $comments_read = !$user->{is_anon}
+		? $slashdb->getCommentReadLog($discussion->{id}, $user->{uid})
+		: {};
+
 	my $commentsort = defined $options->{commentsort}
 		? $options->{commentsort}
 		: $user->{commentsort};
@@ -207,14 +209,9 @@
 			}
 		}
 
-		my @seen;
-		my $lastcid = 0;
-		my %check = (%{$options->{existing}}, map { $_->{cid} => 1 } @new_comments);
-		for my $this_cid (sort { $a <=> $b } keys(%check)) {
-			push @seen, $lastcid ? $this_cid - $lastcid : $this_cid;
-			$lastcid = $this_cid;
-		}
-		$comments->{0}{d2_seen} = join ',', @seen;
+		$comments->{0}{d2_seen} = makeCommentBitmap({
+			%{$options->{existing}}, map { $_->{cid} => 1 } @new_comments
+		});
 
 		@new_comments = sort { $a->{cid} <=> $b->{cid} } @new_comments;
 		($oldComment, $thisComment) = ($thisComment, \@new_comments);
@@ -260,6 +257,10 @@
 		$comments->{$C->{cid}}{kids} = $tmpkids || [];
 		$comments->{$C->{cid}}{visiblekids} = $tmpvkids || 0;
 
+		$comments->{$C->{cid}}{has_read} = $comments_read->{$C->{cid}};
+		$user->{state}{d2_defaultclass}{$C->{cid}} = 'oneline'
+			if $user->{d2_reverse_switch} && $comments_read->{$C->{cid}};
+
 		# The comment pushes itself onto its parent's
 		# kids array.
 		push @{$comments->{$C->{pid}}{kids}}, $C->{cid};
@@ -321,16 +322,18 @@
 					if ($cid && $C->{pid} < $cid) {
 						$user->{state}{d2_defaultclass}{$C->{pid}} = 'oneline';
 						$parent = $old_comments{ $C->{pid} };
+						$parent->{has_read} = $comments_read->{$C->{pid}};
 						push @new_seen, $C->{pid};
 						$count++;
 					} else {
 						$parent = {
-							cid    => $C->{pid},
-							pid    => ($old_comments{ $C->{pid} } && $old_comments{ $C->{pid} }{ pid }) || 0,
-							opid   => ($old_comments{ $C->{pid} } && $old_comments{ $C->{pid} }{ original_pid }) || 0,
-							kids   => [ ],
-							points => -2,
-							dummy  => 1,
+							cid      => $C->{pid},
+							pid      => ($old_comments{ $C->{pid} } && $old_comments{ $C->{pid} }{ pid }) || 0,
+							opid     => ($old_comments{ $C->{pid} } && $old_comments{ $C->{pid} }{ original_pid }) || 0,
+							kids     => [ ],
+							points   => -2,
+							dummy    => 1,
+							has_read => $comments_read->{$C->{pid}},
 							%$parent,
 						};
 						$parent->{opid} ||= $parent->{pid};
@@ -351,18 +354,9 @@
 			}
 		}
 
-		# fix d2_seen
-		my @seen;
-		my $lastcid = 0;
-		for my $this_cid (sort { $a <=> $b } @new_seen) {
-			push @seen, $lastcid ? $this_cid - $lastcid : $this_cid;
-			$lastcid = $this_cid;
-		}
-		my @old_seen = split /,/, $comments->{0}{d2_seen};
-		if (@seen && @old_seen) {
-			$old_seen[0] = $old_seen[0] - $lastcid;
-		}
-		$comments->{0}{d2_seen} = join ',', @seen, @old_seen;
+		# fix d2_seen to include new cids ... these will all be after
+		# the last element in seen, which makes this simpler
+		$comments->{0}{d2_seen} = makeCommentBitmap(\@new_seen, $comments->{0}{d2_seen});
 	}
 
 ##slashProf("", "sC d2 fudging");
@@ -421,6 +415,7 @@
 		my @keys = qw(pid points uid);
 		for my $cid (grep $_, keys %$comments) {
 			@{$comments_new->{$cid}}{@keys} = @{$comments->{$cid}}{@keys};
+			$comments_new->{$cid}{read} = $comments->{$cid}{has_read} ? 1 : 0;
 			$comments_new->{$cid}{opid} = $comments->{$cid}{original_pid};
 			$comments_new->{$cid}{kids} = [sort { $a <=> $b } @{$comments->{$cid}{kids}}];
 
@@ -445,9 +440,11 @@
 	my $anon_thresh   = Data::JavaScript::Anon->anon_dump($thresh_totals || {});
 	s/\s+//g for ($anon_thresh, $anon_roots, $anon_rootsh);
 
-	$user->{is_anon}       ||= 0;
-	$user->{is_admin}      ||= 0;
-	$user->{is_subscriber} ||= 0;
+	$user->{is_anon}          ||= 0;
+	$user->{is_admin}         ||= 0;
+	$user->{is_subscriber}    ||= 0;
+	$user->{state}{d2asp}     ||= 0;
+	$user->{d2_comment_order} ||= 0;
 	my $root_comment = $user->{state}{selectComments}{cidorpid} || 0;
 
 	my $extra = '';
@@ -460,6 +457,9 @@
 	if ($user->{d2_keybindings_switch}) {
 		$extra .= "d2_keybindings_off = 1;\n";
 	}
+	if ($user->{d2_reverse_switch}) {
+		$extra .= "d2_reverse_shift = 1;\n";
+	}
 
 	# maybe also check if this ad should be running with some other var?
 	# from ads table? -- pudge
@@ -484,12 +484,14 @@
 root_comments_hash = $anon_rootsh;
 max_cid = $max_cid;
 
+d2_comment_order = $user->{d2_comment_order};
 user_uid = $user->{uid};
 user_is_anon = $user->{is_anon};
 user_is_admin = $user->{is_admin};
 user_is_subscriber = $user->{is_subscriber};
 user_threshold = $threshold;
 user_highlightthresh = $highlightthresh;
+user_d2asp = $user->{state}{d2asp};
 
 discussion_id = $id;
 
@@ -574,7 +576,46 @@
 	return $newcomments;
 }
 
+sub parseCommentBitmap {
+	my($bitmap) = @_;
+	return {} unless $bitmap;
+	my $lastcid = 0;
+	my %comments;
+	for my $cid (split /,/, $bitmap) {
+		$cid = $lastcid ? $lastcid + $cid : $cid;
+		$comments{$cid} = 1;
+		$lastcid = $cid;
+	}
+	return \%comments;
+}
 
+sub makeCommentBitmap {
+	my($comments, $old) = @_;
+	my $lastcid = 0;
+	my @bitmap;
+	for my $cid (sort { $a <=> $b } ((ref($comments) eq 'HASH')
+			? keys %$comments
+			: @$comments
+		)
+	) {
+		push @bitmap, $lastcid ? $cid - $lastcid : $cid;
+		$lastcid = $cid;
+	}
+
+	my $bitmap = join ',', @bitmap;
+
+	if ($old) {
+		return $old unless $bitmap;
+
+		my @old = split /,/, $old, 2;
+		$old[0] = $old[0] - $lastcid;
+		return join ',', $bitmap, @old;
+	}
+
+	return $bitmap;
+}
+
+
 # this really should have been getData all along
 sub getError {
 	my($value, $hashref, $nocomm) = @_;
@@ -614,8 +655,7 @@
 	my $points = $hr->{score_start} || 0;
 
 	# User can setup to give points based on size.
-#	my $len = length($C->{comment});
-	my $len = $C->{len};
+	my $len = $C->{len} || length($C->{comment});
 	if ($len) {
 		# comments.len should always be > 0, because Slash doesn't
 		# accept zero-length comments.  If it is = 0, something is
@@ -1066,6 +1106,7 @@
 		cid		=> $cid,
 		pid		=> $pid,
 		lvl		=> $lvl,
+		options		=> $options,
 	});
 #slashProf("", "printCommentsMain");
 
@@ -1658,8 +1699,7 @@
 	my $moddb = getObject("Slash::$constants->{m1_pluginname}");
 	if ($moddb) {
 		my $text = $moddb->checkDiscussionForUndoModeration($comm->{sid});
-		# XXX doesn't work for D2
-		print $text if $text;
+		print $text if $text && !discussion2($user);
 	}
 
 	my $tc = $slashdb->getVar('totalComments', 'value', 1);
@@ -2147,8 +2187,10 @@
 <div id="comment_$comment->{cid}"$classattr>
 EOT
 
+	my $new_old_comment = $comment->{has_read} ? 'oldcomment' : 'newcomment';
+
 	$return .= <<EOT if !$options->{noshow};
-	<div id="comment_top_$comment->{cid}" class="commentTop newcomment">
+	<div id="comment_top_$comment->{cid}" class="commentTop $new_old_comment">
 		<div class="title">
 $head
 $comment_links
@@ -2568,7 +2610,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id: $

Modified: slashjp/trunk/Slash/Utility/Comments/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Utility/Comments/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Comments/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Utility::Comments',
-    'VERSION_FROM' => 'Comments.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/Utility/Data/Data.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Data/Data.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Data/Data.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Utility::Data;
 
@@ -49,7 +48,6 @@
 use Encode;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
 # whitespace regex
 our $WS_RE = qr{(?: \s | </? (?:br|p) (?:\ /)?> )*}x;
@@ -63,8 +61,8 @@
 	$HTML::Tagset::linkElements{slash} = ['src', 'href'];
 }
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(
 	addDomainTags
 	createStoryTopicData
 	slashizeLinks
@@ -177,7 +175,9 @@
 # NOTE: sid is also used for discussion ID (and maybe stoid too?),
 # such as in comments.pl, so that's what the \d{1,8} is for. -- pudge
 sub regexSid {
-	return qr{\b(\d{2}/\d{2}/\d{2}/\d{3,8}|\d{1,8})\b};
+	my $anchor = shift;
+	my $sid = '(\d{2}/\d{2}/\d{2}/\d{3,8}|\d{1,8})';
+	return $anchor ? qr{^$sid$} : qr{\b$sid\b};
 }
 
 #========================================================================
@@ -1211,6 +1211,15 @@
 			# Preserve leading indents / spaces
 			# can mess up internal tabs, oh well
 			${$_[0]} =~ s/\t/    /g;			},
+	paragraph_wrap => sub {
+			# start off the text with a <p>!
+			${$_[0]} = '<p>' . ${$_[0]} unless ${$_[0]} =~ /^\s*<p>/s;
+			# this doesn't assume there will be only two BRs,
+			# but it does come after whitespace_tagify, so
+			# chances are, will be only two BRs in a row
+			${$_[0]} =~ s/(?:<br>){2}/<p>/g;
+			# make sure we don't end with a <br><p> or <br>
+			${$_[0]} =~ s/<br>(<p>|$)/$1/g;			},
 	whitespace_and_tt => sub {
 			${$_[0]} =~ s{((?:  )+)(?: (\S))?} {
 				("&nbsp; " x (length($1)/2)) .
@@ -1292,7 +1301,8 @@
 			approveCharrefs
 			breakHtml_ifwhitefix
 			whitespace_tagify
-			newline_indent			)],
+			newline_indent
+			paragraph_wrap			)],
 	HTML, [qw(
 			newline_to_local
 			trailing_whitespace
@@ -2710,6 +2720,9 @@
 	my %is_block    = map { ( lc, 1 ) } qw(p ol ul li dl dt dd blockquote quote div hr address h1 h2 h3 h4 h5 h6);
 	my %no_block    = map { ( lc, 1 ) } qw(b i strong em tt q dfn code samp kbd var cite address ins del big small span p sub sup a h1 h2 h3 h4 h5 h6);
 
+	# needs a <p> inside it
+	my %needs_p     = map { ( lc, 1 ) } qw(blockquote quote div);
+
 	# when a style tag is cut off prematurely because of a newly introduced block
 	# element, we want to re-start the style inside the block; it is not perfect,
 	# but that's why we're here, innit?
@@ -2747,6 +2760,8 @@
 		$lists_re{$list} = qr/$re/;
 	}
 
+	my $is_block_re = join '|', keys %is_block;
+
 sub balanceTags {
 	my($html, $options) = @_;
 	return '' if !defined($html) || !length($html);
@@ -2784,6 +2799,11 @@
 		$cache->{balanceTags}{$matchname} = $match = qr/$match/;
 	}
 
+	# easier to do this before we start the loop, and then fix it inside
+	# we need to make sure when a block ends, a new <p> begins
+	$html =~ s|(</(?:$is_block_re)>)|$1<p>|g;
+
+
 	## this is the main loop.  it finds a tag, any tag
 	while ($html =~ /(<(\/?)($match)\b[^>]*?( \/)?>)/sig) { # loop over tags
 		($tag, $close, $whole, $both) = (lc($3), $2, $1, $4);
@@ -2937,6 +2957,9 @@
 			# opening a new tag to be added to the stack
 			$tags{$tag}++;
 			push @stack, $tag;
+			if ($needs_p{$tag}) {
+				_substitute(\$html, '', '<p>', 1);
+			}
 
 			# we keep track of lists in an add'l stack, for
 			# the immediately above purpose, so push it on here
@@ -2976,7 +2999,12 @@
 	my($html) = @_;
 	my $p    = getCurrentStatic('xhtml') ? '<p />' : '<p>';
 
-	$$html =~ s|<p>\s*</p>|$p|g;
+	# remove consecutive <p> or <p>, <br> tags
+	1 while $$html =~ s{<p> \s* <(?: /?p | br(?:\ /)? )>} {$p}gx;
+	# remove <p> and <br> tags before beginning, or end, of blocks, or end of string
+	1 while $$html =~ s{\s* <(?: p | br(?:\ /)?) > \s*  ( $ | </?(?:$is_block_re)> )} {$1}gx;
+
+	# remove still-empty tags
 	while ($$html =~ m|<(\w+)>\s*</\1>|) {
 		$$html =~ s|<(\w+)>\s*</\1>\s*||g;
 	}
@@ -4496,7 +4524,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::Utility(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/Utility/Data/Data.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/Slash/Utility/Data/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Data/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Utility/Data/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Data/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Utility::Data',
-    'VERSION_FROM' => 'Data.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Utility/Data/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Display/Display.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Display/Display.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Display/Display.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Utility::Display;
 
@@ -31,10 +30,9 @@
 use Slash::Utility::Environment;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(
 	cleanSlashTags
 	createMenu
 	createSelect
@@ -1733,7 +1731,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::Utility(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/Utility/Display/Display.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/Slash/Utility/Display/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Display/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Utility/Display/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Display/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Utility::Display',
-    'VERSION_FROM' => 'Display.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Utility/Display/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Environment/Environment.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Environment/Environment.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Environment/Environment.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Utility::Environment;
 
@@ -28,15 +27,15 @@
 use Apache::ModuleConfig;
 use Digest::MD5 'md5_hex';
 use Time::HiRes;
+use Slash::Constants ();
 use Socket qw( inet_aton inet_ntoa );
 use Encode;
 use Encode::Guess;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(
 
 	dbAvailable
 
@@ -1347,9 +1346,13 @@
 	# ".slashdot.org" is OK.  the only way to set a cookie
 	# to a *host* is to leave the domain blank, which is
 	# why we set the first cookie with no domain. -- pudge
+	# unless domain does not match the root domain -- pudge
 
 	# domain must start with a '.' and have one more '.'
-	# embedded in it, else we ignore it
+	# embedded in it, else we ignore it, so you can
+	# enter an *invalid* value in skins.cookiedomain to
+	# override constants.cookiedomain, and *not* have
+	# any domain cookie set -- pudge
 	my $domain = ($cookiedomain && $cookiedomain =~ /^\..+\./)
 		? $cookiedomain
 		: '';
@@ -1365,8 +1368,6 @@
 
 	my $cookie = Apache::Cookie->new($r, %cookiehash);
 
-	# this should be fine, but if there is a problem, comment the following
-	# lines, and uncomment the one right above "bake"
 	if (!$val) {
 		$cookie->expires('-1y');  # delete
 	} elsif ($session && $session =~ /^\+\d+[mhdy]$/) {
@@ -1589,7 +1590,7 @@
 			@headers{map lc, keys %headers} = values %headers;
 			my $ua = $r->headers_in->{'user-agent'};
 			if ($ua =~ /MSIE (\d+)/) {
-				$d2 = 'none';# if $1 < 7;
+				$d2 = 'none' if $1 < 7;
 			}
 		}
 		$user->{discussion2} = $d2;
@@ -1900,7 +1901,7 @@
 		logtoken	=> sub { $_[0] = '' unless
 					 $_[0] =~ m|^\d+::[A-Za-z0-9]{22}$|		},
 		sid		=> sub { $_[0] = '' unless
-					 $_[0] =~ Slash::Utility::Data::regexSid()	},
+					 $_[0] =~ Slash::Utility::Data::regexSid(1)	},
 		flags		=> sub { $_[0] =~ s|[^a-z0-9_,]||g			},
 		query		=> sub { $_[0] =~ s|[\000-\040<>\177\p{BidiControl}\p{Unassigned}\p{JoinControl}]+| |g;
 			        	 $_[0] =~ s|\s+| |g;				},
@@ -1993,7 +1994,7 @@
 		$data =~ s|[^a-zA-Z0-9_]+||g;
 	} else {
 		for my $ri (@regints) {
-			$data = fixint($data) if $ri =~ $key;
+			$data = fixint($data) if $key =~ /$ri/;
 		}
 
 		# convert input to internal character encoding
@@ -2521,8 +2522,8 @@
 
 	if ($ENV{GATEWAY_INTERFACE} && (my $r = Apache->request)) {
 		$errors[0] = $ENV{SCRIPT_NAME} . $errors[0];
-		$errors[-1] .= "\n";
-		$r->log_error($_) for @errors;
+		#$errors[-1] .= "\n";
+		$r->log_error(join ' ;; ', @errors); # for @errors;
 	} else {
 		$errors[0] = 'Error' . $errors[0];
 		print STDERR $_, "\n" for @errors;
@@ -3584,7 +3585,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::Utility(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/Utility/Environment/Environment.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/Slash/Utility/Environment/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Environment/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Utility/Environment/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Environment/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Utility::Environment',
-    'VERSION_FROM' => 'Environment.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Utility/Environment/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Utility/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Utility',
-    'VERSION_FROM' => 'Utility.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Utility/System/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/System/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/Utility/System/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/System/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Utility::System',
-    'VERSION_FROM' => 'System.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/Utility/System/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/System/System.pm
===================================================================
--- slashjp/trunk/Slash/Utility/System/System.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/System/System.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Utility::System;
 
@@ -33,6 +32,7 @@
 use File::Spec::Functions;
 use File::Temp 'tempfile';
 use Mail::Sendmail;
+use Slash::Constants ();
 use Slash::Custom::Bulkmail;	# Mail::Bulkmail
 use Slash::Utility::Data;
 use Slash::Utility::Environment;
@@ -41,10 +41,9 @@
 use Encode;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT @EXPORT_OK);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT	   = qw(
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT  = qw(
 	bulkEmail
 	doEmail
 	sendEmail
@@ -56,7 +55,7 @@
 	prog2file
 	makeDir
 );
- @ EXPORT_OK = qw();
+our @EXPORT_OK = qw();
 
 #========================================================================
 
@@ -547,7 +546,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::Utility(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/Utility/System/System.pm
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/Utility/Utility.pm
===================================================================
--- slashjp/trunk/Slash/Utility/Utility.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/Utility/Utility.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Utility;
 
@@ -35,12 +34,12 @@
 use Slash::Utility::Display;
 use Slash::Utility::Environment;
 use Slash::Utility::System;
+use Slash::Constants ();
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT = (
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT = (
 	@Slash::Utility::Access::EXPORT,
 	@Slash::Utility::Anchor::EXPORT,
 	@Slash::Utility::Comments::EXPORT,

Modified: slashjp/trunk/Slash/XML/Atom/Atom.pm
===================================================================
--- slashjp/trunk/Slash/XML/Atom/Atom.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/XML/Atom/Atom.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::XML::Atom;
 
@@ -31,9 +30,8 @@
 use XML::Parser::Expat;
 use base 'Slash::XML';
 use base 'Slash::XML::RSS';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 my %syn_ok_fields = (
 	'updateBase' => '',
@@ -153,7 +151,8 @@
 
 	my $atom = {%$rss};
 	bless $atom, __PACKAGE__;
-	return as_atom_1_0($atom);
+	my $data = as_atom_1_0($atom);
+	return $data;
 }
 
 # copied from as_rss_1_0 in XML::RSS ... kinda ugly, but oh well
@@ -349,7 +348,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::XML(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/XML/Atom/Atom.pm
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/XML/Atom/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/XML/Atom/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/XML/Atom/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::XML::Atom',
-    'VERSION_FROM' => 'Atom.pm', # finds $VERSION
 );

Modified: slashjp/trunk/Slash/XML/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/XML/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/XML/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::XML',
-    'VERSION_FROM' => 'XML.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/XML/RSS/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/XML/RSS/Makefile.PL
===================================================================
--- slashjp/trunk/Slash/XML/RSS/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/XML/RSS/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::XML::RSS',
-    'VERSION_FROM' => 'RSS.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/Slash/XML/RSS/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/XML/RSS/RSS.pm
===================================================================
--- slashjp/trunk/Slash/XML/RSS/RSS.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/XML/RSS/RSS.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::XML::RSS;
 
@@ -31,9 +30,8 @@
 use Slash::Display;
 use XML::RSS;
 use base 'Slash::XML';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 
 #========================================================================
@@ -458,16 +456,22 @@
 	if ($version >= 1.0) {
 		my $desc = $self->rss_item_description($item->{description} || $story->{introtext});
 		if ($desc) {
-			$encoded_item->{description} = $desc;
 			$encoded_item->{description} = $desc . getData('rss_story_readmore', {
 				'link'		=> $encoded_item->{link},
 				discussion	=> $story->{discussion},
 			}, 'index');
+
+			my $extra = '';
 			# disabled on slashdot.jp (2008-09-09, tach)
-			#$encoded_item->{description} .= qq{<p><a href="$action"><img src="$channel->{'link'}slashdot-it.pl?from=rss&amp;op=image&amp;style=h0&amp;sid=$story->{sid}"></a></p>};
-			#$encoded_item->{description} .= "<p><a href=\"$action\">Read more of this story</a> at $constants->{sitename}.</p>" if $action;
+			# If the text of the <img src>'s query string changes,
+			# Stats.pm getTopBadgeURLs() may also have to change.
+			#$extra .= qq{<p><a href="$action"><img src="$channel->{'link'}slashdot-it.pl?from=rss&amp;op=image&amp;style=h0&amp;sid=$story->{sid}"></a></p>}
+			#	if $constants->{rdfbadge};
+			#$extra .= "<p><a href=\"$action\">Read more of this story</a> at $constants->{sitename}.</p>"
+			#	if $action;
 			# add poll if any
-			$encoded_item->{description} .= pollbooth($story->{qid},1, 0, 1) if $story->{qid};
+			$extra .= pollbooth($story->{qid},1, 0, 1) if $story->{qid};
+			$encoded_item->{description} .= $self->encode($extra) if $extra;
 
 			# add content:encoded for slashdot.jp
 			$item->{'content:encoded'} ||= ($item->{description} || $story->{introtext}) . getData('rss_story_readmore', {
@@ -612,7 +616,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::XML(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/Slash/XML/RSS/RSS.pm
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/Slash/XML/XML.pm
===================================================================
--- slashjp/trunk/Slash/XML/XML.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/Slash/XML/XML.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::XML;
 
@@ -32,10 +31,9 @@
 use Slash::Utility;
 
 use base 'Exporter';
-use vars qw($VERSION @EXPORT);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
- @ EXPORT = qw(xmlDisplay);
+our $VERSION = $Slash::Constants::VERSION;
+our @EXPORT = qw(xmlDisplay);
 
 # FRY: There must be layers and layers of old stuff down there!
 

Copied: slashjp/trunk/bin/purge-read-log (from rev 741, slashjp/branches/upstream/2.5.0.218/bin/purge-read-log)
===================================================================
--- slashjp/trunk/bin/purge-read-log	                        (rev 0)
+++ slashjp/trunk/bin/purge-read-log	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,74 @@
+#!/usr/bin/perl -w
+
+use strict;
+use File::Basename;
+use Getopt::Std;
+use Slash::DB;
+use Slash::Utility;
+
+(my $VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+my $PROGNAME = basename($0);
+
+my %opts;
+# Remember to doublecheck these match usage()!
+usage('Options used incorrectly') unless getopts('hvu:d:', \%opts);
+usage() if $opts{'h'} || !$opts{'d'} || !$opts{'u'} || !keys %opts;
+version() if $opts{'v'};
+
+createEnvironment($opts{'u'});
+
+usage() if $opts{'d'} =~ /\D/;
+if ($opts{'d'} < 14) {
+	local $| = 1;
+	print "Are you sure you want to delete all rows for\n",
+	      "discussions less than $opts{'d'} days? [yN] ";
+	chomp(my $line = <>);
+	exit unless $line =~ /y/i;
+}
+
+
+
+
+{
+	my $slashdb = getCurrentDB();
+	warn $@ unless $slashdb->sqlDo(<<EOT);
+DELETE users_comments_read_log
+FROM users_comments_read_log, discussions
+WHERE discussion_id=discussions.id
+  AND discussions.ts < DATE_SUB(NOW(), INTERVAL $opts{'d'} DAY)
+EOT
+}
+
+sub usage {
+	print "*** $_[0]\n" if $_[0];
+	# Remember to doublecheck these match getopts()!
+	print <<EOT;
+
+Usage: $PROGNAME [OPTIONS] ... [FILES]
+
+SHORT PROGRAM DESCRIPTION
+
+Main options:
+	-h	Help (this message)
+	-v	Version
+	-u	Virtual user (default is "slash")
+	-d      Discussions that are more than -d days old will be purged
+
+EOT
+	exit;
+}
+
+sub version {
+	print <<EOT;
+
+$PROGNAME $VERSION
+
+This code is a part of Slash, and is released under the GPL.
+Copyright 1997-2008 by Open Source Technology Group. See README
+and COPYING for more information, or see http://slashcode.com/.
+
+EOT
+	exit;
+}
+
+__END__

Modified: slashjp/trunk/bin/runtask
===================================================================
--- slashjp/trunk/bin/runtask	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/bin/runtask	2008-09-09 13:07:58 UTC (rev 742)
@@ -11,6 +11,7 @@
 use File::Basename;
 use File::Path;
 use File::Spec::Functions;
+use File::Temp 'tempfile';
 use FindBin '$Bin';
 use LWP::UserAgent;
 use HTTP::Request;
@@ -177,8 +178,57 @@
 		my $file = basename($fullname);
 		next unless $file eq $task_name or $file eq "$task_name.pl";
 		$task_name = $file;
+
+		# we want to encapsulate each task automatically.  to do that,
+		# we automatically create a package name for each task, and
+		# then we manually import the symbols we want into that package.
+		# then it is written out as a temp file, and THAT file is
+		# require'd, not the actual task.
+		# we may be importing more than we need for coderefs, but
+		# i didn't feel like looking at each task individually.
+
+		(my $tmppackage = $file) =~ s/\.pl$//;
+		$tmppackage =~ s/\W/_/g;
+		$tmppackage =~ s/^([^a-zA-Z])/a_$1/g;
+		$tmppackage = "Slash::Task::$tmppackage";
+
+		# replace tmppackage in string where appropriate
+		(my $addtxt = <<'EOT') =~ s/\${?tmppackage}?/$tmppackage/g;
+package $tmppackage;
+
+{ no strict 'refs';
+	my @scalar = qw(me task_exit_flag);
+	my @hash   = qw(task);
+	my @code   = (qw(
+			slashdLog slashdErrnote slashdLogDie
+			tagboxLog verbosity db_time init_cron
+		),
+		grep { *{"main::$_"}{CODE} }
+			@Slash::EXPORT, @Slash::Display::EXPORT,
+			@Slash::Utility::EXPORT,
+			@File::Spec::Functions::EXPORT,
+			@LWP::UserAgent::EXPORT, @URI::Escape::EXPORT,
+			@File::Basename::EXPORT, @File::Path::EXPORT,
+			@Time::Local::EXPORT, @Time::HiRes::EXPORT
+	);
+
+	*{"${tmppackage}::$_"} = *{"main::$_"}{HASH}   for @hash;
+	*{"${tmppackage}::$_"} = *{"main::$_"}{SCALAR} for @scalar;
+	*{"${tmppackage}::$_"} = *{"main::$_"}{CODE}   for @code;
+}
+
+#line 1
+EOT
+
+		my($tmpfh, $tmpfile) = tempfile();
+		my $tmptxt = do { open my $fh, '<', $fullname; local $/; <$fh> };
+		print $tmpfh $addtxt, $tmptxt;
+		$tmpfh->flush; # can't close fh until we require the file,
+		               # else the file might disappear
+
 		my $ok = 0;
-		eval { local $me = $file; $ok = require $fullname; };
+		eval { local $me = $file; $ok = require $tmpfile };
+
 		if ($@) {
 			slashdLog("requiring '$fullname' raised exception: $@");
 			$ok = 0;
@@ -187,7 +237,7 @@
 			slashdLog("requiring '$fullname' caused error: $!");
 			$ok = 0;
 		}
-		if (!$task{$file}{code} or ref $task{$file}{code} ne 'CODE') {
+		if (!$task{$file}{code} || ref $task{$file}{code} ne 'CODE') {
 			slashdLog("'$fullname' did not set code properly");
 			$ok = 0;
 		}

Modified: slashjp/trunk/debian/changelog
===================================================================
--- slashjp/trunk/debian/changelog	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/debian/changelog	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,3 +1,11 @@
+slash (2.5.0.218-1) unstable; urgency=low
+
+  * New upstream git release
+    - Upstream SCM has been changed to git
+      (git://github.com/scc/slash.git)
+
+ -- Taku YASUI <tach****@osdn*****>  Tue, 09 Sep 2008 22:05:52 +0900
+
 slash (2.5.0.201-1) unstable; urgency=low
 
   * New upstream CVS release

Modified: slashjp/trunk/docs/INSTALL.pod
===================================================================
--- slashjp/trunk/docs/INSTALL.pod	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/docs/INSTALL.pod	2008-09-09 13:07:58 UTC (rev 742)
@@ -161,9 +161,12 @@
 server, and you wanted to use the mysql username 'slash', you might:
 
 	GRANT SELECT, INSERT, UPDATE, DELETE, LOCK TABLES, CREATE, DROP,
-	INDEX, ALTER, PROCESS ON slash.* TO 'slash'@'localhost'
+	INDEX, ALTER ON slash.* TO 'slash'@'localhost'
 	IDENTIFIED BY (quoted password);
 
+	GRANT PROCESS ON *.* TO 'slash'@'localhost' IDENTIFIED BY
+	(quoted password);
+
 In this case, 'slash' would also be the name of your MySQL user as
 described in L<"Types of Users"> below.  You'll have to give your MySQL
 user to DBIx::Password when you install and configure it, so don't
@@ -404,6 +407,8 @@
 proceeding.  Note that Net::Cmd has a history of being a little broken
 in its tests;  if it fails on tests 8 and 9 of t/require, then it's OK;
 just do C<force install Net::Cmd> and repeat C<install Bundle::LWP>.
+On Mac OS X and possibly other operating systems, if LWP's live/https
+tests fail, C<install Net::SSL> manually and retry.
 
 Assuming you chose to install the LWP, then after it's been configured
 successfully, again, C<exit> the CPAN and reinvoke it.


Property changes on: slashjp/trunk/docs/slasherd.pdf
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/docs/slashguide.pod
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/docs/slashtables.pod
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Admin/Admin/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Admin/Admin/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/Admin/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,5 +2,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::Admin::PopupTree',
-    'VERSION_FROM' => 'PopupTree.pm', # finds $VERSION
 );

Modified: slashjp/trunk/plugins/Admin/Admin/PopupTree.pm
===================================================================
--- slashjp/trunk/plugins/Admin/Admin/PopupTree.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/Admin/PopupTree.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Admin::PopupTree;
 
@@ -31,9 +30,8 @@
 #use HTML::PopupTreeSelect '1.4';
 
 use base 'HTML::PopupTreeSelect';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 #========================================================================
 
@@ -236,7 +234,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/plugins/Admin/Admin.pm
===================================================================
--- slashjp/trunk/plugins/Admin/Admin.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/Admin.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Admin;
 
@@ -11,12 +10,10 @@
 use Slash::Display;
 use Slash::Utility;
 
-use vars qw($VERSION);
-use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # On a side note, I am not sure if I liked the way I named the methods either.
 # -Brian
@@ -337,6 +334,25 @@
 
 }
 
+sub showAdminTodo {
+	my($self) = @_;
+	my $gSkin = getCurrentSkin();
+	my $pb_reader = getObject("Slash::PollBooth", { db_type => 'reader' });
+	my $text = "";
+	my $days = $pb_reader->getPollDaysOld();
+	if ($days > 3 ) {
+		$text .= "<b><a href=\"" . $gSkin->{rootdir} . "/pollBooth.pl\">Poll</a> has not been updated in $days days</b><br>";
+		$text .= '<a href="#" onclick=\'firehose_set_options("setfhfilter", "polls hold")\'>View current poll submissions</a><br><hr>';
+	}
+	if ($text) {
+		slashDisplay('sidebox', {
+			title 		=> 'Admin Todo',
+			contents	=> $text,
+			name 		=> 'admintodo',
+		}, { Return => 1});
+	}
+}
+
 sub showStoryAdminBox {
 	my ($self, $storyref, $options) = @_;
 	my $user = getCurrentUser();
@@ -522,7 +538,8 @@
 	my $now = timeCalc($self->getTime(), "%s", 0);
 
 	foreach my $admin (@$cur_admin) {
-		my ($nickname, $time, $title, $subid, $sid, $uid, $fhid) = @$admin;
+		my ($nickname, $time, $title, $subid, $sid, $uid, $fhid, $last_action) = @$admin;
+		$last_action ||= "reviewing";
 		push @activity, {
 			nickname => $nickname,
 			title	=> $title,
@@ -531,7 +548,7 @@
 			uid	=> $uid,
 			fhid	=> $fhid,
 			'time'	=> $time,
-			verb	=> "reviewing"
+			verb	=> $last_action
 		};
 	}
 
@@ -630,6 +647,34 @@
 	}
 }
 
+sub getStoryThumbLargeLink {
+	my($self, $id, $stoid) = @_;
+	my $file = $self->getStaticFile($id);
+	my $full_name = $file->{name};
+	$full_name =~ s/(-thumb[^.]*)\././g;
+	my $thumb_lg_name = $full_name;
+	$thumb_lg_name =~ s/\./-thumblg./;
+
+	my $stoid_q = $self->sqlQuote($stoid);
+	my $name_q = $self->sqlQuote($full_name);
+
+	my $full_img = $self->sqlSelectHashref("*", "static_files", "stoid=$stoid_q AND name = $name_q");
+
+	$name_q = $self->sqlQuote($thumb_lg_name);
+	my $thumb_lg_img = $self->sqlSelectHashref("*", "static_files", "stoid=$stoid_q AND name = $name_q");
+
+	if ($full_img && $full_img->{sfid} && $thumb_lg_img && $thumb_lg_img->{sfid}) {
+		if ($full_img->{height} > $thumb_lg_img->{height} || $full_img->{width} > $thumb_lg_img->{height}) {
+			return getData('thumb_link_large', { full_img => $full_img, thumb_img => $thumb_lg_img });
+		} else {
+			return getData('thumb_link_large', { thumb_img => $thumb_lg_img });
+		}
+	}
+
+
+
+}
+
 sub DESTROY {
 	my($self) = @_;
 	$self->{_dbh}->disconnect if !$ENV{GATEWAY_INTERFACE} && $self->{_dbh};

Modified: slashjp/trunk/plugins/Admin/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Admin/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Admin',
-    'VERSION_FROM' => 'Admin.pm', # finds $VERSION
     'PM'	=> { 'Admin.pm' => '$(INST_LIBDIR)/Admin.pm' },
 );

Modified: slashjp/trunk/plugins/Admin/admin.pl
===================================================================
--- slashjp/trunk/plugins/Admin/admin.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/admin.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -1191,11 +1191,13 @@
 
 		$storyref->{uid} ||= $user->{uid};
 		if ($constants->{use_dept_space2dash} && $storyref->{dept}){
+			$storyref->{dept} ||= '';
 			$storyref->{dept} =~ s/[-\s]+/-/g;
 			$storyref->{dept} =~ s/^-//;
 			$storyref->{dept} =~ s/-$//;
 		}
 
+
 		my($related_sids_hr, $related_urls_hr, $related_cids_hr, $related_firehose_hr) = extractRelatedStoriesFromForm($form, $storyref->{sid});
 		$storyref->{related_sids_hr} = $related_sids_hr;
 		$storyref->{related_urls_hr} = $related_urls_hr;
@@ -1405,6 +1407,7 @@
 		last_sid	=> $sid,
 		last_subid	=> '',
 		last_fhid	=> '',
+		last_action	=> 'editing',
 	});
 
 	# Run a spellcheck on introtext, bodytext, and title if they're set.

Modified: slashjp/trunk/plugins/Admin/templates/commentlog;admin;default
===================================================================
--- slashjp/trunk/plugins/Admin/templates/commentlog;admin;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/templates/commentlog;admin;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -23,4 +23,4 @@
 [% END %]
 </table>
 __version__
-
+$Id$

Modified: slashjp/trunk/plugins/Admin/templates/data;admin;default
===================================================================
--- slashjp/trunk/plugins/Admin/templates/data;admin;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/templates/data;admin;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -153,6 +153,12 @@
 [% CASE 'storyadminbox_js' %]
 	<script type="text/javascript">admin_storyadminbox_fetch(30);</script>
 
+[% CASE 'thumb_link_large' %]
+[% IF full_img -%]
+<a href=\'[% constants.imagedir %][% full_img.name %]\'><img src=\'[% constants.imagedir %][% thumb_img.name %]\'></a>
+[%- ELSE -%]
+<img src=\'[% constants.imagedir %][% thumb_img.name %]\'>
+[%- END -%]
 [% END %]
 __seclev__
 10000

Modified: slashjp/trunk/plugins/Admin/templates/editStory;admin;default
===================================================================
--- slashjp/trunk/plugins/Admin/templates/editStory;admin;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/templates/editStory;admin;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -276,7 +276,10 @@
 </td>
 <td>
 	[% IF mfile.filetype == "image" %]
-		<a href="#media" onclick="appendToMedia('\n<img src=\'[% constants.imagedir %][% bigfile %]\'>')"><img src="[% constants.imagedir %][% mfile.name %]" width="[% width %]" height="[% height %]"></a>
+		[% admindb = Slash.getObject("Slash::Admin");
+                   thumblink = admindb.getStoryThumbLargeLink(mfile.sfid, storyref.stoid);
+		%]
+		<a href="#media" onclick="appendToMedia('\n[% thumblink %]')"><img src="[% constants.imagedir %][% mfile.name %]" width="[% width %]" height="[% height %]"></a>
 	[% ELSE %]
 		<a href="#media" onclick="appendToMedia('\n<a href=\'[% constants.imagedir %][% mfile.name %]\'>[% filename %]</a>')">Add [% filename %]</a>
 	[% END %]

Modified: slashjp/trunk/plugins/Admin/templates/peer_weights;admin;default
===================================================================
--- slashjp/trunk/plugins/Admin/templates/peer_weights;admin;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/templates/peer_weights;admin;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -44,5 +44,5 @@
 </table>
 
 __version__
-$Id: peer_weights;admin;default,v 1.2 2007/04/05 19:46:52 jamiemccarthy Exp $
+$Id$
 

Modified: slashjp/trunk/plugins/Admin/templates/static_files;admin;default
===================================================================
--- slashjp/trunk/plugins/Admin/templates/static_files;admin;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Admin/templates/static_files;admin;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -26,4 +26,4 @@
 
 
 __version__
-$Id: static_files;admin;default,v 1.1 2007/10/16 22:59:06 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Ajax/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::Ajax',
-    'VERSION_FROM' => 'htdocs/ajax.pl', # finds $VERSION
 );

Modified: slashjp/trunk/plugins/Ajax/PLUGIN
===================================================================
--- slashjp/trunk/plugins/Ajax/PLUGIN	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/PLUGIN	2008-09-09 13:07:58 UTC (rev 742)
@@ -7,6 +7,10 @@
 glob=calendarcss:htdocs/calendar.css
 calendarcss=htdocs/images/yui/calendar.css
 css=htdocs/calendar.css
+glob=taguicss:htdocs/tagui.css
+taguicss=htdocs/images/tagui.css
+taguicss=htdocs/images/jquery/jquery.autocomplete.css
+css=htdocs/tagui.css
 image=htdocs/images/yui/callt.gif
 image=htdocs/images/yui/calrt.gif
 image=htdocs/images/yui/calx.gif
@@ -28,11 +32,19 @@
 htdoc=htdocs/images/slashbox.js
 htdoc=htdocs/images/common.js
 htdoc=htdocs/images/nodnix.js
-htdoc=htdocs/images/jquery-1.2.3.js
+htdoc=htdocs/images/jquery/jquery-1.2.6.js
+htdoc=htdocs/images/jquery/jquery.metadata.js
+htdoc=htdocs/images/jquery/jquery.textselection.js
+htdoc=htdocs/images/jquery/jquery.autocomplete.js
+htdoc=htdocs/images/jquery/ui.core.js
+htdoc=htdocs/images/jquery/ui.sortable.js
+htdoc=htdocs/images/jquery/jquery.slashdot.js
+htdoc=htdocs/images/tagui.js
 htdoc=htdocs/images/sectionprefs.js
 requiresplugin=ResKey
 template=templates/ajax_reskey_signoff;misc;default
 template=templates/ajax_reskey_tag;misc;default
+template=templates/combined_tags;misc;default
 template=templates/data;ajax;default
 template=templates/datewidget;misc;default
 template=templates/edit_comment;ajax;default
@@ -49,3 +61,5 @@
 template=templates/prefs_main;ajax;default
 template=templates/prefs_admin;ajax;default
 template=templates/sectionpref;ajax;default
+template=templates/tag_widget;misc;default
+template=templates/tag_display;misc;default

Modified: slashjp/trunk/plugins/Ajax/htdocs/ajax.pl
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/ajax.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/ajax.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 use strict;
 use warnings;
@@ -12,10 +11,7 @@
 use Slash 2.003;	# require Slash 2.3.x
 use Slash::Display;
 use Slash::Utility;
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
-
 ##################################################################
 sub main {
 	my $slashdb   = getCurrentDB();
@@ -73,7 +69,7 @@
 			# feel free to send msgdiv => 'thisdivhere' to the ajax call,
 			# and any reskey error messages will be sent to it
 			if ($form->{msgdiv}) {
-				header_ajax({ content_type => 'application/json' });
+				http_send({ content_type => 'application/json' });
 				(my $msgdiv = $form->{msgdiv}) =~ s/[^\w-]+//g;
 				print Data::JavaScript::Anon->anon_dump({
 					html	  => { $msgdiv => $rkey->errstr },
@@ -93,7 +89,7 @@
 #	print STDERR "AJAX7 $$: $user->{uid}, $op ($retval)\n";
 
 	if ($retval) {
-		header_ajax($options);
+		http_send($options);
 		print $retval;
 	}
 
@@ -333,7 +329,7 @@
 		error => $error_message,
 	);
 	$to_dump{html} = { "replyto_preview_$pid" => $html } if $html;
-	$to_dump{eval_first} = "\$('gotmodwarning_$pid').value = 1;"
+	$to_dump{eval_first} = "\$dom('gotmodwarning_$pid').value = 1;"
 		if $form->{gotmodwarning} || ($error_message && $error_message eq
 			Slash::Utility::Comments::getError("moderations to be lost")
 		);
@@ -412,16 +408,21 @@
 sub fetchComments {
 	my($slashdb, $constants, $user, $form, $options) = @_;
 
-	my $cids         = [ grep { defined && /^\d+$/ } ($form->{_multi}{cids} ? @{$form->{_multi}{cids}} : $form->{cids}) ];
-	my $id           = $form->{discussion_id} || 0;
-	my $cid          = $form->{cid} || 0; # root id
-	my $d2_seen      = $form->{d2_seen};
-	my $placeholders = [ grep { defined && /^\d+$/ } ($form->{_multi}{placeholders} ? @{$form->{_multi}{placeholders}} : $form->{placeholders}) ];
+	my $cids          = [ grep { defined && /^\d+$/ } ($form->{_multi}{cids} ? @{$form->{_multi}{cids}} : $form->{cids}) ];
+	my $id            = $form->{discussion_id} || 0;
+	my $cid           = $form->{cid} || 0; # root id
+	my $d2_seen       = $form->{d2_seen};
+	my $placeholders  = [ grep { defined && /^\d+$/ } ($form->{_multi}{placeholders}  ? @{$form->{_multi}{placeholders}}  : $form->{placeholders}) ];
+	my $read_comments = [ grep { defined && /^\d+$/ } ($form->{_multi}{read_comments} ? @{$form->{_multi}{read_comments}} : $form->{read_comments}) ];
 
 	$user->{state}{ajax_accesslog_op} = "ajax_comments_fetch";
-#use Data::Dumper; print STDERR Dumper [ $form, $cids, $id, $cid, $d2_seen ];
+#use Data::Dumper; print STDERR Dumper [ $form, $cids, $id, $cid, $d2_seen, $read_comments ];
+	return unless $id;
+
+	$slashdb->saveCommentReadLog($read_comments, $id, $user->{uid}) if @$read_comments;
+
 	# XXX error?
-	return unless $id && (@$cids || $d2_seen);
+	return unless (@$cids || $d2_seen);
 
 	my $discussion = $slashdb->getDiscussion($id);
 	if ($discussion->{type} eq 'archived') {
@@ -437,18 +438,10 @@
 		no_d2        => 1
 	);
 
-	my %seen;
-	if ($d2_seen || $form->{d2_seen_ex}) {
-		my $lastcid = 0;
-		for my $cid (split /,/, $d2_seen || $form->{d2_seen_ex}) {
-			$cid = $lastcid ? $lastcid + $cid : $cid;
-			$seen{$cid} = 1;
-			$lastcid = $cid;
-		}
-		if ($d2_seen) {
-			$select_options{existing} = \%seen if keys %seen;
-			delete $select_options{no_d2};
-		}
+	my $seen = parseCommentBitmap($d2_seen || $form->{d2_seen_ex});
+	if ($d2_seen) {
+		$select_options{existing} = $seen if keys %$seen;
+		delete $select_options{no_d2};
 	}
 
 	my($comments) = selectComments(
@@ -467,18 +460,13 @@
 	if ($d2_seen || @$placeholders) {
 		my $special_cids;
 		if ($d2_seen) {
-			$special_cids = $cids = [ sort { $a <=> $b } grep { $_ && !$seen{$_} } keys %$comments ];
+			$special_cids = $cids = [ sort { $a <=> $b } grep { $_ && !$seen->{$_} } keys %$comments ];
 		} elsif (@$placeholders) {
 			$special_cids = [ sort { $a <=> $b } @$placeholders ];
 			if ($form->{d2_seen_ex}) {
-				my @seen;
-				my $lastcid = 0;
-				my %check = (%seen, map { $_ => 1 } @$placeholders);
-				for my $cid (sort { $a <=> $b } keys(%check)) {
-					push @seen, $lastcid ? $cid - $lastcid : $cid;
-					$lastcid = $cid;
-				}
-				$d2_seen_0 = join ',', @seen;
+				$d2_seen_0 = makeCommentBitmap({
+					%$seen, map { $_ => 1 } @$placeholders
+				});
 			}
 		}
 
@@ -489,6 +477,7 @@
 					uid     => $comments->{$cid}{uid},
 					pid     => $comments->{$cid}{pid},
 					points  => $comments->{$cid}{points},
+					read    => $comments->{$cid}{has_read} || 0,
 					kids    => []
 				};
 				if ($comments->{$cid}{subject_orig} && $comments->{$cid}{subject_orig} eq 'no') {
@@ -596,26 +585,30 @@
 	}
 
 # XXX update noshow_comments, pieces_comments -- pudge
-#use Data::Dumper; print STDERR Dumper \@hidden_cids, \@pieces_cids, \@abbrev_cids, \%get_pieces_cids, \%keep_hidden, \%pieces, \%abbrev, \%html, \%html_append_substr, $form, \%data;
+#use Data::Dumper; print STDERR Dumper \@hidden_cids, \@pieces_cids, \@abbrev_cids, \%get_pieces_cids, \%keep_hidden, \%pieces, \%abbrev, \%html, \%html_append_substr, $form, \%data, $d2_seen_0;
 
+	$user->{d2_comment_order} ||= 0;
+
 	$options->{content_type} = 'application/json';
 	my %to_dump = (
+		read_comments      => $read_comments,  # send back so we can just mark them
 		update_data        => \%data,
 		html               => \%html,
-		html_append_substr => \%html_append_substr
+		html_append_substr => \%html_append_substr,
+		eval_first         => "d2_comment_order = $user->{d2_comment_order};"
 	);
+
 	if ($d2_seen_0) {
 		my $total = $slashdb->countCommentsBySid($id);
 		$total -= $d2_seen_0 =~ tr/,//; # total
 		$total--; # off by one
-		$to_dump{eval_first} ||= '';
 		$to_dump{eval_first} .= "d2_seen = '$d2_seen_0'; updateMoreNum($total);";
 	}
 	if (@$placeholders) {
-		$to_dump{eval_first} ||= '';
 		$to_dump{eval_first} .= "placeholder_no_update = " . Data::JavaScript::Anon->anon_dump({ map { $_ => 1 } @$placeholders }) . ';';
 	}
 	writeLog($id);
+#print STDERR "\n\n\n", Data::JavaScript::Anon->anon_dump(\%to_dump), "\n\n\n";
 	return Data::JavaScript::Anon->anon_dump(\%to_dump);
 }
 
@@ -785,7 +778,6 @@
 		}
 
 	} else {
-		
 		return
 			slashDisplay('prefs_' . $form->{'section'}, {
 				user   => $user,
@@ -813,7 +805,8 @@
 			# we only want to save the pref for people who turn it off, but the checkbox
 			# is on by default, so if the value is true then it is on, and if false,
 			# it is off -- pudge
-			d2_keybindings_switch => $params{'d2_keybindings_switch'}   ? undef : 1,
+			d2_reverse_switch     => $params{'d2_reverse_switch'}     ? 1 : undef,
+			d2_keybindings_switch => $params{'d2_keybindings_switch'} ? undef : 1,
 			d2_comment_q          => $params{'d2_comment_q'}         || undef,
 			d2_comment_order      => $params{'d2_comment_order'}     || undef,
 			nosigs                => ($params{'nosigs'}              ? 1 : 0),
@@ -1103,17 +1096,6 @@
 sub default { }
 
 ##################################################################
-sub header_ajax {
-	my($options) = @_;
-	my $ct = $options->{content_type} || 'text/plain';
-
-	my $r = Apache->request;
-	$r->content_type($ct);
-	$r->header_out('Cache-Control', 'no-cache');
-	$r->send_http_header;
-}
-
-##################################################################
 sub getOps {
 	my $slashdb   = getCurrentDB();
 	my $constants = getCurrentStatic();

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/admin.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/admin.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/admin.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-// $Id$
+; // $Id$
 
 function um_ajax(the_behaviors, the_events) {
 	ajax_update({
@@ -19,6 +19,102 @@
 	}, 'links-vendors-content');
 }
 
+function tagsHistory(id, type) {
+	var params = {};
+	type = type || "stories";
+	params.type = type;
+	params.op = 'tags_history';
+	if (type == "stories") {
+		params.sidenc = id;
+	} else if (type == "urls" || type == "firehose") {
+		params.id = id;
+	}
+
+	var $entry = $('#firehose-'+id);
+	var $widget = $('#tag-widget-'+id, $entry[0]);
+
+	// hang the pop-up from the first available of:
+	var $positioners =
+		$widget.find('.history-button').		// the history button
+			add($related_trigger).			// whatever you clicked
+			add($widget.find('.edit-toggle')).	// the disclosure triangle
+			add($entry.find('#updown-'+id));	// the nod/nix capsule
+
+	var popupid    = "taghistory-" + id;
+	var title      = "History ";
+	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(getXYForSelector($positioners), title, popupid);
+	ajax_update(params, "taghistory-" + id + "-contents");
+}
+
+//
+// firehose + admin + tagui
+//
+
+function firehose_admin_context( display ){
+	display.update_tags('history', { order: 'prepend' });
+}
+
+function firehose_handle_admin_commands( commands ){
+	var neverdisplay, hold, signoff, history;
+
+	var non_admin_commands = $.map(commands, function(cmd){
+		var user_cmd = null;
+		switch ( cmd ) {
+			case 'neverdisplay':	neverdisplay = true; break;
+			case 'hold':		hold = true; break;
+
+			case 'history':		history = true; break;
+
+			case 'signed':
+			case 'signoff':
+			case 'unsigned':
+				signoff = true;
+				break;
+
+			default:
+				user_cmd = cmd;
+		}
+		return user_cmd;
+	});
+
+	var id = this.getAttribute('tag-server');
+	if ( neverdisplay && confirm("Set story to neverdisplay?") ) {
+		non_admin_commands.push('neverdisplay');
+		this._ajax_request('', {
+			op:	'admin_neverdisplay',
+			stoid:	'',
+			fhid:	id,
+			ajax:	{ success: function(){ firehose_remove_entry(id); } }
+		});
+	}
+
+	if ( signoff ) {
+		var signoff_tag_server = this;
+		this._ajax_request('', {
+			op:	'admin_signoff',
+			stoid:	$('[stoid]', this).attr('stoid'),
+			ajax:	{ success: function(){ $('[context=signoff]', signoff_tag_server).remove(); } }
+		});
+	}
+
+	if ( hold ) {
+		non_admin_commands.push('hold');
+	}
+
+	if ( hold || signoff ) {
+		firehose_collapse_entry(id);
+	}
+
+	if ( history ) {
+		tagsHistory(id, 'firehose');
+	}
+
+	return non_admin_commands;
+}
+
+
 function admin_neverdisplay(stoid, type, fhid) {
 	if (confirm("Set story to neverdisplay?")) {
 		ajax_update({
@@ -51,43 +147,24 @@
 
 	var params = {};
 	type = type || "stories";
-	params['op'] = 'tags_admin_commands';
+	params.op = 'tags_admin_commands';
 	if (type == "stories") {
-		params['sidenc'] = id;
+		params.sidenc = id;
 	} else if (type == "urls") {
-		params['id'] = id;
+		params.id = id;
 	} else if (type == "firehose") {
-		params['id'] = id;
+		params.id = id;
 	}
-	params['type'] = type;
+	params.type = type;
 	var tags_admin_commands_el = $dom('tags_admin_commands-' + id);
-	params['commands'] = tags_admin_commands_el.value;
+	params.commands = tags_admin_commands_el.value;
 	var reskeyel = $dom('admin_commands-reskey-' + id);
-	params['reskey'] = reskeyel.value;
+	params.reskey = reskeyel.value;
 	ajax_update(params, 'tags-admin-' + id);
 
 	toggletags_message_el.innerHTML = 'Commands executed.';
 }
 
-function tagsHistory(id, type) {
-	var params = {};
-	type = type || "stories";
-	params['type'] = type;
-	params['op'] = 'tags_history';
-	if (type == "stories") {
-		params['sidenc'] = id;
-	} else if (type == "urls" || type == "firehose") {
-		params['id'] = id;
-	}
-	var tagshistid = "taghist-" + id;
-	var popupid    = "taghistory-" + id;
-	var title      = "History ";
-	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");
-}
-
 function remarks_create() {
 	var reskey = $dom('remarks_reskey');
 	var remark = $dom('remarks_new');
@@ -96,31 +173,31 @@
 	}
 
 	var params = {};
-	params['op']     = 'remarks_create';
-	params['remark'] = remark.value;
-	params['reskey'] = reskey.value;
+	params.op     = 'remarks_create';
+	params.remark = remark.value;
+	params.reskey = reskey.value;
 	remarks_max = $dom('remarks_max');
 	if (remarks_max && remarks_max.value) {
-		params['limit'] = remarks_max.value;
+		params.limit = remarks_max.value;
 	}
 	ajax_update(params, 'remarks_whole');
 }
 
 function remarks_fetch(secs, limit) {
 	var params = {};
-	params['op'] = 'remarks_fetch';
-	params['limit'] = limit;
+	params.op = 'remarks_fetch';
+	params.limit = limit;
 	// run it every 30 seconds; don't need to call again
 	ajax_periodic_update(secs, params, 'remarks_table');
 }
 
 function remarks_popup() {
 	var params = {};
-	params['op'] = 'remarks_config';
+	params.op = 'remarks_config';
 	var title = "Remarks Config ";
 	var buttons = createPopupButtons('<a href="#" onclick="closePopup(\'remarksconfig-popup\', 1); return false">[X]</a>');
 	title = title + buttons;
-	createPopup(getXYForId('remarks_table'), title + buttons, 'remarksconfig');
+	createPopup(getXYForSelector('#remarks_table'), title + buttons, 'remarksconfig');
 	ajax_update(params, 'remarksconfig-contents');
 	
 }
@@ -131,18 +208,18 @@
 	var min_priority = $dom('remarks_min_priority');
 	var limit = $dom('remarks_limit');
 	var filter = $dom('remarks_filter');
-	params['op'] = 'remarks_config_save';
+	params.op = 'remarks_config_save';
 	if (!reskey && !reskey.value) {
 		return false;
 	} 
 	if (min_priority) {
-		params['min_priority'] = min_priority.value;
+		params.min_priority = min_priority.value;
 	}
 	if (limit) {
-		params['limit'] = limit.value;
+		params.limit = limit.value;
 	}
 	if (filter) {
-		params['filter'] = filter.value;
+		params.filter = filter.value;
 	}
 	var message = $dom('remarksconfig-message');
 	if (message) {
@@ -183,7 +260,7 @@
 	if(use_fh_interval) {
 		interval = getFirehoseUpdateInterval(); 
 	}
-	setTimeout(function(){console_update(use_fh_interval, fh_is_timed_out)}, interval * 2);
+	setTimeout(function(){console_update(use_fh_interval, fh_is_timed_out);}, interval * 2);
 }
 
 function firehose_usage() {
@@ -196,7 +273,7 @@
 	var selected_key   = "select_" + form_element + '_' + misspelled_word;
 	var selected_index = document.forms.slashstoryform.elements[selected_key].selectedIndex;
 	
-	if (selected_index == 0) {
+	if (selected_index === 0) {
 		return(0);
 	}
 
@@ -204,8 +281,8 @@
 	if (selected_index >= 1) {
 		if (selected_index == 1) {
 			var params = {};
-			params['op'] = 'admin_learnword';
-			params['word'] = misspelled_word;
+			params.op = 'admin_learnword';
+			params.word = misspelled_word;
 			ajax_update(params);
 		}
 		else {
@@ -243,19 +320,27 @@
 }
 
 function firehose_open_note(id) {
-	$('#note-form-'+id).removeClass();
-	$('#note-input-'+id).each(function(){this.focus()});
-	$('#note-text-'+id).setClass("hide");
+	var $entry = $('#firehose-'+id);
+
+	$entry.find('.note-wrapper').removeClass('no-note');
+	$entry.find('#note-form-'+id).removeClass('hide');
+	$entry.find('#note-input-'+id).each(function(){this.focus();});
+	$entry.find('#note-text-'+id).addClass('hide');
 }
 
 function firehose_save_note(id) {
+	var $entry = $('#firehose-'+id);
+
+	var note_text = $entry.find('#note-input-'+id).val();
+	$entry.find('.note-flag, .note-wrapper').toggleClassTo('no-note', !note_text);
+
 	ajax_update({
 		op:	'firehose_save_note',
-		note:	$('#note-input-'+id).val(),
+		note:	note_text,
 		id:	id
 	}, 'note-text-'+id);
-	$('#note-form-'+id).setClass("hide");
-	$('#note-text-'+id).removeClass();
+	$entry.find('#note-form-'+id).addClass('hide');
+	$entry.find('#note-text-'+id).removeClass('hide');
 }
 
 function firehose_get_admin_extras(id) {
@@ -278,7 +363,7 @@
 		id:	id
 	}, 'postform-'+id, {
 		onComplete: function() {
-			$dom('postform-'+id).submit()
+			$dom('postform-'+id).submit();
 		}
 	});
 }
@@ -287,7 +372,7 @@
 	$('#admin-bodytext').each(function(){
 		this.className = "show";
 		this.value += text;
-	})
+	});
 }
 
 function appendToMedia(text) {

Copied: slashjp/trunk/plugins/Ajax/htdocs/images/api.js (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/htdocs/images/api.js)
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/api.js	                        (rev 0)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/api.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,178 @@
+/* API
+
+Usage:
+	var api = new API(api_definition);
+
+api_definition is an object with the following properties, of which 'name' is
+required and all others are optional (of course the whole thing is pointless if
+you don't supply at least one of api, or element_api).
+
+	name:			non-empty string
+	api:			object with function and data members
+	element_api:		object with function members whose first argument is an element
+	element_constructor:	boolean or function
+	extend_jquery:		boolean or string
+	extend_jquery_wrapper:	boolean or function
+
+Example:
+
+	var greeter = new API({
+		name: 'greeter',
+		element_api: {
+			say_hello: function( element, person ){
+				$element.text("Hello, " + (person || "world") + "!");
+			}
+		},
+		extend_jquery_wrapper: true
+	});
+
+	var elem = $('#world-greeting')[0];
+
+	// you can now use the functions from your 'namespace'
+	greeter.say_hello(elem);
+
+	// or you can attach your api to an element...
+	greeter(elem);
+
+	// ...and then call your functions directly on the element
+	elem.greeter.say_hello('Bob');
+
+	// Because we asked to extend the jQuery wrapper, we can use our
+	// functions from a selection even without attaching the api to the
+	// selected elements
+	$('[id*=greeting]').greeter__say_hello();
+
+	// or we can use jQuery to attach the api to the selected elements
+	$('[id*=greeting]').greeter();
+
+When your element functions are called _from_ elements, 'this' will always be
+set to the element.  If your function is called in the form where the elem is
+supplied as a parameter at the call-site, 'this' is set to your global api
+object.
+
+	elem.greeter.say_hello('Bob')	// inside say_hello, 'this' is elem
+	greeter.say_hello(elem, 'Bob')	// inside say_hello, 'this' is greeter
+
+If you also supply an 'api' entry in the definition, those functions (and data
+members) will be available on greeter, above, but _not_ on individual elements
+no from a jQuery selection.
+
+If you also elect to extend_jquery itself, then jQuery will have an member named
+as your api name, or else as the string you supplied:
+
+	$.greeter
+
+...which has all the same powers as our greeter object, above.
+ */
+
+(function($){
+
+/*global window jQuery */
+
+// XXX move to Algorithm
+var clone = ($.clone = function( o ){
+	if ( !o || typeof o !== 'object' ) {
+		return o;
+	}
+
+	var o2 = new o.constructor();
+	for ( var k in o ) {
+		o2[k] = clone(o[k]);
+	}
+	return o2;
+});
+
+// return a function, fn', such that a call fn'(a, b, c) really means fn(obj, a, b, c) { this===obj }
+function proxy_fn( obj, fn ){
+	return function(){
+		return fn.apply(obj, [obj].concat($.makeArray(arguments)));
+	};
+}
+
+// attach any number of functions to obj such that, for each function, fn, in api_defn
+//	obj.fn(a, b, c) ==> api_defn.fn(elem, a, b, c){ this===elem }
+// e.g., elem.tag_server.ajax(a, b, c) ==> tag_server_api.ajax(elem, a, b, c){ this===elem }
+function attach_element_api(api_defn, elem, obj){
+	obj = obj || elem;
+	$.each(api_defn, function(fn_name, fn){
+		if ( $.isFunction(fn) ) {
+			obj[fn_name] = proxy_fn(elem, fn);
+		}
+	});
+	return obj;
+}
+
+var API = (window.API = function( o ){
+	var api_object = function(){};
+
+	var e_ctor = o.element_constructor;
+	var e_ctor_is_fn = $.isFunction(e_ctor);
+
+	var xe_ctor = undefined;
+
+	if ( o.element_api && (e_ctor === undefined || e_ctor_is_fn) ) {
+		xe_ctor = function( elem ){
+			// two steps, so e_ctor may use api already bound to obj
+			var obj = (elem[o.name] = attach_element_api(o.element_api, elem, elem[o.name]||{}));
+			var extra = e_ctor ? e_ctor.apply(elem, arguments) : clone(arguments[1]);
+			if ( extra ) {
+				$.extend(obj, extra);
+			}
+			return obj;
+		};
+		api_object = xe_ctor;
+	}
+
+	// o.element_api first, so the general api can override same-named functions
+	$.extend(api_object, o.element_api||{}, o.api||{});
+
+	// extend $ if requested
+	if ( o.extend_jquery ) {
+		$[typeof o.extend_jquery === 'string' ? o.extend_jquery : o.name] = api_object;
+	}
+
+	// extend $.fn if requested and if we have an element api
+	if ( o.element_api && o.extend_jquery_wrapper ) {
+		var j_ctor = $.isFunction(o.extend_jquery_wrapper) ? o.extend_jquery_wrapper : undefined;
+
+		// constructor
+		// $().tag_server(opts) ==> n * tag_server_api.construct(elem, opts);
+		$.fn[o.name] = j_ctor ? j_ctor : function(){
+			var args = arguments;
+			return this.each(function(){
+				// must apply to unwrap args
+				proxy_fn(this, xe_ctor).apply(this, args);
+			});
+		};
+
+		// other member functions
+		// $().tag_server__ajax(opts) ==> n * s_elem.tag_server.ajax(opts)
+		$.each(o.element_api, function( fn_name, fn ){
+			if ( $.isFunction(fn) ) {
+				$.fn[o.name + '__' + fn_name] = xe_ctor && e_ctor_is_fn ?
+					// if api has a e_ctor, we can expect elements to have been extended, e.g., elem.tag_server
+					function(){
+						var args = arguments;
+						return this.each(function(){
+							var fn_proxy = this[o.name] && this[o.name][fn_name];
+							if ( fn_proxy ) {
+								fn_proxy.apply(this, args);
+							}
+						});
+					} :
+					// ...otherwise, we expect we can run the function on _any_ element
+					function(){
+						var args = arguments;
+						return this.each(function(){
+							// must apply to unwrap args
+							proxy_fn(this, fn).apply(this, args);
+						});
+					};
+			}
+		});
+	}
+
+	return api_object;
+});
+
+})(jQuery);

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/common.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/common.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/common.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,44 +1,14 @@
 // _*_ Mode: JavaScript; tab-width: 8; indent-tabs-mode: true _*_
-// $Id$
+; // $Id$
 
-function $dom( id ) {
-	return document.getElementById(id);
-}
+/*global setFirehoseAction firehose_get_updates tagsHideBody tagsShowBody attachCompleter createTag
+	firehose_remove_all_items firehose_fix_up_down firehose_toggle_tagui_to ajax_update json_handler
+	json_update firehose_reorder firehose_get_next_updates getFirehoseUpdateInterval run_before_update
+	firehose_play firehose_add_update_timerid firehose_collapse_entry firehose_slider_end
+	firehose_slider_set_color vendorStoryPopup vendorStoryPopup2 firehose_save_tab check_logged_in
+	scrollWindowToFirehose scrollWindowToId viewWindowLeft getOffsetTop firehoseIsInWindow
+	isInWindow viewWindowTop viewWindowBottom firehose_set_cur firehose_get_onscreen */
 
-jQuery.fn.extend({
-
-	mapClass: function( map ) {
-		map['?'] = map['?'] || [];
-		return this.each(function() {
-			var unique = {};
-			var cl = [];
-			$.each($.map(this.className.split(/\s+/), function(k){
-				return k in map ? map[k] : ('*' in map ? map['*'] : k)
-			}).concat(map['+']), function(i, k) {
-				if ( k && !(k in unique) ) {
-					unique[k] = true;
-					cl.push(k);
-				}
-			});
-			this.className = (cl.length ? cl : map['?']).join(' ');
-		});
-	},
-
-	setClass: function( c1 ) {
-		return this.each(function() {
-			this.className = c1
-		});
-	},
-
-	toggleClasses: function( c1, c2, force ) {
-		var map = { '?': force };
-		map[c1]=c2;
-		map[c2]=c1;
-		return this.mapClass(map);
-	}
-
-});
-
 var reskey_static = '';
 
 // global settings, but a firehose might use a local settings object instead
@@ -55,17 +25,19 @@
   firehose_settings.not_id = 0;
   firehose_settings.section = 0;
   firehose_settings.more_num = 0;
+  firehose_settings.metamod = 0;
 
 // Settings to port out of settings object
   firehose_item_count = 0;
-  firehose_updates = Array(0);
+  firehose_updates = [];
   firehose_updates_size = 0;
-  firehose_ordered = Array(0);
-  firehose_before = Array(0);
-  firehose_after = Array(0);
+  firehose_ordered = [];
+  firehose_before = [];
+  firehose_after = [];
   firehose_removed_first = '0';
   firehose_removals = null;
   firehose_future = null;
+  firehose_more_increment = 10;
 
   var firehose_cur = 0;
 
@@ -73,22 +45,23 @@
 var fh_play = 0;
 var fh_is_timed_out = 0;
 var fh_is_updating = 0;
-var fh_update_timerids = Array(0);
+var fh_update_timerids = [];
 var fh_is_admin = 0;
 var console_updating = 0;
-var fh_colorslider; 
+var fh_colorslider;
 var fh_ticksize;
-var fh_colors = Array(0);
+var fh_colors = [];
 var fh_use_jquery = 0;
-var vendor_popup_timerids = Array(0);
+var vendor_popup_timerids = [];
 var vendor_popup_id = 0;
 var fh_slider_init_set = 0;
 var ua=navigator.userAgent;
 var is_ie = ua.match("/MSIE/");
 
 
+
 function createPopup(xy, titlebar, name, contents, message, onmouseout) {
-	var body = document.getElementsByTagName("body")[0]; 
+	var body = document.getElementsByTagName("body")[0];
 	var div = document.createElement("div");
 	div.id = name + "-popup";
 	div.style.position = "absolute";
@@ -99,7 +72,7 @@
 
 	var leftpos = xy[0] + "px";
 	var toppos  = xy[1] + "px";
-	
+
 	div.style.left = leftpos;
 	div.style.top = toppos;
 	div.style.zIndex = "100";
@@ -159,14 +132,50 @@
 	}
 }
 
-function getXYForId(id, addWidth, addHeight) {
-	var div = $('#'+id);
-	var offset = div.offset();
-	if (addWidth) offset.left += div.attr('offsetWidth');
-	if (addHeight) offset.top += div.attr('offsetHeight');
-	return [ offset.left, offset.top ];
+function getXYForSelector( selector, addWidth, addHeight ){
+	var $elem = $(selector);
+	var dX = addWidth ? $elem.attr('offsetWidth') : 0;
+	var dY = addHeight ? $elem.attr('offsetHeight') : 0;
+
+	var o = $elem.offset();
+	return [ o.left+dX, o.top+dY ];
 }
 
+// function getXYForId(id, addWidth, addHeight){ return getXYForSelector('#'+id, addWidth, addHeight); }
+
+function firehose_id_of( expr ) {
+	try {
+		// We accept a number, or...
+		if ( typeof expr === 'number' ) {
+			return expr;
+		}
+
+		// ...a dom element that is or is within a firehose entry, or...
+		else if ( typeof expr === 'object' && expr.parentNode ) {
+			if ( expr.id && expr.id.match(/-\d+$/) ) {
+				expr = expr.id;
+			} else {
+				expr = $(expr).parents('[id^=firehose-]').attr('id');
+			}
+		}
+
+		// ...a string that is a number or the id of
+		//	a dom element that is or is within a firehose entry.
+		var match = /(?:.+-)?(\d+)$/.exec(expr);
+
+		// We return an integer id.
+		if ( match ) {
+			return parseInt(match[1], 10);
+		}
+	}
+	catch ( e ) {
+		// If we can't deduce an integer id; we won't throw...
+	}
+
+	// ...but we won't return an answer, either.
+	return undefined;
+}
+
 function firehose_toggle_advpref() {
 	$('#fh_advprefs').toggleClass('hide');
 }
@@ -189,8 +198,13 @@
 	$('#'+toggleid).setClass(new_class).html(new_html);
 }
 
+
 function tagsToggleStoryDiv(id, is_admin, type) {
-	($('#toggletags-body-'+id).hasClass('tagshide') ? tagsShowBody : tagsHideBody)(id, is_admin, '', type);
+	if ( $('#toggletags-body-'+id).hasClass('tagshide') ) {
+		tagsShowBody(id, is_admin, '', type);
+	} else {
+		tagsHideBody(id);
+	}
 }
 
 function tagsHideBody(id) {
@@ -216,67 +230,69 @@
 	$('#tagbox-'+id).setClass("tags");			// Make the tagbox change to the slashbox class
 	$('#tagbox-title-'+id).setClass("tagtitleopen");	// Make the title of the tagbox change to white-on-green
 	$('#toggletags-body-'+id).setClass("tagbody");		// Make the body of the tagbox visible
-	
-	// If the tags-user div hasn't been filled, fill it.
-	var tagsuser = $('#tags-user-' + id);
-	if (tagsuser.html() == "") {
-		// The tags-user-123 div is empty, and needs to be
-		// filled with the tags this user has already
-		// specified for this story, and a reskey to allow
-		// the user to enter more tags.
-		tagsuser.html("Retrieving...");
-		var params = {};
-		if (type == "stories") {
-			params['op'] = 'tags_get_user_story';
-			params['sidenc'] = id;
-		} else if (type == "urls") {
-			//alert('getting user urls ' + id);
-			params['op'] = 'tags_get_user_urls';
-			params['id'] = id;
-		} else if (type == "firehose") {
-			params['op'] = 'tags_get_user_firehose';
-			params['id'] = id;
-		}
-		params['newtagspreloadtext'] = newtagspreloadtext;
-		var handlers = {
-			onComplete: function() { 
-				$dom('newtags-'+id).focus();
-			}
-		}
-		ajax_update(params, 'tags-user-' + id, handlers);
-		//alert('after ajax_update ' + tagsuserid);
 
-		// Also fill the admin div.  Note that if the user
-		// is not an admin, this call will not actually
-		// return the necessary form (which couldn't be
-		// submitted anyway).  The is_admin parameter just
-		// saves us an ajax call to find that out, if the
-		// user is not actually an admin.
-		if (is_admin) {
-			var tagsadminid = 'tags-admin-' + id;
-			params = {};
+	// If there is a tags-user div, and it hasn't been filled, fill it.
+	var $tagsuser = $('#tags-user-' + id);
+	if ( $tagsuser.length ) {
+		if ($tagsuser.html() === "") {
+			// The tags-user-123 div is empty, and needs to be
+			// filled with the tags this user has already
+			// specified for this story, and a reskey to allow
+			// the user to enter more tags.
+			$tagsuser.html("Retrieving...");
+			var params = {};
 			if (type == "stories") {
-				params['op'] = 'tags_get_admin_story';
-				params['sidenc'] = id;
+				params.op = 'tags_get_user_story';
+				params.sidenc = id;
 			} else if (type == "urls") {
-				params['op'] = 'tags_get_admin_url';
-				params['id'] = id;
+				//alert('getting user urls ' + id);
+				params.op = 'tags_get_user_urls';
+				params.id = id;
 			} else if (type == "firehose") {
-				params['op'] = 'tags_get_admin_firehose';
-				params['id'] = id;
+				params.op = 'tags_get_user_firehose';
+				params.id = id;
 			}
-			ajax_update(params, tagsadminid);
-		}
+			params.newtagspreloadtext = newtagspreloadtext;
+			var handlers = {
+				onComplete: function() {
+					$dom('newtags-'+id).focus();
+				}
+			};
+			ajax_update(params, 'tags-user-' + id, handlers);
+			//alert('after ajax_update ' + tagsuserid);
 
-	} else {
-		if (newtagspreloadtext) {
-			// The box was already open but it was requested
-			// that we append some text to the user text.
-			// We can't do that by passing it in, so do it
-			// manually now.
-			var textinput = $dom('newtags-'+id);
-			textinput.value += ' ' + newtagspreloadtext;
-			textinput.focus();
+			// Also fill the admin div.  Note that if the user
+			// is not an admin, this call will not actually
+			// return the necessary form (which couldn't be
+			// submitted anyway).  The is_admin parameter just
+			// saves us an ajax call to find that out, if the
+			// user is not actually an admin.
+			if (is_admin) {
+				var tagsadminid = 'tags-admin-' + id;
+				params = {};
+				if (type == "stories") {
+					params.op = 'tags_get_admin_story';
+					params.sidenc = id;
+				} else if (type == "urls") {
+					params.op = 'tags_get_admin_url';
+					params.id = id;
+				} else if (type == "firehose") {
+					params.op = 'tags_get_admin_firehose';
+					params.id = id;
+				}
+				ajax_update(params, tagsadminid);
+			}
+
+		} else {
+			if (newtagspreloadtext) {
+				// The box was already open but it was requested
+				// that we append some text to the user text.
+				// We can't do that by passing it in, so do it
+				// manually now.
+				var textinput = $dom('newtags-'+id);
+				textinput.value += ' ' + newtagspreloadtext;
+				textinput.focus();
+			}
 		}
 	}
 }
@@ -287,24 +303,27 @@
 }
 
 function completer_renameMenu( s, params ) {
-	if ( s )
+	if ( s ) {
 		params._sourceEl.innerHTML = s;
+	}
 }
 
 function completer_setTag( s, params ) {
 	createTag(s, params._id, params._type);
 	var tagField = document.getElementById('newtags-'+params._id);
 	if ( tagField ) {
-		var s = tagField.value.slice(-1);
-		if ( s.length && s != " " )
+		var end_char = tagField.value.slice(-1);
+		if ( end_char.length && end_char != " " ) {
 			tagField.value += " ";
+		}
 		tagField.value += s;
 	}
 }
 
 function completer_handleNeverDisplay( s, params ) {
-	if ( s == "neverdisplay" )
+	if ( s == "neverdisplay" ) {
 		admin_neverdisplay("", "firehose", params._id);
+	}
 }
 
 function completer_save_tab(s, params) {
@@ -318,25 +337,29 @@
 function focusCompleter( obj, id, is_admin, type, tagDomain, customize ) {
 	if ( navigator.vendor !== undefined ) {
 		var vendor = navigator.vendor.toLowerCase();
-		if ( vendor.indexOf("apple") != -1
-				|| vendor.indexOf("kde") != -1 )
+		if ( vendor.indexOf("apple") != -1 ||
+				vendor.indexOf("kde") != -1 ) {
 			return false;
+		}
 	}
 
 	return attachCompleter(obj, id, is_admin, type, tagDomain, customize);
 }
 
 function attachCompleter( obj, id, is_admin, type, tagDomain, customize ) {
-	if ( customize === undefined )
-		customize = new Object();
+	if ( customize === undefined ) {
+		customize = {};
+	}
 	customize._id = id;
 	customize._is_admin = is_admin;
 	customize._type = type;
-	if ( tagDomain != 0 && customize.queryOnAttach === undefined )
+	if ( tagDomain !== 0 && customize.queryOnAttach === undefined ) {
 		customize.queryOnAttach = true;
-	
-	if ( !YAHOO.slashdot.gCompleterWidget )
+	}
+
+	if ( !YAHOO.slashdot.gCompleterWidget ) {
 		YAHOO.slashdot.gCompleterWidget = new YAHOO.slashdot.AutoCompleteWidget();
+	}
 
 	YAHOO.slashdot.gCompleterWidget.attach(obj, customize, tagDomain);
 	return false;
@@ -349,16 +372,16 @@
 
 function createTag(tag, id, type) {
 	var params = {};
-	params['id'] = id;
-	params['type'] = type;
+	params.id = id;
+	params.type = type;
 	if ( fh_is_admin && ("_#)^*".indexOf(tag[0]) != -1) ) {
-	  params['op'] = 'tags_admin_commands';
-	  params['reskey'] = $('#admin_commands-reskey-' + id).val();
-	  params['command'] = tag;
+	  params.op = 'tags_admin_commands';
+	  params.reskey = $('#admin_commands-reskey-' + id).val();
+	  params.command = tag;
 	} else {
-	  params['op'] = 'tags_create_tag';
-	  params['reskey'] = reskey_static;
-	  params['name'] = tag;
+	  params.op = 'tags_create_tag';
+	  params.reskey = reskey_static;
+	  params.name = tag;
 	  if ( fh_is_admin && (tag == "hold") ) {
 	    firehose_collapse_entry(id);
 	  }
@@ -402,10 +425,9 @@
 		tags: newtag
 	});
 }
-
 function tagsCreateForFirehose(id) {
 	var status = $('#toggletags-message-'+id).html('Saving tags...');
-	
+
 	ajax_update({
 		op:	'tags_create_for_firehose',
 		id:	id,
@@ -419,26 +441,28 @@
 function toggle_firehose_body(id, is_admin) {
 	var params = {};
 	setFirehoseAction();
-	params['op'] = 'firehose_fetch_text';
-	params['id'] = id;
+	params.op = 'firehose_fetch_text';
+	params.id = id;
 	var fhbody = $dom('fhbody-'+id);
 	var fh = $dom('firehose-'+id);
+
 	var usertype = fh_is_admin ? " adminmode" : " usermode";
 	if (fhbody.className == "empty") {
 		var handlers = {
 			onComplete: function() {
-				if(firehoseIsInWindow(id)) { 
-					scrollToWindowFirehose(id); 
+				if(firehoseIsInWindow(id)) {
+					scrollWindowToFirehose(id);
 				}
-				firehose_get_admin_extras(id); 
+				firehose_get_admin_extras(id);
 			}
 		};
-		params['reskey'] = reskey_static;
+		params.reskey = reskey_static;
 		ajax_update(params, 'fhbody-'+id, is_admin ? handlers : null);
 		fhbody.className = "body";
 		fh.className = "article" + usertype;
-		if (is_admin)
-			tagsShowBody(id, is_admin, '', "firehose");
+		if (is_admin) {
+			firehose_toggle_tagui_to(true, fh);
+		}
 	} else if (fhbody.className == "body") {
 		fhbody.className = "hide";
 		fh.className = "briefarticle" + usertype;
@@ -447,6 +471,9 @@
 	} else if (fhbody.className == "hide") {
 		fhbody.className = "body";
 		fh.className = "article" + usertype;
+		if (is_admin) {
+			firehose_toggle_tagui_to(true, fh);
+		}
 		/*if (is_admin)
 			tagsShowBody(id, is_admin, '', "firehose"); */
 	}
@@ -457,8 +484,12 @@
 }
 
 function firehose_set_options(name, value) {
+	if (name == "color" && value === undefined) {
+		return;
+	}
+
 	var pairs = [
-		// name		value		curid		newid		newvalue 	title 
+		// name		value		curid		newid		newvalue 	title
 		["orderby", 	"createtime", 	"popularity",	"time",		"popularity"	],
 		["orderby", 	"popularity", 	"time",		"popularity",	"createtime"	],
 		["orderdir", 	"ASC", 		"asc",		"desc",		"DESC"],
@@ -467,24 +498,20 @@
 		["mode", 	"fulltitle", 	"full",		"abbrev",	"full"]
 	];
 	var params = {};
-	params['op'] = 'firehose_set_options';
-	params['reskey'] = reskey_static;
-	var theForm = document.forms["firehoseform"];
+	params.setting_name = name;
+	params.op = 'firehose_set_options';
+	params.reskey = reskey_static;
+	var theForm = document.forms.firehoseform;
 	if (name == "firehose_usermode") {
-		if (value ==  true) {
-			value = 1;
-		}
-		if (value == false) {
-			value = 0;
-		}
-		params['setusermode'] = 1;
+		value = value ? 1 : 0;
+		params.setusermode = 1;
 		params[name] = value;
 	}
 
 	if (name == "nodates" || name == "nobylines" || name == "nothumbs" || name == "nocolors" || name == "mixedmode" || name == "nocommentcnt" || name == "nomarquee" || name == "noslashboxes") {
-		value = value == true ? 1 : 0;
+		value = value ? 1 : 0;
 		params[name] = value;
-		params['setfield'] = 1;
+		params.setfield = 1;
 		var classname;
 		if (name == "nodates") {
 			classname = "date";
@@ -506,18 +533,26 @@
 		firehose_settings.page = 0;
 		firehose_settings.more_num = 0;
 	}
+
+	if (name == "setfhfilter") {
+		firehose_settings.fhfilter = value;
+		firehose_settings.page = 0;
+		firehose_settings.more_num = 0;
+	}
+
 	if (name != "color") {
 	for (i=0; i< pairs.length; i++) {
 		var el = pairs[i];
 		if (name == el[0] && value == el[1]) {
 			firehose_settings[name] = value;
-			if ($dom(el[2])) {
-				$dom(el[2]).id = el[3];
-				if($dom(el[3])) {
-					var namenew = el[0];
-					var valuenew = el[4];
-					$dom(el[3]).firstChild.onclick = function() { firehose_set_options(namenew, valuenew); return false;}
-				}
+			var $ctrl = $('#'+el[2]);
+			if ( $ctrl.length ) {
+				$ctrl.attr('id', el[3]);
+				var namenew = el[0], valuenew = el[4];
+				$ctrl.children().eq(0).click(function(){
+					firehose_set_options(namenew, valuenew);
+					return false;
+				});
 			}
 		}
 	}
@@ -529,12 +564,12 @@
 		if ($dom('firehoselist')) {
 			// set page
 			page = 0;
-			
+
 			if (!is_ie) {
-				var attributes = { 
+				var attributes = {
 					opacity: { from: 1, to: 0 }
 				};
-				var myAnim = new YAHOO.util.Anim("firehoselist", attributes); 
+				var myAnim = new YAHOO.util.Anim("firehoselist", attributes);
 				myAnim.duration = 1;
 				myAnim.onComplete.subscribe(function() {
 					$dom('firehoselist').style.opacity = "1";
@@ -542,12 +577,12 @@
 				myAnim.animate();
 			}
 			// remove elements
-			setTimeout(firehose_remove_all_items, 600);
+			firehose_remove_all_items();
 		}
 	}
 	}
 
-	if (name == "color" || name == "tab" || name == "pause" || name == "startdate" || name == "duration" || name == "issue" || name == "pagesize") { 
+	if (name == "color" || name == "tab" || name == "pause" || name == "startdate" || name == "duration" || name == "issue" || name == "pagesize") {
 		params[name] = value;
 		if (name == "startdate") {
 			firehose_settings.startdate = value;
@@ -577,7 +612,7 @@
 	}
 
 	var handlers = {
-		onComplete: function(transport) { 
+		onComplete: function(transport) {
 			json_handler(transport);
 			firehose_get_updates({ oneupdate: 1 });
 		}
@@ -585,17 +620,19 @@
 
 	if (name == 'tabsection') {
 		firehose_settings.section = value;
-		params['tabtype'] = 'tabsection';
+		params.tabtype = 'tabsection';
 	}
 
 	if (name == 'tabtype') {
-		params['tabtype'] = value;
+		params.tabtype = value;
 	}
 
-	params['section'] = firehose_settings.section;
-	for (i in firehose_settings) {
-		params[i] = firehose_settings[i];
+	if (name == 'more_num') {
+		params.ask_more = 1;
 	}
+
+	params.section = firehose_settings.section;
+	$.extend(params, firehose_settings);
 	ajax_update(params, '', handlers);
 }
 
@@ -604,24 +641,65 @@
 }
 
 
-function firehose_up_down(id, dir) {
-	if (!check_logged_in()) return;
+function firehose_up_down(id, dir, type) {
+	if (!check_logged_in()) { return; }
 
 	setFirehoseAction();
+	var meta = 0;
+	if (type && type == "comment") {
+		meta = 1;
+	}
 	ajax_update({
 		op:	'firehose_up_down',
 		id:	id,
 		reskey:	reskey_static,
-		dir:	dir
+		dir:	dir,
+		meta:	meta
 	}, '', { onComplete: json_handler });
 
-	$('#updown-'+id).setClass(dir=='+' ? 'votedup' : 'voteddown');
 
-	if (dir == "-" && fh_is_admin) {
+	// We changed the tags outside the notice of the tag widget (if any).
+	// If there is one, we need to tell it.  Look for the tag widget.
+	var new_context = {'+':'nod', '-':'nix'}[dir];
+	var found_widgets = 0;
+
+	var $server = $('#firehoselist > [tag-server='+id+']');
+	$server.find('.tag-widget').
+			each(function(){
+				++found_widgets;
+				this.set_context(new_context);
+			});
+
+	if ( found_widgets ) {
+		$server[0].fetch_tags();
+	} else {
+		// No tag widget; we have to call directly...
+		firehose_fix_up_down(id, {'+':'votedup', '-':'voteddown'}[dir]);
+	}
+}
+
+function firehose_fix_up_down(id, new_state) {
+	// Find the (possibly) affected +/- capsule.
+	var $updown = $('#updown-'+id);
+
+	if ( $updown.length && ! $updown.hasClass(new_state) ) {
+		// We found the capsule, and it's state needs to be fixed.
+		$updown.setClass(new_state);
+	}
+}
+
+function firehose_click_nodnix_reason( event ) {
+	var $entry = $(event.target).nearest_parent('[tag-server]');
+	var id = $entry.attr('tag-server');
+
+	if ( (fh_is_admin || firehose_settings.metamod) && ($('#updown-'+id).hasClass('voteddown') || $entry.is('[type=comment]')) ) {
 		firehose_collapse_entry(id);
 	}
+
+	return true;
 }
 
+
 function firehose_remove_tab(tabid) {
 	setFirehoseAction();
 	ajax_update({
@@ -634,43 +712,278 @@
 }
 
 
+//
+// firehose + tagui
+//
+
+var $related_trigger = $().filter();
+
+function firehose_toggle_tagui_to( if_expanded, selector ){
+	var	$server = $(selector).nearest_parent('[tag-server]'),
+		$widget = $server.find('.tag-widget.body-widget'),
+		id	= $server.attr('tag-server');
+
+	setFirehoseAction();
+	$server.find('.tag-widget').each(function(){ this.set_context(); });
+
+	$widget.toggleClassTo('expanded', if_expanded);
+
+	var toggle_button={}, toggle_div={};
+	if ( if_expanded ){
+		$server.each(function(){ this.fetch_tags(); });
+		if ( fh_is_admin ) {
+			firehose_get_admin_extras(id);
+		}
+		$widget.find('.tag-entry:visible:first').each(function(){ this.focus(); });
+
+		toggle_button['+'] = (toggle_button.collapse = 'expand');
+		toggle_div['+'] = (toggle_div.tagshide = 'tagbody');
+	} else {
+		toggle_button['+'] = (toggle_button.expand = 'collapse');
+		toggle_div['+'] = (toggle_div.tagbody = 'tagshide');
+	}
+
+	$widget.find('a.edit-toggle .button').mapClass(toggle_button);
+	$server.find('#toggletags-body-'+id).mapClass(toggle_div);
+}
+
+function firehose_toggle_tagui( toggle ) {
+	firehose_toggle_tagui_to( ! $(toggle.parentNode).hasClass('expanded'), toggle );
+}
+
+function firehose_click_tag( event ) {
+	var $target = $(event.target);
+	var command='';
+
+	$related_trigger = $target;
+
+	if ( $target.is('a.up') ) {
+		command = 'nod';
+	} else if ( $target.is('a.down') ) {
+		command = 'nix';
+	} else if ( $target.is('.tag') ) {
+		command = $target.text();
+	} else if ( $target.nearest_parent('.tmenu').length ) {
+		var op = $target.text();
+		var $tag = $target.nearest_parent(':has(span.tag)').find('.tag');
+		$related_trigger = $tag;
+
+		var tag = $tag.text();
+		command = normalize_tag_menu_command(tag, op);
+	} else {
+		$related_target = $().filter();
+	}
+
+	if ( command ) {
+		var $server = $target.nearest_parent('[tag-server]');
+
+		if ( event.shiftKey ) {
+			// if the shift key is down, append the tag to the edit field
+			$server.find('.tag-entry:text:visible:first').each(function(){
+				if ( this.value ) {
+					var last_char = this.value[ this.value.length-1 ];
+					if ( '-^#!)_ '.indexOf(last_char) == -1 ) {
+						this.value += ' ';
+					}
+				}
+				this.value += command;
+				this.focus();
+			});
+		} else {
+			// otherwise, send it the server to be processed
+			$server.each(function(){
+				this.submit_tags(command, { fade_remove: 400, order: 'prepend', classes: 'not-saved'});
+			});
+		}
+		return false;
+	}
+
+	return true;
+}
+
+
+function firehose_handle_context_triggers( commands ){
+	var context;
+	commands = $.map(commands, function(cmd){
+		if ( cmd in context_triggers ) {
+			context = cmd;
+			cmd = null;
+		}
+		return cmd;
+	});
+
+	$('.tag-widget:not(.nod-nix-reasons)', this).
+		each(function(){
+			this.set_context(context);
+		});
+
+	return commands;
+}
+
+
+function firehose_handle_nodnix( commands ){
+	if ( commands.length ) {
+		var $reasons = $('.nod-nix-reasons', this);
+		var nodnix_context = function( ctx ){
+			$reasons.each(function(){
+				this.set_context(ctx);
+			});
+		};
+
+		var tag_server=this, context_not_set=true;
+		$.each(commands.slice(0).reverse(), function(i, cmd){
+			if ( cmd=='nod' || cmd=='nix' ) {
+				nodnix_context(cmd);
+				context_not_set = false;
+				firehose_fix_up_down(
+					tag_server.getAttribute('tag-server'),
+					{ nod:'votedup', nix:'voteddown' }[cmd] );
+				return false;
+			}
+		});
+
+		if ( context_not_set ) {
+			nodnix_context(undefined);
+		}
+	}
+
+	return commands;
+}
+
+function firehose_handle_comment_nodnix( commands ){
+	if ( commands.length ) {
+		var tag_server=this, handled_underlying=false;
+		commands = $.map(commands.reverse(), function( cmd ){
+			var match = /^([\-!]*)(nod|nix)$/.exec(cmd);
+			if ( match ) {
+				var modifier = match[1], vote = match[2];
+				cmd = modifier + 'meta' + vote;
+				if ( !handled_underlying && !modifier ) {
+					var id = tag_server.getAttribute('tag-server');
+					firehose_fix_up_down(
+						id,
+						{ nod:'votedup', nix:'voteddown' }[vote] );
+					firehose_collapse_entry(id);
+					handled_underlying = true;
+				}
+			}
+			return cmd;
+		}).reverse();
+
+		$('.nod-nix-reasons', this).each(function(){
+			this.set_context(undefined);
+		});
+	}
+
+	return commands;
+}
+
+
+function firehose_init_tagui( $new_entries ){
+	if ( ! $new_entries || ! $new_entries.length ) {
+		var $firehoselist = $('#firehoselist');
+		if ( $firehoselist.length ) {
+			$new_entries = $firehoselist.children('[id^=firehose-][class*=article]');
+		} else {
+			$new_entries = $('[id^=firehose-][class*=article]');
+		}
+	}
+
+	$new_entries = $new_entries.filter(':not([tag-server])');
+
+	$new_entries.
+		each(function(){
+			var $this = $(this), id = firehose_id_of(this);
+
+			install_tag_server(this, id);
+
+			if ( fh_is_admin ) {
+				this.command_pipeline.push(firehose_handle_admin_commands);
+
+				var $note_flag = $this.find('.title h3').
+					append('<span class="note-flag">note</span>').
+					find('.note-flag').
+					attr('title', "don't click; I am not a button");
+
+				var $note_wrapper = $this.find('.note-wrapper');
+				if ( ! $note_wrapper.length || $note_wrapper.hasClass('no-note') ) {
+					$note_flag.addClass('no-note');
+				}
+			}
+
+			this.command_pipeline.push(
+				firehose_handle_context_triggers,
+				($this.attr('type') == 'comment') ?
+					firehose_handle_comment_nodnix :
+					firehose_handle_nodnix );
+
+			$this.
+				find('.title').
+					append('<div class="tag-widget-stub nod-nix-reasons" init="context_timeout:15000">' +
+							'<div class="tag-display-stub" context="related" init="legend:\'why\', menu:false" />' +
+						'</div>').
+					find('.tag-display-stub').
+						click(firehose_click_nodnix_reason);
+		});
+
+	var $widgets = $init_tag_widgets($new_entries.find('.tag-widget-stub'));
+
+	if ( fh_is_admin ) {
+		$widgets.
+			filter('.body-widget').
+				each(function(){
+					this.modify_context = firehose_admin_context;
+				});
+	}
+
+	init_tagui_styles($new_entries);
+}
 // firehose functions end
 
 // helper functions
-function ajax_update(request_params, id, handlers, request_url) {
+function ajax_update(request_params, id, handlers, options) {
 	// make an ajax request to request_url with request_params, on success,
 	//  update the innerHTML of the element with id
+	if ( !options ) {
+		options = {};
+	}
 
 	var opts = {
-		url: request_url || '/ajax.pl',
+		url: options.request_url || '/ajax.pl',
 		data: request_params,
 		type: 'POST',
 		contentType: 'application/x-www-form-urlencoded'
 	};
 
+	if ( options.async_off ) {
+		opts.async = false;
+	}
+
 	if ( id ) {
-		opts['success'] = function(html){
+		opts.success = function(html){
 			$('#'+id).html(html);
-		}
+		};
 	}
 
 	if ( handlers && handlers.onComplete ) {
-		opts['complete'] = handlers.onComplete;
+		opts.complete = handlers.onComplete;
 	}
 
 	jQuery.ajax(opts);
 }
 
-function ajax_periodic_update(interval_in_seconds, request_params, id, handlers, request_url) {
+function ajax_periodic_update(interval_in_seconds, request_params, id, handlers, options) {
 	setInterval(function(){
-		ajax_update(request_params, id, handlers, request_url);
+		ajax_update(request_params, id, handlers, options);
 	}, interval_in_seconds*1000);
 }
 
 function eval_response(transport) {
 	var response;
 	try {
-		eval("response = " + transport.responseText)
+/*jslint evil: true */
+		eval("response = " + transport.responseText);
+/*jslint evil: false */
 	} catch (e) {
 		//alert(e + "\n" + transport.responseText)
 	}
@@ -686,50 +999,67 @@
 function json_update(response) {
 	if (response.eval_first) {
 		try {
-			eval(response.eval_first)
-		} catch (e) {
+/*jslint evil: true */
+			eval(response.eval_first);
+/*jslint evil: false */
+		} catch (e0) {
 
 		}
 	}
 
 	if (response.html) {
-		for (el in response.html) {
-			$('#'+el).html(response.html[el]);
+		var new_content = response.html;
+		for (id in new_content) {
+			if ( new_content.hasOwnProperty(id) ) {
+				$('#'+id).html(new_content[id]);
+			}
 		}
-		
-	} 
 
+	}
+
 	if (response.value) {
-		for (el in response.value) {
-			$('#'+el).val(response.value[el]);
+		var new_value = response.value;
+		for (id in new_value) {
+			if ( new_value.hasOwnProperty(id) ) {
+				$('#'+id).val(new_value[id]);
+			}
 		}
 	}
 
 	if (response.html_append) {
-		for (el in response.html_append) {
-			$('#'+el).each(function(){
-				this.innerHTML += response.html_append[el];
-			});
+		new_content = response.html_append;
+		for (id in new_content) {
+			if ( new_content.hasOwnProperty(id) ) {
+				$('#'+id).each(function(){
+					this.innerHTML += new_content[id];
+				});
+			}
 		}
 	}
 
 	if (response.html_append_substr) {
-		for (el in response.html_append_substr) {
-			var found = $('#'+el);
-			if (found.size()) {
-				var this_html = found.html();
-				var pos = this_html.search(/<span class="?substr"?> ?<\/span>[\s\S]*$/i);
-				if ( pos != -1 )
-					this_html = this_html.substr(0, pos);
-				found.html(this_html + response.html_append_substr[el]);
+		new_content = response.html_append_substr;
+		for (id in new_content) {
+			if ( new_content.hasOwnProperty(id) ) {
+				var $found = $('#'+id);
+				if ($found.size()) {
+					var existing_content = $found.html();
+					var pos = existing_content.search(/<span class="?substr"?> ?<\/span>[\s\S]*$/i);
+					if ( pos != -1 ) {
+						existing_content = existing_content.substr(0, pos);
+					}
+					$found.html(existing_content + new_content[id]);
+				}
 			}
 		}
-	}		
-	
+	}
+
 	if (response.eval_last) {
 		try {
-			eval(response.eval_last)
-		} catch (e) {
+/*jslint evil: true */
+			eval(response.eval_last);
+/*jslint evil: false */
+		} catch (e1) {
 
 		}
 	}
@@ -737,33 +1067,50 @@
 
 
 function firehose_handle_update() {
+	var saved_selection = new $.TextSelection(gFocusedText);
+	var $menu = $('.ac_results:visible');
+
 	if (firehose_updates.length > 0) {
 		var el = firehose_updates.pop();
 		var fh = 'firehose-' + el[1];
 		var wait_interval = 800;
+		var need_animate = 1;
+
+		var attributes = {};
+		var myAnim;
+
 		if(el[0] == "add") {
 			if (firehose_before[el[1]] && $('#firehose-' + firehose_before[el[1]]).size()) {
 				$('#firehose-' + firehose_before[el[1]]).after(el[2]);
+				if (!isInWindow($dom('title-'+ firehose_before[el[1]]))) {
+					need_animate = 0;
+				}
 			} else if (firehose_after[el[1]] && $('#firehose-' + firehose_after[el[1]]).size()) {
 				$('#firehose-' + firehose_after[el[1]]).before(el[2]);
+				if (!isInWindow($dom('title-'+ firehose_after[el[1]]))) {
+					need_animate = 0;
+				}
 			} else if (insert_new_at == "bottom") {
 				$('#firehoselist').append(el[2]);
+				if (!isInWindow($dom('fh-paginate'))) {
+					need_animate = 0;
+				}
 			} else {
 				$('#firehoselist').prepend(el[2]);
 			}
-		
+
 			var toheight = 50;
 			if (fh_view_mode == "full") {
 				toheight = 200;
 			}
 
-			var attributes = { 
+			attributes = {
 				height: { from: 0, to: toheight }
 			};
 			if (!is_ie) {
 				attributes.opacity = { from: 0, to: 1 };
 			}
-			var myAnim = new YAHOO.util.Anim(fh, attributes); 
+			myAnim = new YAHOO.util.Anim(fh, attributes);
 			myAnim.duration = 0.7;
 
 			if (firehose_updates_size > 10) {
@@ -781,36 +1128,37 @@
 			}
 
 			myAnim.onComplete.subscribe(function() {
-				if ($dom(fh)) {
-					$dom(fh).style.height = "";
+				var fh_node = $dom(fh);
+				if (fh_node) {
+					fh_node.style.height = "";
 					if (fh_use_jquery) {
-						jQuery("#" + fh + " h3 a[class!='skin']").click(
-				                	function(){
-                	        				jQuery(this).parent('h3').next('div.hide').toggle("fast");
-				                        	jQuery(this).parent('h3').find('a img').toggle("fast");
-                        			        	return false;
-                        				}
-                				);
+						$("h3 a[class!='skin']", fh_node).click(function(){
+							var h3 = $(this).parent('h3');
+							h3.next('div.hid').and(h3.find('a img')).toggle("fast");
+							return false;
+						});
 					}
 				}
 			});
-			myAnim.animate();
+			if (need_animate) {
+				myAnim.animate();
+			}
 		} else if (el[0] == "remove") {
 			var fh_node = $dom(fh);
 			if (fh_is_admin && fh_view_mode == "fulltitle" && fh_node && fh_node.className == "article" ) {
 				// Don't delete admin looking at this in expanded view
 			} else {
-				var attributes = { 
+				attributes = {
 					height: { to: 0 }
 				};
-				
+
 				if (!is_ie) {
 					attributes.opacity = { to: 0};
 				}
-				var myAnim = new YAHOO.util.Anim(fh, attributes); 
+				myAnim = new YAHOO.util.Anim(fh, attributes);
 				myAnim.duration = 0.4;
 				wait_interval = 500;
-				
+
 				if (firehose_updates_size > 10) {
 					myAnim.duration = myAnim.duration * 2;
 					if (!firehose_removed_first) {
@@ -820,14 +1168,18 @@
 					}
 				}
 				firehose_removed_first = 1;
-				if (firehose_removals < 10 ) {
+				if (!isInWindow(fh_node)) {
+					need_animate = 0;
+				}
+
+				if ((firehose_removals < 10 ) || !need_animate) {
 					myAnim.onComplete.subscribe(function() {
 						var elem = this.getEl();
 						if (elem && elem.parentNode) {
 							elem.parentNode.removeChild(elem);
 						}
 					});
-					myAnim.animate(); 
+					myAnim.animate();
 				} else {
 					var elem = $dom(fh);
 					wait_interval = 25;
@@ -837,14 +1189,39 @@
 				}
 			}
 		}
+		if(!need_animate) {
+			wait_interval = 10;
+		}
 		setTimeout(firehose_handle_update, wait_interval);
 	} else {
 		firehose_reorder();
 		firehose_get_next_updates();
 	}
+
+	firehose_init_tagui();
+
+	saved_selection.restore().focus();
+	$menu.show();
 }
 
+function firehose_adjust_window(onscreen) {
+	var i=0;
+	var on = 0;
+	while(i < onscreen.length && on === 0) {
+		if(isInWindow($(onscreen[i]))) {
+			on = 1;
+		} else {
+			scrollWindowToId(onscreen[i]);
+			if(isInWindow($(onscreen[i]))) {
+				on = 1;
+			}
+		}
+		i++;
+	}
+}
+
 function firehose_reorder() {
+	var onscreen = firehose_get_onscreen();
 	if (firehose_ordered) {
 		var fhlist = $('#firehoselist');
 		if (fhlist) {
@@ -860,7 +1237,13 @@
 					$('#ttype-'+firehose_ordered[i]+'.future').setClass('story');
 				}
 			}
-			document.title = "[% sitename %] - " + (console_updating ? "Console" : "Firehose") + " (" + firehose_item_count + ")";
+			var newtitle = document.title;
+			if (/\(\d+\)/.test(newtitle)) {
+				newtitle = newtitle.replace(/(\(\d+\))/,"(" + firehose_item_count + ")");
+			} else {
+				newtitle = newtitle + " (" + firehose_item_count + ")";
+			}
+			document.title = newtitle;
 		}
 	}
 
@@ -873,16 +1256,15 @@
 	firehose_add_update_timerid(setTimeout(firehose_get_updates, interval));
 }
 
-
 function firehose_get_updates_handler(transport) {
-	$('#busy').setClass('hide');
+	$('.busy').hide();
 	var response = eval_response(transport);
 	var processed = 0;
 	firehose_removals = response.update_data.removals;
 	firehose_ordered = response.ordered;
 	firehose_future = response.future;
-	firehose_before = Array(0);
-	firehose_after = Array(0);
+	firehose_before = [];
+	firehose_after = [];
 	for (i = 0; i < firehose_ordered.length; i++) {
 		if (i > 0) {
 			firehose_before[firehose_ordered[i]] = firehose_ordered[i - 1];
@@ -914,16 +1296,16 @@
 function firehose_get_updates(options) {
 	options = options || {};
 	run_before_update();
-	if ((fh_play == 0 && !options.oneupdate) || fh_is_updating == 1) {
+	if ((fh_play === 0 && !options.oneupdate) || fh_is_updating == 1) {
 		firehose_add_update_timerid(setTimeout(firehose_get_updates, 2000));
 	//	alert("wait loop: " + fh_is_updating);
 		return;
 	}
 	if (fh_update_timerids.length > 0) {
 		var id = 0;
-		while(id = fh_update_timerids.pop()) { clearTimeout(id) };
+		while((id = fh_update_timerids.pop())) { clearTimeout(id); }
 	}
-	fh_is_updating = 1
+	fh_is_updating = 1;
 	var params = {
 		op:		'firehose_get_updates',
 		ids:		firehose_get_item_idstring(),
@@ -933,14 +1315,15 @@
 	};
 
 	for (i in firehose_settings) {
-		params[i] = firehose_settings[i];
+		if ( firehose_settings.hasOwnProperty(i) ) {
+			params[i] = firehose_settings[i];
+		}
 	}
 
-	$('#busy').removeClass();
+	$('.busy').show();
 	ajax_update(params, '', { onComplete: firehose_get_updates_handler });
 }
 
-
 function setFirehoseAction() {
 	var thedate = new Date();
 	var newtime = thedate.getTime();
@@ -950,7 +1333,7 @@
 		firehose_play();
 		firehose_get_updates();
 		if (console_updating) {
-			console_update(1, 0)
+			console_update(1, 0);
 		}
 	}
 }
@@ -979,7 +1362,7 @@
 	var secs = getSecsSinceLastFirehoseAction();
 	if (secs > inactivity_timeout) {
 		fh_is_timed_out = 1;
-		$('#message_area').html("Automatic updates have been slowed due to inactivity")
+		$('#message_area').html("Automatic updates have been slowed due to inactivity");
 		//firehose_pause();
 	}
 }
@@ -1007,26 +1390,28 @@
 }
 
 function firehose_add_update_timerid(timerid) {
-	fh_update_timerids.push(timerid);		
+	fh_update_timerids.push(timerid);
 }
 
 function firehose_collapse_entry(id) {
-	$('#fhbody-'+id+'.body').setClass('hide');
-	$('#firehose-'+id).setClass('briefarticle');
-	tagsHideBody(id)
-
+	$('#firehoselist > #firehose-'+id).
+		find('#fhbody-'+id+'.body').
+			setClass('hide').
+		end().
+		setClass('briefarticle');
+	tagsHideBody(id);
 }
 
 function firehose_remove_entry(id) {
 	var fh = $dom('firehose-' + id);
 	if (fh) {
-		var attributes = { 
+		var attributes = {
 			height: { to: 0 }
 		};
 		if (!is_ie) {
 			attributes.opacity = { to: 0 };
 		}
-		var myAnim = new YAHOO.util.Anim(fh, attributes); 
+		var myAnim = new YAHOO.util.Anim(fh, attributes);
 		myAnim.duration = 0.5;
 		myAnim.onComplete.subscribe(function() {
 			var el = this.getEl();
@@ -1036,12 +1421,12 @@
 	}
 }
 
-var firehose_cal_select_handler = function(type,args,obj) { 
+var firehose_cal_select_handler = function(type,args,obj) {
 	var selected = args[0];
 	firehose_settings.issue = '';
 	firehose_set_options('startdate', selected.startdate);
 	firehose_set_options('duration', selected.duration);
-}; 
+};
 
 
 function firehose_calendar_init( widget ) {
@@ -1055,17 +1440,21 @@
 		var fh_get_val_return = fh_colorslider.getValue();
 		fh_colorslider.subscribe("slideEnd", firehose_slider_end);
 	}
-}	
+}
 
 function firehose_slider_end(offsetFromStart) {
-	var newVal = fh_colorslider.getValue();
+	var newVal = Math.round(fh_colorslider.getValue());
 	if (newVal) {
 		fh_slider_init_set = 1;
 	}
 	var color = fh_colors[ newVal / fh_ticksize ];
-	$dom('fh_slider_img').title = "Firehose filtered to " + color;
-	if (fh_slider_init_set) {
-		firehose_set_options("color", color)
+	if (color !== undefined) {
+		$dom('fh_slider_img').title = "Firehose filtered to " + color;
+		if (fh_slider_init_set) {
+			firehose_set_options("color", color);
+		}
+	} else if (firehohse_settings.color !== undefined) {
+		firehose_slider_set_color(firehose_settings.color);
 	}
 }
 
@@ -1093,16 +1482,16 @@
 	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;
-	var relTarg = e.relatedTarget || e.toElement;
-	if (relTarg && relTarg.id == "vendorStory-26-popup") {
-		closePopup("vendorStory-26-popup");
-	}
+		if (!e) { e = window.event; }
+		var relTarg = e.relatedTarget || e.toElement;
+		if (relTarg && relTarg.id == "vendorStory-26-popup") {
+			closePopup("vendorStory-26-popup");
+		}
 	};
-	createPopup(getXYForId('sponsorlinks', 0, 0), title, "vendorStory-" + id, "Loading", "", closepopup );
+	createPopup(getXYForSelector('#sponsorlinks'), title, "vendorStory-" + id, "Loading", "", closepopup );
 	var params = {};
-	params['op'] = 'getTopVendorStory';
-	params['skid'] = id;
+	params.op = 'getTopVendorStory';
+	params.skid = id;
 	ajax_update(params, "vendorStory-" + id + "-contents");
 }
 
@@ -1118,16 +1507,16 @@
 	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;
+		if (!e) { e = window.event; }
 		var relTarg = e.relatedTarget || e.toElement;
 		if (relTarg && relTarg.id == "vendorStory-26-popup") {
 			closePopup("vendorStory-26-popup");
 		}
 	};
-	createPopup(getXYForId('sponsorlinks2', 0, 0), title, "vendorStory-" + id, "Loading", "", closepopup );
+	createPopup(getXYForSelector('#sponsorlinks'), title, "vendorStory-" + id, "Loading", "", closepopup );
 	var params = {};
-	params['op'] = 'getTopVendorStory';
-	params['skid'] = id;
+	params.op = 'getTopVendorStory';
+	params.skid = id;
 	ajax_update(params, "vendorStory-" + id + "-contents");
 }
 
@@ -1152,8 +1541,6 @@
 	$('#tab-form-'+id).setClass('hide');
 	$('#tab-text-'+id).removeClass();
 }
-
-
 var logged_in   = 1;
 var login_cover = 0;
 var login_box   = 0;
@@ -1165,14 +1552,17 @@
 }
 
 function install_login() {
-	if (login_inst)
+	if (login_inst) {
 		return;
+	}
 
-	if (!login_cover || !login_box)
+	if (!login_cover || !login_box) {
 		init_login_divs();
+	}
 
-	if (!login_cover || !login_box)
+	if (!login_cover || !login_box) {
 		return;
+	}
 
 	login_cover.parentNode.removeChild(login_cover);
 	login_box.parentNode.removeChild(login_box);
@@ -1184,8 +1574,9 @@
 }
 
 function show_login_box() {
-	if (!login_inst)
+	if (!login_inst) {
 		install_login();
+	}
 
 	if (login_cover && login_box) {
 		login_cover.style.display = '';
@@ -1196,8 +1587,9 @@
 }
 
 function hide_login_box() {
-	if (!login_inst)
+	if (!login_inst) {
 		install_login();
+	}
 
 	if (login_cover && login_box) {
 		login_box.style.display = 'none';
@@ -1214,7 +1606,6 @@
 	}
 	return 1;
 }
-
 var modal_cover = 0;
 var modal_box   = 0;
 var modal_inst  = 0;
@@ -1225,14 +1616,17 @@
 }
 
 function install_modal() {
-	if (modal_inst)
+	if (modal_inst) {
 		return;
+	}
 
-	if (!modal_cover || !modal_box)
+	if (!modal_cover || !modal_box) {
 		init_modal_divs();
+	}
 
-	if (!modal_cover || !modal_box)
+	if (!modal_cover || !modal_box) {
 		return;
+	}
 
 	modal_cover.parentNode.removeChild(modal_cover);
 	modal_box.parentNode.removeChild(modal_box);
@@ -1244,8 +1638,9 @@
 }
 
 function show_modal_box() {
-	if (!modal_inst)
+	if (!modal_inst) {
 		install_modal();
+	}
 
 	if (modal_cover && modal_box) {
 		modal_cover.style.display = '';
@@ -1256,8 +1651,9 @@
 }
 
 function hide_modal_box() {
-	if (!modal_inst)
+	if (!modal_inst) {
 		install_modal();
+	}
 
 	if (modal_cover && modal_box) {
 		modal_box.style.display = 'none';
@@ -1268,8 +1664,9 @@
 }
 
 function getModalPrefs(section, title, tabbed) {
-	if (!reskey_static)
+	if (!reskey_static) {
 		return show_login_box();
+	}
 	$('#preference_title').html(title);
 	ajax_update({
 		op:		'getModalPrefs',
@@ -1291,14 +1688,15 @@
 
 function saveModalPrefs() {
 	var params = {};
-	params['op'] = 'saveModalPrefs';
-	params['data'] = jQuery("#modal_prefs").serialize();
-	params['reskey'] = reskey_static;
+	params.op = 'saveModalPrefs';
+	params.data = jQuery("#modal_prefs").serialize();
+	params.reskey = reskey_static;
 	var handlers = {
 		onComplete: function() {
 			hide_modal_box();
-			if (document.forms['modal_prefs'].refreshable.value)
+			if (document.forms.modal_prefs.refreshable.value) {
 				document.location=document.URL;
+			}
 		}
 	};
 	ajax_update(params, '', handlers);
@@ -1329,12 +1727,12 @@
 	var fps = $dom('filter_play_status');
 	var fp  = $dom('filter_prefs');
 	if (fps) {
-		if (fps.className == "") {
+		if (fps.className === "") {
 			fps.className = "hide";
 			if (fp) {
 				fp.className = "";
 				setTimeout(firehose_slider_init,500);
-			} 
+			}
 		} else if (fps.className == "hide") {
 			fps.className = "";
 			if (fp) {
@@ -1347,21 +1745,24 @@
 
 function admin_signoff(stoid, type, id) {
 	var params = {};
-	params['op'] = 'admin_signoff';
-	params['stoid'] = stoid;
-	params['reskey'] = reskey_static;
+	params.op = 'admin_signoff';
+	params.stoid = stoid;
+	params.reskey = reskey_static;
 	ajax_update(params, 'signoff_' + stoid);
 	if (type == "firehose") {
 		firehose_collapse_entry(id);
 	}
 }
 
-
 function scrollWindowToFirehose(fhid) {
-	var firehose_y = getOffsetTop($('firehose-' + fhid));
-	scroll(viewWindowLeft(), firehose_y);
+	scrollWindowToId('firehose-'+fhid);
 }
 
+function scrollWindowToId(id) {
+	var id_y = getOffsetTop($dom(id));
+	scroll(viewWindowLeft(), id_y);
+}
+
 function viewWindowLeft() {
 	if (self.pageXOffset) // all except Explorer
 	{
@@ -1379,11 +1780,13 @@
 }
 
 function getOffsetTop (el) {
-	if (!el)
+	if (!el) {
 		return false;
+	}
 	var ot = el.offsetTop;
-	while((el = el.offsetParent) != null)
+	while((el = el.offsetParent)) {
 		ot += el.offsetTop;
+	}
 	return ot;
 }
 
@@ -1467,13 +1870,16 @@
 }
 
 function firehose_more() {
-	var increment_by = 10;
-	firehose_settings.more_num = firehose_settings.more_num + increment_by;
-	
-	if (((firehose_item_count + increment_by) >= 200) && !fh_is_admin) {
+	firehose_settings.more_num = firehose_settings.more_num + firehose_more_increment;
+
+	if (((firehose_item_count + firehose_more_increment) >= 200) && !fh_is_admin) {
 		$('#firehose_more').hide();
 	}
 	firehose_set_options('more_num', firehose_settings.more_num);
 }
 
-
+function firehose_get_onscreen() {
+	var onscreen = [];
+	$('#firehoselist').children().each(function() { if(isInWindow(this)){ onscreen.push(this.id);} });
+	return onscreen;
+}

Copied: slashjp/trunk/plugins/Ajax/htdocs/images/jquery (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/htdocs/images/jquery)

Deleted: slashjp/trunk/plugins/Ajax/htdocs/images/jquery-1.2.3.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/jquery-1.2.3.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/jquery-1.2.3.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,11 +0,0 @@
-/*
- * jQuery 1.2.3 - New Wave Javascript
- *
- * Copyright (c) 2008 John Resig (jquery.com)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * $Date: 2008/03/14 15:48:06 $
- * $Rev: 4663 $
- */
-eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(J(){7(1e.3N)L w=1e.3N;L E=1e.3N=J(a,b){K 1B E.2l.4T(a,b)};7(1e.$)L D=1e.$;1e.$=E;L u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;L G=/^.[^:#\\[\\.]*$/;E.1n=E.2l={4T:J(d,b){d=d||T;7(d.15){6[0]=d;6.M=1;K 6}N 7(1o d=="25"){L c=u.2O(d);7(c&&(c[1]||!b)){7(c[1])d=E.4a([c[1]],b);N{L a=T.5J(c[3]);7(a)7(a.2w!=c[3])K E().2s(d);N{6[0]=a;6.M=1;K 6}N d=[]}}N K 1B E(b).2s(d)}N 7(E.1q(d))K 1B E(T)[E.1n.21?"21":"3U"](d);K 6.6E(d.1k==1M&&d||(d.5h||d.M&&d!=1e&&!d.15&&d[0]!=10&&d[0].15)&&E.2I(d)||[d])},5h:"1.2.3",87:J(){K 6.M},M:0,22:J(a){K a==10?E.2I(6):6[a]},2F:J(b){L a=E(b);a.54=6;K a},6E:J(a){6.M=0;1M.2l.1g.1i(6,a);K 6},R:J(a,b){K E.R(6,a,b)},4X:J(b){L a=-1;6.R(J(i){7(6==b)a=i});K a},1J:J(c,a,b){L d=c;7(c.1k==4e)7(a==10)K 6.M&&E[b||"1J"](6[0],c)||10;N{d={};d[c]=a}K 6.R(J(i){Q(c 1p d)E.1J(b?6.W:6,c,E.1l(6,d[c],b,i,c))})},1j:J(b,a){7((b==\'27\'||b==\'1R\')&&2M(a)<0)a=10;K 6.1J(b,a,"2o")},1u:J(b){7(1o b!="3V"&&b!=V)K 6.4x().3t((6[0]&&6[0].2i||T).5r(b));L a="";E.R(b||6,J(){E.R(6.3p,J(){7(6.15!=8)a+=6.15!=1?6.6K:E.1n.1u([6])})});K a},5m:J(b){7(6[0])E(b,6[0].2i).5k().3o(6[0]).2c(J(){L a=6;2b(a.1C)a=a.1C;K a}).3t(6);K 6},8w:J(a){K 6.R(J(){E(6).6z().5m(a)})},8p:J(a){K 6.R(J(){E(6).5m(a)})},3t:J(){K 6.3O(18,P,S,J(a){7(6.15==1)6.38(a)})},6q:J(){K 6.3O(18,P,P,J(a){7(6.15==1)6.3o(a,6.1C)})},6o:J(){K 6.3O(18,S,S,J(a){6.1a.3o(a,6)})},5a:J(){K 6.3O(18,S,P,J(a){6.1a.3o(a,6.2B)})},3h:J(){K 6.54||E([])},2s:J(b){L c=E.2c(6,J(a){K E.2s(b,a)});K 6.2F(/[^+>] [^+>]/.17(b)||b.1f("..")>-1?E.57(c):c)},5k:J(e){L f=6.2c(J(){7(E.14.1d&&!E.3E(6)){L a=6.69(P),4Y=T.3s("1x");4Y.38(a);K E.4a([4Y.3d])[0]}N K 6.69(P)});L d=f.2s("*").4R().R(J(){7(6[F]!=10)6[F]=V});7(e===P)6.2s("*").4R().R(J(i){7(6.15==3)K;L c=E.O(6,"2R");Q(L a 1p c)Q(L b 1p c[a])E.16.1b(d[i],a,c[a][b],c[a][b].O)});K f},1E:J(b){K 6.2F(E.1q(b)&&E.3y(6,J(a,i){K b.1P(a,i)})||E.3e(b,6))},56:J(b){7(b.1k==4e)7(G.17(b))K 6.2F(E.3e(b,6,P));N b=E.3e(b,6);L a=b.M&&b[b.M-1]!==10&&!b.15;K 6.1E(J(){K a?E.33(6,b)<0:6!=b})},1b:J(a){K!a?6:6.2F(E.37(6.22(),a.1k==4e?E(a).22():a.M!=10&&(!a.12||E.12(a,"3u"))?a:[a]))},3H:J(a){K a?E.3e(a,6).M>0:S},7j:J(a){K 6.3H("."+a)},5O:J(b){7(b==10){7(6.M){L c=6[0];7(E.12(c,"2k")){L e=c.3T,5I=[],11=c.11,2X=c.U=="2k-2X";7(e<0)K V;Q(L i=2X?e:0,2f=2X?e+1:11.M;i<2f;i++){L d=11[i];7(d.2p){b=E.14.1d&&!d.9J.1A.9y?d.1u:d.1A;7(2X)K b;5I.1g(b)}}K 5I}N K(6[0].1A||"").1r(/\\r/g,"")}K 10}K 6.R(J(){7(6.15!=1)K;7(b.1k==1M&&/5u|5t/.17(6.U))6.3k=(E.33(6.1A,b)>=0||E.33(6.31,b)>=0);N 7(E.12(6,"2k")){L a=b.1k==1M?b:[b];E("98",6).R(J(){6.2p=(E.33(6.1A,a)>=0||E.33(6.1u,a)>=0)});7(!a.M)6.3T=-1}N 6.1A=b})},3q:J(a){K a==10?(6.M?6[0].3d:V):6.4x().3t(a)},6S:J(a){K 6.5a(a).1V()},6Z:J(i){K 6.2K(i,i+1)},2K:J(){K 6.2F(1M.2l.2K.1i(6,18))},2c:J(b){K 6.2F(E.2c(6,J(a,i){K b.1P(a,i,a)}))},4R:J(){K 6.1b(6.54)},O:J(d,b){L a=d.23(".");a[1]=a[1]?"."+a[1]:"";7(b==V){L c=6.5n("8P"+a[1]+"!",[a[0]]);7(c==10&&6.M)c=E.O(6[0],d);K c==V&&a[1]?6.O(a[0]):c}N K 6.1N("8K"+a[1]+"!",[a[0],b]).R(J(){E.O(6,d,b)})},35:J(a){K 6.R(J(){E.35(6,a)})},3O:J(g,f,h,d){L e=6.M>1,3n;K 6.R(J(){7(!3n){3n=E.4a(g,6.2i);7(h)3n.8D()}L b=6;7(f&&E.12(6,"1O")&&E.12(3n[0],"4v"))b=6.3S("1U")[0]||6.38(6.2i.3s("1U"));L c=E([]);E.R(3n,J(){L a=e?E(6).5k(P)[0]:6;7(E.12(a,"1m")){c=c.1b(a)}N{7(a.15==1)c=c.1b(E("1m",a).1V());d.1P(b,a)}});c.R(6A)})}};E.2l.4T.2l=E.2l;J 6A(i,a){7(a.3Q)E.3P({1c:a.3Q,3l:S,1H:"1m"});N E.5g(a.1u||a.6x||a.3d||"");7(a.1a)a.1a.34(a)}E.1s=E.1n.1s=J(){L b=18[0]||{},i=1,M=18.M,5c=S,11;7(b.1k==8d){5c=b;b=18[1]||{};i=2}7(1o b!="3V"&&1o b!="J")b={};7(M==1){b=6;i=0}Q(;i<M;i++)7((11=18[i])!=V)Q(L a 1p 11){7(b===11[a])6w;7(5c&&11[a]&&1o 11[a]=="3V"&&b[a]&&!11[a].15)b[a]=E.1s(b[a],11[a]);N 7(11[a]!=10)b[a]=11[a]}K b};L F="3N"+(1B 3v()).3L(),6t=0,5b={};L H=/z-?4X|86-?84|1w|6k|7Z-?1R/i;E.1s({7Y:J(a){1e.$=D;7(a)1e.3N=w;K E},1q:J(a){K!!a&&1o a!="25"&&!a.12&&a.1k!=1M&&/J/i.17(a+"")},3E:J(a){K a.1F&&!a.1h||a.28&&a.2i&&!a.2i.1h},5g:J(a){a=E.3g(a);7(a){L b=T.3S("6f")[0]||T.1F,1m=T.3s("1m");1m.U="1u/4m";7(E.14.1d)1m.1u=a;N 1m.38(T.5r(a));b.38(1m);b.34(1m)}},12:J(b,a){K b.12&&b.12.2E()==a.2E()},1T:{},O:J(c,d,b){c=c==1e?5b:c;L a=c[F];7(!a)a=c[F]=++6t;7(d&&!E.1T[a])E.1T[a]={};7(b!=10)E.1T[a][d]=b;K d?E.1T[a][d]:a},35:J(c,b){c=c==1e?5b:c;L a=c[F];7(b){7(E.1T[a]){2V E.1T[a][b];b="";Q(b 1p E.1T[a])1Q;7(!b)E.35(c)}}N{1S{2V c[F]}1X(e){7(c.52)c.52(F)}2V E.1T[a]}},R:J(c,a,b){7(b){7(c.M==10){Q(L d 1p c)7(a.1i(c[d],b)===S)1Q}N Q(L i=0,M=c.M;i<M;i++)7(a.1i(c[i],b)===S)1Q}N{7(c.M==10){Q(L d 1p c)7(a.1P(c[d],d,c[d])===S)1Q}N Q(L i=0,M=c.M,1A=c[0];i<M&&a.1P(1A,i,1A)!==S;1A=c[++i]){}}K c},1l:J(b,a,c,i,d){7(E.1q(a))a=a.1P(b,i);K a&&a.1k==51&&c=="2o"&&!H.17(d)?a+"2S":a},1t:{1b:J(c,b){E.R((b||"").23(/\\s+/),J(i,a){7(c.15==1&&!E.1t.3Y(c.1t,a))c.1t+=(c.1t?" ":"")+a})},1V:J(c,b){7(c.15==1)c.1t=b!=10?E.3y(c.1t.23(/\\s+/),J(a){K!E.1t.3Y(b,a)}).6a(" "):""},3Y:J(b,a){K E.33(a,(b.1t||b).3X().23(/\\s+/))>-1}},68:J(b,c,a){L e={};Q(L d 1p c){e[d]=b.W[d];b.W[d]=c[d]}a.1P(b);Q(L d 1p c)b.W[d]=e[d]},1j:J(d,e,c){7(e=="27"||e=="1R"){L b,46={43:"4W",4U:"1Z",19:"3D"},3c=e=="27"?["7O","7M"]:["7J","7I"];J 5E(){b=e=="27"?d.7H:d.7F;L a=0,2N=0;E.R(3c,J(){a+=2M(E.2o(d,"7E"+6,P))||0;2N+=2M(E.2o(d,"2N"+6+"5X",P))||0});b-=24.7C(a+2N)}7(E(d).3H(":4d"))5E();N E.68(d,46,5E);K 24.2f(0,b)}K E.2o(d,e,c)},2o:J(e,k,j){L d;J 3x(b){7(!E.14.2d)K S;L a=T.4c.4K(b,V);K!a||a.4M("3x")==""}7(k=="1w"&&E.14.1d){d=E.1J(e.W,"1w");K d==""?"1":d}7(E.14.2z&&k=="19"){L c=e.W.50;e.W.50="0 7r 7o";e.W.50=c}7(k.1D(/4g/i))k=y;7(!j&&e.W&&e.W[k])d=e.W[k];N 7(T.4c&&T.4c.4K){7(k.1D(/4g/i))k="4g";k=k.1r(/([A-Z])/g,"-$1").2h();L h=T.4c.4K(e,V);7(h&&!3x(e))d=h.4M(k);N{L f=[],2C=[];Q(L a=e;a&&3x(a);a=a.1a)2C.4J(a);Q(L i=0;i<2C.M;i++)7(3x(2C[i])){f[i]=2C[i].W.19;2C[i].W.19="3D"}d=k=="19"&&f[2C.M-1]!=V?"2H":(h&&h.4M(k))||"";Q(L i=0;i<f.M;i++)7(f[i]!=V)2C[i].W.19=f[i]}7(k=="1w"&&d=="")d="1"}N 7(e.4n){L g=k.1r(/\\-(\\w)/g,J(a,b){K b.2E()});d=e.4n[k]||e.4n[g];7(!/^\\d+(2S)?$/i.17(d)&&/^\\d/.17(d)){L l=e.W.26,3K=e.3K.26;e.3K.26=e.4n.26;e.W.26=d||0;d=e.W.7f+"2S";e.W.26=l;e.3K.26=3K}}K d},4a:J(l,h){L k=[];h=h||T;7(1o h.3s==\'10\')h=h.2i||h[0]&&h[0].2i||T;E.R(l,J(i,d){7(!d)K;7(d.1k==51)d=d.3X();7(1o d=="25"){d=d.1r(/(<(\\w+)[^>]*?)\\/>/g,J(b,a,c){K c.1D(/^(aa|a6|7e|a5|4D|7a|a0|3m|9W|9U|9S)$/i)?b:a+"></"+c+">"});L f=E.3g(d).2h(),1x=h.3s("1x");L e=!f.1f("<9P")&&[1,"<2k 74=\'74\'>","</2k>"]||!f.1f("<9M")&&[1,"<73>","</73>"]||f.1D(/^<(9G|1U|9E|9B|9x)/)&&[1,"<1O>","</1O>"]||!f.1f("<4v")&&[2,"<1O><1U>","</1U></1O>"]||(!f.1f("<9w")||!f.1f("<9v"))&&[3,"<1O><1U><4v>","</4v></1U></1O>"]||!f.1f("<7e")&&[2,"<1O><1U></1U><6V>","</6V></1O>"]||E.14.1d&&[1,"1x<1x>","</1x>"]||[0,"",""];1x.3d=e[1]+d+e[2];2b(e[0]--)1x=1x.5o;7(E.14.1d){L g=!f.1f("<1O")&&f.1f("<1U")<0?1x.1C&&1x.1C.3p:e[1]=="<1O>"&&f.1f("<1U")<0?1x.3p:[];Q(L j=g.M-1;j>=0;--j)7(E.12(g[j],"1U")&&!g[j].3p.M)g[j].1a.34(g[j]);7(/^\\s/.17(d))1x.3o(h.5r(d.1D(/^\\s*/)[0]),1x.1C)}d=E.2I(1x.3p)}7(d.M===0&&(!E.12(d,"3u")&&!E.12(d,"2k")))K;7(d[0]==10||E.12(d,"3u")||d.11)k.1g(d);N k=E.37(k,d)});K k},1J:J(d,e,c){7(!d||d.15==3||d.15==8)K 10;L f=E.3E(d)?{}:E.46;7(e=="2p"&&E.14.2d)d.1a.3T;7(f[e]){7(c!=10)d[f[e]]=c;K d[f[e]]}N 7(E.14.1d&&e=="W")K E.1J(d.W,"9u",c);N 7(c==10&&E.14.1d&&E.12(d,"3u")&&(e=="9r"||e=="9o"))K d.9m(e).6K;N 7(d.28){7(c!=10){7(e=="U"&&E.12(d,"4D")&&d.1a)6Q"U 9i 9h\'t 9g 9e";d.9b(e,""+c)}7(E.14.1d&&/6O|3Q/.17(e)&&!E.3E(d))K d.4z(e,2);K d.4z(e)}N{7(e=="1w"&&E.14.1d){7(c!=10){d.6k=1;d.1E=(d.1E||"").1r(/6M\\([^)]*\\)/,"")+(2M(c).3X()=="96"?"":"6M(1w="+c*6L+")")}K d.1E&&d.1E.1f("1w=")>=0?(2M(d.1E.1D(/1w=([^)]*)/)[1])/6L).3X():""}e=e.1r(/-([a-z])/95,J(a,b){K b.2E()});7(c!=10)d[e]=c;K d[e]}},3g:J(a){K(a||"").1r(/^\\s+|\\s+$/g,"")},2I:J(b){L a=[];7(1o b!="93")Q(L i=0,M=b.M;i<M;i++)a.1g(b[i]);N a=b.2K(0);K a},33:J(b,a){Q(L i=0,M=a.M;i<M;i++)7(a[i]==b)K i;K-1},37:J(a,b){7(E.14.1d){Q(L i=0;b[i];i++)7(b[i].15!=8)a.1g(b[i])}N Q(L i=0;b[i];i++)a.1g(b[i]);K a},57:J(a){L c=[],2r={};1S{Q(L i=0,M=a.M;i<M;i++){L b=E.O(a[i]);7(!2r[b]){2r[b]=P;c.1g(a[i])}}}1X(e){c=a}K c},3y:J(c,a,d){L b=[];Q(L i=0,M=c.M;i<M;i++)7(!d&&a(c[i],i)||d&&!a(c[i],i))b.1g(c[i]);K b},2c:J(d,a){L c=[];Q(L i=0,M=d.M;i<M;i++){L b=a(d[i],i);7(b!==V&&b!=10){7(b.1k!=1M)b=[b];c=c.71(b)}}K c}});L v=8Y.8W.2h();E.14={5K:(v.1D(/.+(?:8T|8S|8R|8O)[\\/: ]([\\d.]+)/)||[])[1],2d:/77/.17(v),2z:/2z/.17(v),1d:/1d/.17(v)&&!/2z/.17(v),48:/48/.17(v)&&!/(8L|77)/.17(v)};L y=E.14.1d?"6H":"75";E.1s({8I:!E.14.1d||T.6F=="79",46:{"Q":"8F","8E":"1t","4g":y,75:y,6H:y,3d:"3d",1t:"1t",1A:"1A",2Y:"2Y",3k:"3k",8C:"8B",2p:"2p",8A:"8z",3T:"3T",6C:"6C",28:"28",12:"12"}});E.R({6B:J(a){K a.1a},8y:J(a){K E.4u(a,"1a")},8x:J(a){K E.2Z(a,2,"2B")},8v:J(a){K E.2Z(a,2,"4t")},8u:J(a){K E.4u(a,"2B")},8t:J(a){K E.4u(a,"4t")},8s:J(a){K E.5i(a.1a.1C,a)},8r:J(a){K E.5i(a.1C)},6z:J(a){K E.12(a,"8q")?a.8o||a.8n.T:E.2I(a.3p)}},J(c,d){E.1n[c]=J(b){L a=E.2c(6,d);7(b&&1o b=="25")a=E.3e(b,a);K 6.2F(E.57(a))}});E.R({6y:"3t",8m:"6q",3o:"6o",8l:"5a",8k:"6S"},J(c,b){E.1n[c]=J(){L a=18;K 6.R(J(){Q(L i=0,M=a.M;i<M;i++)E(a[i])[b](6)})}});E.R({8j:J(a){E.1J(6,a,"");7(6.15==1)6.52(a)},8i:J(a){E.1t.1b(6,a)},8h:J(a){E.1t.1V(6,a)},8g:J(a){E.1t[E.1t.3Y(6,a)?"1V":"1b"](6,a)},1V:J(a){7(!a||E.1E(a,[6]).r.M){E("*",6).1b(6).R(J(){E.16.1V(6);E.35(6)});7(6.1a)6.1a.34(6)}},4x:J(){E(">*",6).1V();2b(6.1C)6.34(6.1C)}},J(a,b){E.1n[a]=J(){K 6.R(b,18)}});E.R(["8f","5X"],J(i,c){L b=c.2h();E.1n[b]=J(a){K 6[0]==1e?E.14.2z&&T.1h["5e"+c]||E.14.2d&&1e["8e"+c]||T.6F=="79"&&T.1F["5e"+c]||T.1h["5e"+c]:6[0]==T?24.2f(24.2f(T.1h["5d"+c],T.1F["5d"+c]),24.2f(T.1h["5L"+c],T.1F["5L"+c])):a==10?(6.M?E.1j(6[0],b):V):6.1j(b,a.1k==4e?a:a+"2S")}});L C=E.14.2d&&4s(E.14.5K)<8c?"(?:[\\\\w*4r-]|\\\\\\\\.)":"(?:[\\\\w\\8b-\\8a*4r-]|\\\\\\\\.)",6v=1B 4q("^>\\\\s*("+C+"+)"),6u=1B 4q("^("+C+"+)(#)("+C+"+)"),6s=1B 4q("^([#.]?)("+C+"*)");E.1s({6r:{"":J(a,i,m){K m[2]=="*"||E.12(a,m[2])},"#":J(a,i,m){K a.4z("2w")==m[2]},":":{89:J(a,i,m){K i<m[3]-0},88:J(a,i,m){K i>m[3]-0},2Z:J(a,i,m){K m[3]-0==i},6Z:J(a,i,m){K m[3]-0==i},3j:J(a,i){K i==0},3J:J(a,i,m,r){K i==r.M-1},6n:J(a,i){K i%2==0},6l:J(a,i){K i%2},"3j-4p":J(a){K a.1a.3S("*")[0]==a},"3J-4p":J(a){K E.2Z(a.1a.5o,1,"4t")==a},"83-4p":J(a){K!E.2Z(a.1a.5o,2,"4t")},6B:J(a){K a.1C},4x:J(a){K!a.1C},82:J(a,i,m){K(a.6x||a.81||E(a).1u()||"").1f(m[3])>=0},4d:J(a){K"1Z"!=a.U&&E.1j(a,"19")!="2H"&&E.1j(a,"4U")!="1Z"},1Z:J(a){K"1Z"==a.U||E.1j(a,"19")=="2H"||E.1j(a,"4U")=="1Z"},80:J(a){K!a.2Y},2Y:J(a){K a.2Y},3k:J(a){K a.3k},2p:J(a){K a.2p||E.1J(a,"2p")},1u:J(a){K"1u"==a.U},5u:J(a){K"5u"==a.U},5t:J(a){K"5t"==a.U},59:J(a){K"59"==a.U},3I:J(a){K"3I"==a.U},58:J(a){K"58"==a.U},6j:J(a){K"6j"==a.U},6i:J(a){K"6i"==a.U},2G:J(a){K"2G"==a.U||E.12(a,"2G")},4D:J(a){K/4D|2k|6h|2G/i.17(a.12)},3Y:J(a,i,m){K E.2s(m[3],a).M},7X:J(a){K/h\\d/i.17(a.12)},7W:J(a){K E.3y(E.3G,J(b){K a==b.Y}).M}}},6g:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1B 4q("^([:.#]*)("+C+"+)")],3e:J(a,c,b){L d,2m=[];2b(a&&a!=d){d=a;L f=E.1E(a,c,b);a=f.t.1r(/^\\s*,\\s*/,"");2m=b?c=f.r:E.37(2m,f.r)}K 2m},2s:J(t,p){7(1o t!="25")K[t];7(p&&p.15!=1&&p.15!=9)K[];p=p||T;L d=[p],2r=[],3J,12;2b(t&&3J!=t){L r=[];3J=t;t=E.3g(t);L o=S;L g=6v;L m=g.2O(t);7(m){12=m[1].2E();Q(L i=0;d[i];i++)Q(L c=d[i].1C;c;c=c.2B)7(c.15==1&&(12=="*"||c.12.2E()==12))r.1g(c);d=r;t=t.1r(g,"");7(t.1f(" ")==0)6w;o=P}N{g=/^([>+~])\\s*(\\w*)/i;7((m=g.2O(t))!=V){r=[];L l={};12=m[2].2E();m=m[1];Q(L j=0,3f=d.M;j<3f;j++){L n=m=="~"||m=="+"?d[j].2B:d[j].1C;Q(;n;n=n.2B)7(n.15==1){L h=E.O(n);7(m=="~"&&l[h])1Q;7(!12||n.12.2E()==12){7(m=="~")l[h]=P;r.1g(n)}7(m=="+")1Q}}d=r;t=E.3g(t.1r(g,""));o=P}}7(t&&!o){7(!t.1f(",")){7(p==d[0])d.4l();2r=E.37(2r,d);r=d=[p];t=" "+t.6e(1,t.M)}N{L k=6u;L m=k.2O(t);7(m){m=[0,m[2],m[3],m[1]]}N{k=6s;m=k.2O(t)}m[2]=m[2].1r(/\\\\/g,"");L f=d[d.M-1];7(m[1]=="#"&&f&&f.5J&&!E.3E(f)){L q=f.5J(m[2]);7((E.14.1d||E.14.2z)&&q&&1o q.2w=="25"&&q.2w!=m[2])q=E(\'[@2w="\'+m[2]+\'"]\',f)[0];d=r=q&&(!m[3]||E.12(q,m[3]))?[q]:[]}N{Q(L i=0;d[i];i++){L a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];7(a=="*"&&d[i].12.2h()=="3V")a="3m";r=E.37(r,d[i].3S(a))}7(m[1]==".")r=E.55(r,m[2]);7(m[1]=="#"){L e=[];Q(L i=0;r[i];i++)7(r[i].4z("2w")==m[2]){e=[r[i]];1Q}r=e}d=r}t=t.1r(k,"")}}7(t){L b=E.1E(t,r);d=r=b.r;t=E.3g(b.t)}}7(t)d=[];7(d&&p==d[0])d.4l();2r=E.37(2r,d);K 2r},55:J(r,m,a){m=" "+m+" ";L c=[];Q(L i=0;r[i];i++){L b=(" "+r[i].1t+" ").1f(m)>=0;7(!a&&b||a&&!b)c.1g(r[i])}K c},1E:J(t,r,h){L d;2b(t&&t!=d){d=t;L p=E.6g,m;Q(L i=0;p[i];i++){m=p[i].2O(t);7(m){t=t.7V(m[0].M);m[2]=m[2].1r(/\\\\/g,"");1Q}}7(!m)1Q;7(m[1]==":"&&m[2]=="56")r=G.17(m[3])?E.1E(m[3],r,P).r:E(r).56(m[3]);N 7(m[1]==".")r=E.55(r,m[2],h);N 7(m[1]=="["){L g=[],U=m[3];Q(L i=0,3f=r.M;i<3f;i++){L a=r[i],z=a[E.46[m[2]]||m[2]];7(z==V||/6O|3Q|2p/.17(m[2]))z=E.1J(a,m[2])||\'\';7((U==""&&!!z||U=="="&&z==m[5]||U=="!="&&z!=m[5]||U=="^="&&z&&!z.1f(m[5])||U=="$="&&z.6e(z.M-m[5].M)==m[5]||(U=="*="||U=="~=")&&z.1f(m[5])>=0)^h)g.1g(a)}r=g}N 7(m[1]==":"&&m[2]=="2Z-4p"){L e={},g=[],17=/(-?)(\\d*)n((?:\\+|-)?\\d*)/.2O(m[3]=="6n"&&"2n"||m[3]=="6l"&&"2n+1"||!/\\D/.17(m[3])&&"7U+"+m[3]||m[3]),3j=(17[1]+(17[2]||1))-0,d=17[3]-0;Q(L i=0,3f=r.M;i<3f;i++){L j=r[i],1a=j.1a,2w=E.O(1a);7(!e[2w]){L c=1;Q(L n=1a.1C;n;n=n.2B)7(n.15==1)n.4k=c++;e[2w]=P}L b=S;7(3j==0){7(j.4k==d)b=P}N 7((j.4k-d)%3j==0&&(j.4k-d)/3j>=0)b=P;7(b^h)g.1g(j)}r=g}N{L f=E.6r[m[1]];7(1o f=="3V")f=f[m[2]];7(1o f=="25")f=6c("S||J(a,i){K "+f+";}");r=E.3y(r,J(a,i){K f(a,i,m,r)},h)}}K{r:r,t:t}},4u:J(b,c){L d=[];L a=b[c];2b(a&&a!=T){7(a.15==1)d.1g(a);a=a[c]}K d},2Z:J(a,e,c,b){e=e||1;L d=0;Q(;a;a=a[c])7(a.15==1&&++d==e)1Q;K a},5i:J(n,a){L r=[];Q(;n;n=n.2B){7(n.15==1&&(!a||n!=a))r.1g(n)}K r}});E.16={1b:J(f,i,g,e){7(f.15==3||f.15==8)K;7(E.14.1d&&f.53!=10)f=1e;7(!g.2D)g.2D=6.2D++;7(e!=10){L h=g;g=J(){K h.1i(6,18)};g.O=e;g.2D=h.2D}L j=E.O(f,"2R")||E.O(f,"2R",{}),1v=E.O(f,"1v")||E.O(f,"1v",J(){L a;7(1o E=="10"||E.16.5f)K a;a=E.16.1v.1i(18.3R.Y,18);K a});1v.Y=f;E.R(i.23(/\\s+/),J(c,b){L a=b.23(".");b=a[0];g.U=a[1];L d=j[b];7(!d){d=j[b]={};7(!E.16.2y[b]||E.16.2y[b].4j.1P(f)===S){7(f.3F)f.3F(b,1v,S);N 7(f.6b)f.6b("4i"+b,1v)}}d[g.2D]=g;E.16.2a[b]=P});f=V},2D:1,2a:{},1V:J(e,h,f){7(e.15==3||e.15==8)K;L i=E.O(e,"2R"),29,4X;7(i){7(h==10||(1o h=="25"&&h.7T(0)=="."))Q(L g 1p i)6.1V(e,g+(h||""));N{7(h.U){f=h.2q;h=h.U}E.R(h.23(/\\s+/),J(b,a){L c=a.23(".");a=c[0];7(i[a]){7(f)2V i[a][f.2D];N Q(f 1p i[a])7(!c[1]||i[a][f].U==c[1])2V i[a][f];Q(29 1p i[a])1Q;7(!29){7(!E.16.2y[a]||E.16.2y[a].4h.1P(e)===S){7(e.67)e.67(a,E.O(e,"1v"),S);N 7(e.66)e.66("4i"+a,E.O(e,"1v"))}29=V;2V i[a]}}})}Q(29 1p i)1Q;7(!29){L d=E.O(e,"1v");7(d)d.Y=V;E.35(e,"2R");E.35(e,"1v")}}},1N:J(g,c,d,f,h){c=E.2I(c||[]);7(g.1f("!")>=0){g=g.2K(0,-1);L a=P}7(!d){7(6.2a[g])E("*").1b([1e,T]).1N(g,c)}N{7(d.15==3||d.15==8)K 10;L b,29,1n=E.1q(d[g]||V),16=!c[0]||!c[0].36;7(16)c.4J(6.4Z({U:g,2L:d}));c[0].U=g;7(a)c[0].65=P;7(E.1q(E.O(d,"1v")))b=E.O(d,"1v").1i(d,c);7(!1n&&d["4i"+g]&&d["4i"+g].1i(d,c)===S)b=S;7(16)c.4l();7(h&&E.1q(h)){29=h.1i(d,b==V?c:c.71(b));7(29!==10)b=29}7(1n&&f!==S&&b!==S&&!(E.12(d,\'a\')&&g=="4V")){6.5f=P;1S{d[g]()}1X(e){}}6.5f=S}K b},1v:J(c){L a;c=E.16.4Z(c||1e.16||{});L b=c.U.23(".");c.U=b[0];L f=E.O(6,"2R")&&E.O(6,"2R")[c.U],42=1M.2l.2K.1P(18,1);42.4J(c);Q(L j 1p f){L d=f[j];42[0].2q=d;42[0].O=d.O;7(!b[1]&&!c.65||d.U==b[1]){L e=d.1i(6,42);7(a!==S)a=e;7(e===S){c.36();c.44()}}}7(E.14.1d)c.2L=c.36=c.44=c.2q=c.O=V;K a},4Z:J(c){L a=c;c=E.1s({},a);c.36=J(){7(a.36)a.36();a.7S=S};c.44=J(){7(a.44)a.44();a.7R=P};7(!c.2L)c.2L=c.7Q||T;7(c.2L.15==3)c.2L=a.2L.1a;7(!c.4S&&c.5w)c.4S=c.5w==c.2L?c.7P:c.5w;7(c.64==V&&c.63!=V){L b=T.1F,1h=T.1h;c.64=c.63+(b&&b.2v||1h&&1h.2v||0)-(b.62||0);c.7N=c.7L+(b&&b.2x||1h&&1h.2x||0)-(b.60||0)}7(!c.3c&&((c.4f||c.4f===0)?c.4f:c.5Z))c.3c=c.4f||c.5Z;7(!c.7b&&c.5Y)c.7b=c.5Y;7(!c.3c&&c.2G)c.3c=(c.2G&1?1:(c.2G&2?3:(c.2G&4?2:0)));K c},2y:{21:{4j:J(){5M();K},4h:J(){K}},3C:{4j:J(){7(E.14.1d)K S;E(6).2j("4P",E.16.2y.3C.2q);K P},4h:J(){7(E.14.1d)K S;E(6).3w("4P",E.16.2y.3C.2q);K P},2q:J(a){7(I(a,6))K P;18[0].U="3C";K E.16.1v.1i(6,18)}},3B:{4j:J(){7(E.14.1d)K S;E(6).2j("4O",E.16.2y.3B.2q);K P},4h:J(){7(E.14.1d)K S;E(6).3w("4O",E.16.2y.3B.2q);K P},2q:J(a){7(I(a,6))K P;18[0].U="3B";K E.16.1v.1i(6,18)}}}};E.1n.1s({2j:J(c,a,b){K c=="4H"?6.2X(c,a,b):6.R(J(){E.16.1b(6,c,b||a,b&&a)})},2X:J(d,b,c){K 6.R(J(){E.16.1b(6,d,J(a){E(6).3w(a);K(c||b).1i(6,18)},c&&b)})},3w:J(a,b){K 6.R(J(){E.16.1V(6,a,b)})},1N:J(c,a,b){K 6.R(J(){E.16.1N(c,a,6,P,b)})},5n:J(c,a,b){7(6[0])K E.16.1N(c,a,6[0],S,b);K 10},2g:J(){L b=18;K 6.4V(J(a){6.4N=0==6.4N?1:0;a.36();K b[6.4N].1i(6,18)||S})},7D:J(a,b){K 6.2j(\'3C\',a).2j(\'3B\',b)},21:J(a){5M();7(E.2Q)a.1P(T,E);N E.3A.1g(J(){K a.1P(6,E)});K 6}});E.1s({2Q:S,3A:[],21:J(){7(!E.2Q){E.2Q=P;7(E.3A){E.R(E.3A,J(){6.1i(T)});E.3A=V}E(T).5n("21")}}});L x=S;J 5M(){7(x)K;x=P;7(T.3F&&!E.14.2z)T.3F("5W",E.21,S);7(E.14.1d&&1e==3b)(J(){7(E.2Q)K;1S{T.1F.7B("26")}1X(3a){3z(18.3R,0);K}E.21()})();7(E.14.2z)T.3F("5W",J(){7(E.2Q)K;Q(L i=0;i<T.4L.M;i++)7(T.4L[i].2Y){3z(18.3R,0);K}E.21()},S);7(E.14.2d){L a;(J(){7(E.2Q)K;7(T.39!="5V"&&T.39!="1y"){3z(18.3R,0);K}7(a===10)a=E("W, 7a[7A=7z]").M;7(T.4L.M!=a){3z(18.3R,0);K}E.21()})()}E.16.1b(1e,"3U",E.21)}E.R(("7y,7x,3U,7w,5d,4H,4V,7v,"+"7G,7u,7t,4P,4O,7s,2k,"+"58,7K,7q,7p,3a").23(","),J(i,b){E.1n[b]=J(a){K a?6.2j(b,a):6.1N(b)}});L I=J(a,c){L b=a.4S;2b(b&&b!=c)1S{b=b.1a}1X(3a){b=c}K b==c};E(1e).2j("4H",J(){E("*").1b(T).3w()});E.1n.1s({3U:J(g,d,c){7(E.1q(g))K 6.2j("3U",g);L e=g.1f(" ");7(e>=0){L i=g.2K(e,g.M);g=g.2K(0,e)}c=c||J(){};L f="4Q";7(d)7(E.1q(d)){c=d;d=V}N{d=E.3m(d);f="61"}L h=6;E.3P({1c:g,U:f,1H:"3q",O:d,1y:J(a,b){7(b=="1W"||b=="5U")h.3q(i?E("<1x/>").3t(a.4b.1r(/<1m(.|\\s)*?\\/1m>/g,"")).2s(i):a.4b);h.R(c,[a.4b,b,a])}});K 6},7n:J(){K E.3m(6.5T())},5T:J(){K 6.2c(J(){K E.12(6,"3u")?E.2I(6.7m):6}).1E(J(){K 6.31&&!6.2Y&&(6.3k||/2k|6h/i.17(6.12)||/1u|1Z|3I/i.17(6.U))}).2c(J(i,c){L b=E(6).5O();K b==V?V:b.1k==1M?E.2c(b,J(a,i){K{31:c.31,1A:a}}):{31:c.31,1A:b}}).22()}});E.R("5S,6d,5R,6D,5Q,6m".23(","),J(i,o){E.1n[o]=J(f){K 6.2j(o,f)}});L B=(1B 3v).3L();E.1s({22:J(d,b,a,c){7(E.1q(b)){a=b;b=V}K E.3P({U:"4Q",1c:d,O:b,1W:a,1H:c})},7l:J(b,a){K E.22(b,V,a,"1m")},7k:J(c,b,a){K E.22(c,b,a,"3i")},7i:J(d,b,a,c){7(E.1q(b)){a=b;b={}}K E.3P({U:"61",1c:d,O:b,1W:a,1H:c})},85:J(a){E.1s(E.4I,a)},4I:{2a:P,U:"4Q",2U:0,5P:"4o/x-7h-3u-7g",5N:P,3l:P,O:V,6p:V,3I:V,49:{3M:"4o/3M, 1u/3M",3q:"1u/3q",1m:"1u/4m, 4o/4m",3i:"4o/3i, 1u/4m",1u:"1u/a7",4G:"*/*"}},4F:{},3P:J(s){L f,2W=/=\\?(&|$)/g,1z,O;s=E.1s(P,s,E.1s(P,{},E.4I,s));7(s.O&&s.5N&&1o s.O!="25")s.O=E.3m(s.O);7(s.1H=="4E"){7(s.U.2h()=="22"){7(!s.1c.1D(2W))s.1c+=(s.1c.1D(/\\?/)?"&":"?")+(s.4E||"7d")+"=?"}N 7(!s.O||!s.O.1D(2W))s.O=(s.O?s.O+"&":"")+(s.4E||"7d")+"=?";s.1H="3i"}7(s.1H=="3i"&&(s.O&&s.O.1D(2W)||s.1c.1D(2W))){f="4E"+B++;7(s.O)s.O=(s.O+"").1r(2W,"="+f+"$1");s.1c=s.1c.1r(2W,"="+f+"$1");s.1H="1m";1e[f]=J(a){O=a;1W();1y();1e[f]=10;1S{2V 1e[f]}1X(e){}7(h)h.34(g)}}7(s.1H=="1m"&&s.1T==V)s.1T=S;7(s.1T===S&&s.U.2h()=="22"){L i=(1B 3v()).3L();L j=s.1c.1r(/(\\?|&)4r=.*?(&|$)/,"$a4="+i+"$2");s.1c=j+((j==s.1c)?(s.1c.1D(/\\?/)?"&":"?")+"4r="+i:"")}7(s.O&&s.U.2h()=="22"){s.1c+=(s.1c.1D(/\\?/)?"&":"?")+s.O;s.O=V}7(s.2a&&!E.5H++)E.16.1N("5S");7((!s.1c.1f("a3")||!s.1c.1f("//"))&&s.1H=="1m"&&s.U.2h()=="22"){L h=T.3S("6f")[0];L g=T.3s("1m");g.3Q=s.1c;7(s.7c)g.a2=s.7c;7(!f){L l=S;g.9Z=g.9Y=J(){7(!l&&(!6.39||6.39=="5V"||6.39=="1y")){l=P;1W();1y();h.34(g)}}}h.38(g);K 10}L m=S;L k=1e.78?1B 78("9X.9V"):1B 76();k.9T(s.U,s.1c,s.3l,s.6p,s.3I);1S{7(s.O)k.4C("9R-9Q",s.5P);7(s.5C)k.4C("9O-5A-9N",E.4F[s.1c]||"9L, 9K 9I 9H 5z:5z:5z 9F");k.4C("X-9C-9A","76");k.4C("9z",s.1H&&s.49[s.1H]?s.49[s.1H]+", */*":s.49.4G)}1X(e){}7(s.6Y)s.6Y(k);7(s.2a)E.16.1N("6m",[k,s]);L c=J(a){7(!m&&k&&(k.39==4||a=="2U")){m=P;7(d){6I(d);d=V}1z=a=="2U"&&"2U"||!E.6X(k)&&"3a"||s.5C&&E.6J(k,s.1c)&&"5U"||"1W";7(1z=="1W"){1S{O=E.6W(k,s.1H)}1X(e){1z="5x"}}7(1z=="1W"){L b;1S{b=k.5q("6U-5A")}1X(e){}7(s.5C&&b)E.4F[s.1c]=b;7(!f)1W()}N E.5v(s,k,1z);1y();7(s.3l)k=V}};7(s.3l){L d=53(c,13);7(s.2U>0)3z(J(){7(k){k.9t();7(!m)c("2U")}},s.2U)}1S{k.9s(s.O)}1X(e){E.5v(s,k,V,e)}7(!s.3l)c();J 1W(){7(s.1W)s.1W(O,1z);7(s.2a)E.16.1N("5Q",[k,s])}J 1y(){7(s.1y)s.1y(k,1z);7(s.2a)E.16.1N("5R",[k,s]);7(s.2a&&!--E.5H)E.16.1N("6d")}K k},5v:J(s,a,b,e){7(s.3a)s.3a(a,b,e);7(s.2a)E.16.1N("6D",[a,s,e])},5H:0,6X:J(r){1S{K!r.1z&&9q.9p=="59:"||(r.1z>=6T&&r.1z<9n)||r.1z==6R||r.1z==9l||E.14.2d&&r.1z==10}1X(e){}K S},6J:J(a,c){1S{L b=a.5q("6U-5A");K a.1z==6R||b==E.4F[c]||E.14.2d&&a.1z==10}1X(e){}K S},6W:J(r,b){L c=r.5q("9k-U");L d=b=="3M"||!b&&c&&c.1f("3M")>=0;L a=d?r.9j:r.4b;7(d&&a.1F.28=="5x")6Q"5x";7(b=="1m")E.5g(a);7(b=="3i")a=6c("("+a+")");K a},3m:J(a){L s=[];7(a.1k==1M||a.5h)E.R(a,J(){s.1g(3r(6.31)+"="+3r(6.1A))});N Q(L j 1p a)7(a[j]&&a[j].1k==1M)E.R(a[j],J(){s.1g(3r(j)+"="+3r(6))});N s.1g(3r(j)+"="+3r(a[j]));K s.6a("&").1r(/%20/g,"+")}});E.1n.1s({1G:J(c,b){K c?6.2e({1R:"1G",27:"1G",1w:"1G"},c,b):6.1E(":1Z").R(J(){6.W.19=6.5s||"";7(E.1j(6,"19")=="2H"){L a=E("<"+6.28+" />").6y("1h");6.W.19=a.1j("19");7(6.W.19=="2H")6.W.19="3D";a.1V()}}).3h()},1I:J(b,a){K b?6.2e({1R:"1I",27:"1I",1w:"1I"},b,a):6.1E(":4d").R(J(){6.5s=6.5s||E.1j(6,"19");6.W.19="2H"}).3h()},6N:E.1n.2g,2g:J(a,b){K E.1q(a)&&E.1q(b)?6.6N(a,b):a?6.2e({1R:"2g",27:"2g",1w:"2g"},a,b):6.R(J(){E(6)[E(6).3H(":1Z")?"1G":"1I"]()})},9f:J(b,a){K 6.2e({1R:"1G"},b,a)},9d:J(b,a){K 6.2e({1R:"1I"},b,a)},9c:J(b,a){K 6.2e({1R:"2g"},b,a)},9a:J(b,a){K 6.2e({1w:"1G"},b,a)},99:J(b,a){K 6.2e({1w:"1I"},b,a)},97:J(c,a,b){K 6.2e({1w:a},c,b)},2e:J(l,k,j,h){L i=E.6P(k,j,h);K 6[i.2P===S?"R":"2P"](J(){7(6.15!=1)K S;L g=E.1s({},i);L f=E(6).3H(":1Z"),4A=6;Q(L p 1p l){7(l[p]=="1I"&&f||l[p]=="1G"&&!f)K E.1q(g.1y)&&g.1y.1i(6);7(p=="1R"||p=="27"){g.19=E.1j(6,"19");g.32=6.W.32}}7(g.32!=V)6.W.32="1Z";g.40=E.1s({},l);E.R(l,J(c,a){L e=1B E.2t(4A,g,c);7(/2g|1G|1I/.17(a))e[a=="2g"?f?"1G":"1I":a](l);N{L b=a.3X().1D(/^([+-]=)?([\\d+-.]+)(.*)$/),1Y=e.2m(P)||0;7(b){L d=2M(b[2]),2A=b[3]||"2S";7(2A!="2S"){4A.W[c]=(d||1)+2A;1Y=((d||1)/e.2m(P))*1Y;4A.W[c]=1Y+2A}7(b[1])d=((b[1]=="-="?-1:1)*d)+1Y;e.45(1Y,d,2A)}N e.45(1Y,a,"")}});K P})},2P:J(a,b){7(E.1q(a)||(a&&a.1k==1M)){b=a;a="2t"}7(!a||(1o a=="25"&&!b))K A(6[0],a);K 6.R(J(){7(b.1k==1M)A(6,a,b);N{A(6,a).1g(b);7(A(6,a).M==1)b.1i(6)}})},94:J(b,c){L a=E.3G;7(b)6.2P([]);6.R(J(){Q(L i=a.M-1;i>=0;i--)7(a[i].Y==6){7(c)a[i](P);a.72(i,1)}});7(!c)6.5p();K 6}});L A=J(b,c,a){7(!b)K 10;c=c||"2t";L q=E.O(b,c+"2P");7(!q||a)q=E.O(b,c+"2P",a?E.2I(a):[]);K q};E.1n.5p=J(a){a=a||"2t";K 6.R(J(){L q=A(6,a);q.4l();7(q.M)q[0].1i(6)})};E.1s({6P:J(b,a,c){L d=b&&b.1k==92?b:{1y:c||!c&&a||E.1q(b)&&b,2u:b,3Z:c&&a||a&&a.1k!=91&&a};d.2u=(d.2u&&d.2u.1k==51?d.2u:{90:8Z,9D:6T}[d.2u])||8X;d.5y=d.1y;d.1y=J(){7(d.2P!==S)E(6).5p();7(E.1q(d.5y))d.5y.1i(6)};K d},3Z:{70:J(p,n,b,a){K b+a*p},5j:J(p,n,b,a){K((-24.8V(p*24.8U)/2)+0.5)*a+b}},3G:[],3W:V,2t:J(b,c,a){6.11=c;6.Y=b;6.1l=a;7(!c.47)c.47={}}});E.2t.2l={4y:J(){7(6.11.30)6.11.30.1i(6.Y,[6.2J,6]);(E.2t.30[6.1l]||E.2t.30.4G)(6);7(6.1l=="1R"||6.1l=="27")6.Y.W.19="3D"},2m:J(a){7(6.Y[6.1l]!=V&&6.Y.W[6.1l]==V)K 6.Y[6.1l];L r=2M(E.1j(6.Y,6.1l,a));K r&&r>-8Q?r:2M(E.2o(6.Y,6.1l))||0},45:J(c,b,d){6.5B=(1B 3v()).3L();6.1Y=c;6.3h=b;6.2A=d||6.2A||"2S";6.2J=6.1Y;6.4B=6.4w=0;6.4y();L e=6;J t(a){K e.30(a)}t.Y=6.Y;E.3G.1g(t);7(E.3W==V){E.3W=53(J(){L a=E.3G;Q(L i=0;i<a.M;i++)7(!a[i]())a.72(i--,1);7(!a.M){6I(E.3W);E.3W=V}},13)}},1G:J(){6.11.47[6.1l]=E.1J(6.Y.W,6.1l);6.11.1G=P;6.45(0,6.2m());7(6.1l=="27"||6.1l=="1R")6.Y.W[6.1l]="8N";E(6.Y).1G()},1I:J(){6.11.47[6.1l]=E.1J(6.Y.W,6.1l);6.11.1I=P;6.45(6.2m(),0)},30:J(a){L t=(1B 3v()).3L();7(a||t>6.11.2u+6.5B){6.2J=6.3h;6.4B=6.4w=1;6.4y();6.11.40[6.1l]=P;L b=P;Q(L i 1p 6.11.40)7(6.11.40[i]!==P)b=S;7(b){7(6.11.19!=V){6.Y.W.32=6.11.32;6.Y.W.19=6.11.19;7(E.1j(6.Y,"19")=="2H")6.Y.W.19="3D"}7(6.11.1I)6.Y.W.19="2H";7(6.11.1I||6.11.1G)Q(L p 1p 6.11.40)E.1J(6.Y.W,p,6.11.47[p])}7(b&&E.1q(6.11.1y))6.11.1y.1i(6.Y);K S}N{L n=t-6.5B;6.4w=n/6.11.2u;6.4B=E.3Z[6.11.3Z||(E.3Z.5j?"5j":"70")](6.4w,n,0,1,6.11.2u);6.2J=6.1Y+((6.3h-6.1Y)*6.4B);6.4y()}K P}};E.2t.30={2v:J(a){a.Y.2v=a.2J},2x:J(a){a.Y.2x=a.2J},1w:J(a){E.1J(a.Y.W,"1w",a.2J)},4G:J(a){a.Y.W[a.1l]=a.2J+a.2A}};E.1n.5L=J(){L b=0,3b=0,Y=6[0],5l;7(Y)8M(E.14){L d=Y.1a,41=Y,1K=Y.1K,1L=Y.2i,5D=2d&&4s(5K)<8J&&!/a1/i.17(v),2T=E.1j(Y,"43")=="2T";7(Y.6G){L c=Y.6G();1b(c.26+24.2f(1L.1F.2v,1L.1h.2v),c.3b+24.2f(1L.1F.2x,1L.1h.2x));1b(-1L.1F.62,-1L.1F.60)}N{1b(Y.5G,Y.5F);2b(1K){1b(1K.5G,1K.5F);7(48&&!/^t(8H|d|h)$/i.17(1K.28)||2d&&!5D)2N(1K);7(!2T&&E.1j(1K,"43")=="2T")2T=P;41=/^1h$/i.17(1K.28)?41:1K;1K=1K.1K}2b(d&&d.28&&!/^1h|3q$/i.17(d.28)){7(!/^8G|1O.*$/i.17(E.1j(d,"19")))1b(-d.2v,-d.2x);7(48&&E.1j(d,"32")!="4d")2N(d);d=d.1a}7((5D&&(2T||E.1j(41,"43")=="4W"))||(48&&E.1j(41,"43")!="4W"))1b(-1L.1h.5G,-1L.1h.5F);7(2T)1b(24.2f(1L.1F.2v,1L.1h.2v),24.2f(1L.1F.2x,1L.1h.2x))}5l={3b:3b,26:b}}J 2N(a){1b(E.2o(a,"a8",P),E.2o(a,"a9",P))}J 1b(l,t){b+=4s(l)||0;3b+=4s(t)||0}K 5l}})();',62,631,'||||||this|if||||||||||||||||||||||||||||||||||||||function|return|var|length|else|data|true|for|each|false|document|type|null|style||elem||undefined|options|nodeName||browser|nodeType|event|test|arguments|display|parentNode|add|url|msie|window|indexOf|push|body|apply|css|constructor|prop|script|fn|typeof|in|isFunction|replace|extend|className|text|handle|opacity|div|complete|status|value|new|firstChild|match|filter|documentElement|show|dataType|hide|attr|offsetParent|doc|Array|trigger|table|call|break|height|try|cache|tbody|remove|success|catch|start|hidden||ready|get|split|Math|string|left|width|tagName|ret|global|while|map|safari|animate|max|toggle|toLowerCase|ownerDocument|bind|select|prototype|cur||curCSS|selected|handler|done|find|fx|duration|scrollLeft|id|scrollTop|special|opera|unit|nextSibling|stack|guid|toUpperCase|pushStack|button|none|makeArray|now|slice|target|parseFloat|border|exec|queue|isReady|events|px|fixed|timeout|delete|jsre|one|disabled|nth|step|name|overflow|inArray|removeChild|removeData|preventDefault|merge|appendChild|readyState|error|top|which|innerHTML|multiFilter|rl|trim|end|json|first|checked|async|param|elems|insertBefore|childNodes|html|encodeURIComponent|createElement|append|form|Date|unbind|color|grep|setTimeout|readyList|mouseleave|mouseenter|block|isXMLDoc|addEventListener|timers|is|password|last|runtimeStyle|getTime|xml|jQuery|domManip|ajax|src|callee|getElementsByTagName|selectedIndex|load|object|timerId|toString|has|easing|curAnim|offsetChild|args|position|stopPropagation|custom|props|orig|mozilla|accepts|clean|responseText|defaultView|visible|String|charCode|float|teardown|on|setup|nodeIndex|shift|javascript|currentStyle|application|child|RegExp|_|parseInt|previousSibling|dir|tr|state|empty|update|getAttribute|self|pos|setRequestHeader|input|jsonp|lastModified|_default|unload|ajaxSettings|unshift|getComputedStyle|styleSheets|getPropertyValue|lastToggle|mouseout|mouseover|GET|andSelf|relatedTarget|init|visibility|click|absolute|index|container|fix|outline|Number|removeAttribute|setInterval|prevObject|classFilter|not|unique|submit|file|after|windowData|deep|scroll|client|triggered|globalEval|jquery|sibling|swing|clone|results|wrapAll|triggerHandler|lastChild|dequeue|getResponseHeader|createTextNode|oldblock|checkbox|radio|handleError|fromElement|parsererror|old|00|Modified|startTime|ifModified|safari2|getWH|offsetTop|offsetLeft|active|values|getElementById|version|offset|bindReady|processData|val|contentType|ajaxSuccess|ajaxComplete|ajaxStart|serializeArray|notmodified|loaded|DOMContentLoaded|Width|ctrlKey|keyCode|clientTop|POST|clientLeft|clientX|pageX|exclusive|detachEvent|removeEventListener|swap|cloneNode|join|attachEvent|eval|ajaxStop|substr|head|parse|textarea|reset|image|zoom|odd|ajaxSend|even|before|username|prepend|expr|quickClass|uuid|quickID|quickChild|continue|textContent|appendTo|contents|evalScript|parent|defaultValue|ajaxError|setArray|compatMode|getBoundingClientRect|styleFloat|clearInterval|httpNotModified|nodeValue|100|alpha|_toggle|href|speed|throw|304|replaceWith|200|Last|colgroup|httpData|httpSuccess|beforeSend|eq|linear|concat|splice|fieldset|multiple|cssFloat|XMLHttpRequest|webkit|ActiveXObject|CSS1Compat|link|metaKey|scriptCharset|callback|col|pixelLeft|urlencoded|www|post|hasClass|getJSON|getScript|elements|serialize|black|keyup|keypress|solid|change|mousemove|mouseup|dblclick|resize|focus|blur|stylesheet|rel|doScroll|round|hover|padding|offsetHeight|mousedown|offsetWidth|Bottom|Top|keydown|clientY|Right|pageY|Left|toElement|srcElement|cancelBubble|returnValue|charAt|0n|substring|animated|header|noConflict|line|enabled|innerText|contains|only|weight|ajaxSetup|font|size|gt|lt|uFFFF|u0128|417|Boolean|inner|Height|toggleClass|removeClass|addClass|removeAttr|replaceAll|insertAfter|prependTo|contentWindow|contentDocument|wrap|iframe|children|siblings|prevAll|nextAll|prev|wrapInner|next|parents|maxLength|maxlength|readOnly|readonly|reverse|class|htmlFor|inline|able|boxModel|522|setData|compatible|with|1px|ie|getData|10000|ra|it|rv|PI|cos|userAgent|400|navigator|600|slow|Function|Object|array|stop|ig|NaN|fadeTo|option|fadeOut|fadeIn|setAttribute|slideToggle|slideUp|changed|slideDown|be|can|property|responseXML|content|1223|getAttributeNode|300|method|protocol|location|action|send|abort|cssText|th|td|cap|specified|Accept|With|colg|Requested|fast|tfoot|GMT|thead|1970|Jan|attributes|01|Thu|leg|Since|If|opt|Type|Content|embed|open|area|XMLHTTP|hr|Microsoft|onreadystatechange|onload|meta|adobeair|charset|http|1_|img|br|plain|borderLeftWidth|borderTopWidth|abbr'.split('|'),0,{}))

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/nodnix.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/nodnix.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/nodnix.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 // _*_ Mode: JavaScript; tab-width: 8; indent-tabs-mode: true _*_
-// $Id: nodnix.js,v 1.9 2008/02/20 18:43:31 scc Exp $
+; // $Id$
 
 var nod_completer = null;
 var nix_completer = null;

Copied: slashjp/trunk/plugins/Ajax/htdocs/images/responder.tagui.js (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/htdocs/images/responder.tagui.js)
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/responder.tagui.js	                        (rev 0)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/responder.tagui.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,39 @@
+(function($){
+
+if ( window.TagUI === undefined ) {
+	window.TagUI = {};
+}
+
+window.TagUI.tag_responder = new API({
+	name: 'tag_responder',
+	element_api: {
+		ready: function( r_elem, if_ready ){
+			var $r_elem = $(r_elem), ready_class = 'ready';
+			if ( if_ready === undefined ) {
+				return $(r_elem).hasClass(ready_class);
+			}
+			$(r_elem).toggleClassTo(ready_class, if_ready);
+			return r_elem;
+		},
+		bind: function( r_elem, fn, signals ){
+			r_elem.tag_responder.handle_signal = fn;
+			$(r_elem).attr('signal', list_as_string(signals));
+			return r_elem;
+		},
+		handle: function( r_elem, signals, data, options ){
+			var fn = r_elem.tag_responder && r_elem.tag_responder.handle_signal;
+			if ( fn ) {
+				fn.apply(r_elem, [signals, data, options]);
+			}
+			return r_elem;
+		}
+	},
+	element_constructor: function( r_elem, fn, signals, if_ready ){
+		r_elem.
+			tag_responder.bind(fn, signals).
+			tag_responder.ready(if_ready===undefined?true:if_ready);
+	},
+	extend_jquery_wrapper: true
+});
+
+})(jQuery);

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/sd_autocomplete.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/sd_autocomplete.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/sd_autocomplete.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 // _*_ Mode: JavaScript; tab-width: 8; indent-tabs-mode: true _*_
-// $Id: sd_autocomplete.js,v 1.41 2007/09/28 21:21:20 scc Exp $
+; // $Id$
 
 YAHOO.namespace("slashdot");
 

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/sd_calendar.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/sd_calendar.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/sd_calendar.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 // _*_ Mode: JavaScript; tab-width: 8; indent-tabs-mode: true _*_
-// $Id: sd_calendar.js,v 1.9 2008/03/28 20:53:43 pudge Exp $
+; // $Id$
 
 YAHOO.namespace("slashdot");
 

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,10 +1,10 @@
-// $Id$
+; // $Id$
 
 function configSectionPopup() { 
 	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...");
+	createPopup(getXYForSelector('#links-sections-title'), title, "sectionprefs", "", "Loading...");
 	
 	var url = 'ajax.pl';
 	var params = {};

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/slashbox.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/slashbox.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/slashbox.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-YAHOO.namespace("slashdot");
+; YAHOO.namespace("slashdot");
 
 YAHOO.slashdot.SlashBox = function( id, sGroup, config ) {
 	if ( id ) {

Copied: slashjp/trunk/plugins/Ajax/htdocs/images/t (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/htdocs/images/t)

Copied: slashjp/trunk/plugins/Ajax/htdocs/images/tagui.css (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/htdocs/images/tagui.css)
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/tagui.css	                        (rev 0)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/tagui.css	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,444 @@
+.tag-widget, .tag-entry {
+	user-select: text;
+	-moz-user-select: text;
+}
+
+span.tag, .tmenu, .tag-display, .tag-display-set,
+.tag-display ul, .tag-display li, .tag-display h1.legend,
+.edit-toggle, .tag-widget .related {
+	user-select: none;
+	-moz-user-select: none;
+}
+
+span.tag, .tmenu, .tag-display ul, .tag-display li, .edit-toggle {
+	cursor: pointer;
+}
+
+.tag-entry {
+	cursor: text !important;
+}
+
+
+.tag-display span.tag,
+.tag-widget .admin-buttons {
+	font-family: Optima, sans serif;
+}
+
+/* style tags based on what they are */
+/* ...for everyone */
+.bang > span.tag > .punct { font-weight: bold }
+.minus > .tag { text-decoration: line-through; background-color: inherit !important; }
+.not-saved > .tag { color: darkgray; background-color: inherit !important; }
+
+/* only for admins */
+.adminmode[tag-server] .s1 > .tag,
+.adminmode[tag-server] .t2 > .tag {
+	font-weight: bold;
+	font-variant: small-caps;
+}
+.adminmode[tag-server] .pound > .tag { font-weight: bold }
+.adminmode[tag-server] .descriptive > .tag { color: orange }
+.adminmode[tag-server] .ignore > .tag { color: darkgray }
+
+/* tag "suggestions" look different than tags actually applied */
+.tag-display[context=related] li.suggestion span.tag {
+	font-style: italic;
+	font-weight: bold;
+}
+
+div.tag-display ul, div.tag-display li {
+	display: inline;
+	list-style: none inherit none !important;
+}
+
+/* your personal tags hidden if that tag already in top|system... */
+.tag-display[context=user] li.p,
+.tag-display[context=top] li.p,
+.tag-display[context=system] li.p,
+.tag-display[context=user] li.t,
+.tag-display[context=user] li.s,
+.tag-display[context=top]  li.s {
+	display: none;
+}
+
+div.tag-display .tmenu li {
+	text-align: center;
+	margin: 0 !important;
+}
+
+div.tag-display .tmenu li.minus,
+div.tag-display .tmenu li.ignore,
+div.tag-display .tmenu li.pound,
+div.tag-display .tmenu li.descriptive {
+	display: none;
+}
+
+div.tag-display li.u > .tmenu li.minus,
+div.tag-display li.u > .tmenu li.descriptive,
+div.tag-display li.t > .tmenu li.pound,
+div.tag-display li.t > .tmenu li.ignore,
+div.tag-display li.t > .tmenu li.descriptive {
+	display: inline-block;
+}
+
+/* no menus for newly added tags */
+.tag-display li.not-saved .tmenu,
+.tag-display[context=signoff] .tmenu,
+.tag-display li.d .tmenu {
+	display: none !important;
+}
+
+/* but style the tag that hid yours, so you know */
+.tag-display[context=top] li.u,
+.tag-display[context=system] li.u,
+.tag-display[context=related] li.u {
+	text-decoration: underline;
+}
+
+.tag-display li:hover span.tag {
+	cursor: arrow;
+	color: white;
+	background-color: #066;
+}
+
+.tag-display[context=signoff] {
+	padding-left: 0.5em;
+}
+
+.tag-display[context=signoff] .w span.tag {
+	background-color: #ff4949 !important;
+}
+
+.tag-display[context=signoff] .w:hover span.tag {
+	background-color: #f00 !important;
+}
+
+/* no mouse over highlight for datatypes */
+.tag-display li.d:hover span.tag {
+	color: inherit;
+	background-color: inherit;
+}
+
+div.tag-display > h1.legend {
+	width: auto !important;
+}
+
+/* round edges */
+.tag-display ul,
+.tag-display span.tag,
+.tag-display .tmenu,
+.tag-display .tmenu li,
+.tag-display h1.legend {
+	border: 0 solid transparent;
+	-moz-border-radius: 0.4em;
+	-webkit-border-radius: 0.4em;
+}
+
+/* padding so hover highlighting is bigger than the contents */
+div.tag-display > ul,
+#contents div.tag-display > ul,
+div.tag-display .tmenu li span,
+#contents div.tag-display .tmenu li span {
+	padding: 0.1em 0.5em !important;
+	margin: -0.1em -0.5em !important;
+}
+
+div.tag-display span.tag,
+div.tag-display > h1.legend,
+#contents div.tag-display > h1.legend {
+	padding: 0.1em 0.3em !important;
+	margin: -0.1em -0.3em !important;
+}
+
+div.tag-display .tmenu li span,
+#contents div.tag-display .tmenu li span {
+	text-align: center;
+}
+
+
+/* give the menus something to position against */
+.tag-display > ul > li {
+	position: relative;
+}
+
+/* tag menus are hidden by default... */
+.tag-display .tmenu {
+	display: none;
+	position: absolute;
+	top: -2.15em;
+	right: -.3em;
+	font-size: 85%;
+	color: #fff;
+	background-color: #066;
+	white-space:nowrap;
+	opacity: 0.5;
+	-moz-opacity: 0.5;
+	padding: 0 .3em 0 .2em !important;
+	text-align: center;
+	margin:0 !important;
+
+}
+
+/* ...until you mouse over element to which they are attached */
+.tag-display li:hover ul.tmenu {
+	display: block;
+}
+
+/* no hover menus for datatypes */
+.tag-display li.d:hover ul.tmenu {
+	display: none;
+}
+
+/* the menu item itself */
+.tag-display .tmenu:hover {
+	opacity: 0.9;
+}
+
+.tag-display .tmenu > li:hover {
+	color: white;
+	background-color: black !important;
+}
+
+/* separate tags, also menu items */
+div.tag-display > ul > li,
+div.tag-display .tmenu > li {
+	margin-left: 0 !important;
+}
+
+div.tag-display .tmenu > li + li,
+div.tag-display > ul > li + li {
+	margin-left: 0.25em !important;
+}
+
+
+.tag-display > h1.legend {
+	display: none;
+	position: absolute;
+
+	top: -2.2em;
+	left: -0.2em;
+
+	color: #444;
+	background-color: white;
+	opacity: 0.85;
+
+	font-size: 85% !important;
+	text-align: left;
+	text-transform: capitalize;
+}
+
+.tag-display:hover > h1.legend {
+	display: block;
+}
+
+.tag-display h1.legend {
+	-moz-border-radius-bottomleft: 0;
+	-moz-border-radius-bottomright: 0;
+	-webkit-border-bottom-left-radius: 0em;
+	-webkit-border-bottom-right-radius: 0em;
+}
+
+.tag-display[context=related] > h1.legend {
+	bottom: -2em !important;
+	top: inherit;
+
+	-moz-border-radius-bottomleft: 0.4em;
+	-moz-border-radius-bottomright: 0.4em;
+	-webkit-border-bottom-left-radius: 0.4em;
+	-webkit-border-bottom-right-radius: 0.4em;
+
+	-moz-border-radius-topleft: 0;
+	-moz-border-radius-topright: 0;
+	-webkit-border-top-left-radius: 0;
+	-webkit-border-top-right-radius: 0;
+}
+
+/* ...that's everything _in_ a tag-display... now let's do the display itself */
+
+div.tag-display {
+	display: inline;
+	position: relative;
+	margin-left: 0 !important;
+}
+
+.tag-display:hover > ul {
+	background-color: #dfdfdf;
+}
+
+.tag-widget-stub,
+.tag-display-stub,
+.tag-display.no-tags,
+.tag-display[context=related].no-tags,
+.tag-display[context=user].no-visible-tags {
+	display: none !important;
+}
+
+.tag-widget .tag-display[context=user] {
+	display: none;
+}
+
+.tag-widget.expanded .tag-display[context=user] {
+	display: inline;
+}
+
+
+.tag-display[context=related] {
+	display: block;
+	text-align: left;
+}
+
+
+.tag-display-set.train {
+	display: inline;
+	margin-right: 1em;
+}
+
+.tag-widget.expanded .tag-display-set.train {
+	padding-right: 1em;
+}
+
+
+.tag-widget .tag-entry {
+	display: none;
+	margin-right: 0.4em;
+}
+
+.tag-widget.expanded .tag-entry {
+	display: inline;
+}
+
+.tag-widget .working + .tag-server-busy {
+	display: block;
+}
+
+.tag-widget .tag-server-busy {
+	display: none;
+	position: absolute;
+}
+
+.tag-widget.expanded .tag-server-busy {
+	top: 0.5em;
+	right: 0.25em;
+}
+
+.tag-editor {
+	display: none;
+}
+
+.tag-widget.expanded .tag-editor {
+	display: inline;
+}
+
+.tag-widget {
+	display: block;
+	position: absolute;
+	background-color: transparent;
+}
+
+
+/* firehose-specific [to the end of the file] */
+
+#firehose .tag-widget.body-widget {
+	right: -0.5em;
+	bottom: 6px;
+	z-index: 10;
+	padding: 0 0.4em 0 0.8em;
+	text-align: right;
+}
+
+#firehose .tag-widget.body-widget.expanded {
+	right: 0;
+}
+
+.tag-widget .note-wrapper {
+	display: block;
+	font-style: italic;
+	padding-right: 0.4em;
+	margin: 0 1em 0.5em 0;
+}
+
+.tag-widget .note-wrapper.no-note {
+	display: inline;
+	font-style: inherit;
+	padding-right: 0;
+}
+
+.tag-widget .admin-buttons {
+	padding-right: 0.7em;
+}
+
+.tag-widget .admin-buttons .note-input {
+	font-style: italic;
+}
+
+.tag-widget .admin-buttons a {
+	text-decoration: none;
+}
+
+.tag-widget .admin-buttons .note-wrapper:before {
+	content: 'Note: ';
+}
+
+.tag-widget .admin-buttons a:before,
+.tag-widget .admin-buttons .note-wrapper.no-note a:before {
+	content: '[';
+}
+
+.tag-widget .admin-buttons a:after,
+.tag-widget .admin-buttons .note-wrapper.no-note a:after {
+	content: ']';
+}
+
+.tag-widget .admin-buttons .note-wrapper a:before,
+.tag-widget .admin-buttons .note-wrapper a:after,
+.tag-widget .admin-buttons .note-wrapper.no-note:before {
+	content: '';
+}
+
+.tag-widget div.tags {
+	display: inline;
+	position: relative;
+	right: 1em !important;
+	top: 0.8em;
+	margin-left: 1em;
+}
+
+.briefarticle .tag-widget.body-widget {
+	display: none !important;
+}
+
+
+/* nod/nix suggestion bar */
+
+.tag-widget.nod-nix-reasons {
+	position: relative;
+	bottom: 0;
+	color: inherit;
+	background-color: inherit;
+	text-align: inherit;
+	padding-left: 0.8em;
+
+	z-index: 10;
+}
+
+div.article div.title div.nod-nix-reasons span.tag {
+	color: white;
+}
+
+.nod-nix-reasons .tag-display li:hover span.tag {
+	color: white;
+	background-color: black;
+}
+
+.nod-nix-reasons .tag-display:hover ul {
+	background-color: inherit;
+}
+
+.note-flag {
+	position: absolute;
+	right: 6em;
+}
+
+.note-flag.no-note {
+	opacity: 0;
+}

Copied: slashjp/trunk/plugins/Ajax/htdocs/images/tagui.js (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/htdocs/images/tagui.js)
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/tagui.js	                        (rev 0)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/tagui.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,974 @@
+; // tagui.js
+
+var context_triggers, well_known_tags;
+
+function animate_wiggle( $selector ){
+	$selector.
+		animate({left: '-=3px'}, 20).
+		animate({left: '+=6px'}, 20).
+		animate({left: '-=6px'}, 20).
+		animate({left: '+=6px'}, 20).
+		animate({left: '-=3px'}, 20).
+		queue(function(){
+			$(this).css({left: ''}).dequeue();
+		});
+}
+
+
+var tag_server_fns = {
+
+	broadcast_tag_lists: function( broadcasts, options ){
+		var tuples = ('<notify>' + broadcasts).split(/\n?<([\w:]*)>/).slice(1);
+		if ( tuples && tuples.length >= 2 ) {
+			var $listeners = $('.ready[context]', this);
+
+			// work backwards so 'notify' context is last
+			while ( tuples.length >= 2 ) {
+				var data = tuples.pop();
+				var context = tuples.pop();
+				var context_name = context.split(':')[0];
+
+				$listeners.filter('[context*=' + context_name + ']').each(function(){
+					if ( this.receive_broadcast ) {
+						this.receive_broadcast(data, context, options);
+					}
+				});
+			}
+			recompute_css_classes(this, $listeners);
+		}
+		return this;
+	},
+
+
+	preprocess_commands: function( commands, options ){
+		var server = this;
+		$.each(this.command_pipeline, function(i, handler){
+			commands = handler.apply(server, [ commands, options ]);
+		});
+
+		return commands;
+	},
+
+
+	_ajax_request: function( tag_cmds, options ){
+
+		var feedback_options = $.extend(
+			{},
+			{ // default feedback
+				order:		'append',
+				classes:	'not-saved'
+			},
+			options );
+
+		var server_params = $.extend(
+			{},
+			{ // default params for the server-side handler
+				op:		'tags_setget_combined',
+				id:		$(this).attr('tag-server'),
+				reskey:		reskey_static,
+				limit_fetch:	''
+			},
+			options );
+
+		server_params.tags = '';
+
+		if ( tag_cmds ) {
+			tag_cmds = normalize_tag_commands(
+				this.preprocess_commands(list_as_array(tag_cmds), options),
+				this );
+
+			// if caller wanted to execute some commands,
+			//	but they were all normalized away
+			if ( !tag_cmds.length ) {
+				// ...then there's no work to do (not even fetching)
+				return this;
+			}
+
+
+			// 'harden' the new tags into the user tag-display, but styled 'not-saved'
+			// tags in the response from the server will wipe-out 'not-saved'
+			var $user_displays = $('.tag-display.ready[context*=user]', this);
+			$user_displays.each(function(){
+				this.update_tags(tag_cmds, feedback_options);
+			});
+
+			// Just for fun...
+			if ( options && options.classes ) {
+				animate_wiggle($user_displays.find('.'+options.classes + ':not(:contains("-"))'));
+			}
+
+			server_params.tags = list_as_string(tag_cmds);
+			// console.log('SENDING: '+server_params.tags);
+		}
+
+
+		var tag_server = this.mark_busy(true);
+		$.ajax($.extend(
+			{},
+			{
+				url:		'/ajax.pl',
+				type:		'POST',
+				dataType:	'text',
+				data:		server_params,
+				success: 	function( server_response ){
+							// console.log('RECEIVED: '+server_response);
+							tag_server.broadcast_tag_lists(server_response, options);
+						},
+				complete: 	function(){
+							tag_server.mark_busy(false);
+						}
+			},
+			options && options.ajax ));
+		return this;
+	},
+
+
+	fetch_tags: function( options ){
+		return this._ajax_request('', options);
+	},
+
+
+	submit_tags: function( tag_cmds, options ){
+		return this._ajax_request(tag_cmds, options);
+	},
+
+
+	mark_busy: function( if_busy ){
+		var was_busy = this.busy_depth > 0;
+		this.busy_depth += if_busy ? 1 : -1;
+		var now_busy = this.busy_depth > 0;
+
+		if ( now_busy != was_busy ) {
+			var $busy = $('.tag-server-busy', this);
+			if ( now_busy ) {
+				$busy.show();
+			} else {
+				$busy.removeAttr('style');
+			}
+		}
+
+		return this;
+	}
+
+};
+
+function install_tag_server( selector, item_id ) {
+	if ( item_id === undefined ) {
+		item_id = '*';
+	}
+
+	return $(selector).
+		attr('tag-server', item_id).
+		each(function(){
+			$.extend(this, tag_server_fns);
+			this.busy_depth = 0;
+			this.command_pipeline = [ normalize_nodnix ];
+		});
+}
+
+
+
+function bare_tag( t ) {
+	try {
+		// XXX what are the real requirements for a tag?
+		return /[a-z][a-z0-9]*/.exec(t.toLowerCase())[0];
+	} catch (e) {
+		// I can't do anything with it; I guess you must know what you're doing
+		return t;
+	}
+}
+
+function markup_tag( t ) {
+	try {
+		return t.replace(/^([^a-zA-Z]+)/, '<span class="punct">$1</span>');
+	} catch (e) {
+		return t;
+	}
+}
+
+
+function form_submit_tags( form, options ){
+	var $input = $('.tag-entry:input', form);
+	$related_trigger = $input;
+	$(form).nearest_parent('[tag-server]').
+		each(function(){
+			var tag_cmds = $input.val();
+			$input.val('');
+			this.submit_tags(tag_cmds, options);
+		});
+}
+
+
+var tag_display_fns = {
+
+	// return a dictionary mapping bare tags to the corresponding *.tag DOM element
+	map_tags: function( how ){
+		// map_tags() does not add, remove, or alter any tags
+
+		// we may limit the result, if the caller says how
+		var map_fn;
+		if ( !how ) {
+			// no limit, return a set of all my tags
+			map_fn = function(){return true;};
+		} else if ( $.isFunction(how) ) {
+			// the caller supplied a filter function
+			//  return a set containing only tags for which how(bare_tag(t)) answers true
+			map_fn = how;
+		} else {
+			// how must be a list
+			//  return a set that is the intersection of how and the tags I actually have
+			var allowed_tags = map_list_to_set(how, bare_tag);
+			map_fn = function(bt){return bt in allowed_tags;};
+		}
+
+		// now that we know how, iterate over my actual tags to build the result set
+		var if_mapped_all = true, map = {};
+		$('.tag', this).each(function(){
+			var bt = bare_tag($(this).text());
+			if ( map_fn(bt) ) {
+				map[bt] = this;
+			} else {
+				if_mapped_all = false;
+			}
+		});
+		return [ map, if_mapped_all ];
+	},
+
+
+	// replace existing tags and/or add new tags; preserves order of existing tags
+	//  optional string, options.order, tells where to add new tags { 'append', 'prepend' }
+	//  optional string, options.classes, tells a css class to add to all touched tags
+	update_tags: function( tags, options ){
+		options = $.extend(
+			{},
+			{
+				order:		'append',
+				classes:	''
+			},
+			options );
+
+		// invariant: before.count_tags() <= after.count_tags()
+		// no other call adds tags (except by calling _me_)
+
+		// the intersection of the requested vs. existing tags are the ones I can update in-place
+		var update_map = this.map_tags(tags = list_as_array(tags))[0];
+
+		// update in-place the ones we can; build a list of the ones we can't ($.map returns a js array)
+		var new_tags_seen = {};
+		var new_tags = $.map(tags, function(t){
+			var bt = bare_tag(t);
+			var mt = markup_tag(t);
+			if ( bt in update_map ) {
+				$(update_map[bt]).html(mt);
+			} else if ( !(bt in new_tags_seen) ) {
+				new_tags_seen[bt] = true;
+				return mt;
+			}
+		});
+
+		// a $ list of the actual .tag elements we updated in-place
+		var $changed_tags = $(values(update_map));
+
+		if ( new_tags.length ) {
+			// construct all the completely new tag entries and associated machinery
+			var $new_elems = $(join_wrap(
+					new_tags,
+					'<li class="p"><span class="tag">',
+					'</span></li>')).
+				append(this.tag_display_data.menu_template);
+
+			this.tag_display_data.$list_el[options.order]($new_elems);
+
+			// add in a list of the actual .tag elements we created from scratch
+			$changed_tags = $changed_tags.add( $new_elems.find('.tag') );
+
+			this.$mark_empty(false);
+		}
+
+		// for every .tag we added/changed, fix parent <li>'s css class(es)
+		//   Use case for options.classes: the tag was modified locally, we mark it with "not-saved" until the server
+		//   comes back with a complete list in response that will wipe out the "not-saved" class, essentially
+		//   confirming the user's change has been recorded
+		$changed_tags.each(function(){
+			var $tag = $(this);
+			$tag.parent().
+				removeClass().
+				addClass(static_css_classes_for($tag.text()) + ' ' + options.classes);
+		});
+		return this;
+	},
+
+
+	remove_tags: function( tags, options ){
+		var opts = $.extend({}, { fade_remove: 0 }, options);
+
+		// invariant: before.count_tags() >= after.count_tags()
+		// no other call removes tags (except by calling _me_)
+
+		// when called without an argument, removes all tags, otherwise
+		//   tags to remove may be specified by string, an array, or the result of a previous call to map_tags
+		var if_remove_all;
+		if ( !tags || tags.length ) {
+			var mapped = this.map_tags(tags);
+			tags = mapped[0];
+			if_remove_all = mapped[1];
+		}
+
+		var $remove_li = $(values(tags)).parent();
+
+		var display = this;
+		if ( opts.fade_remove ) {
+			$remove_li
+				.fadeOut(opts.fade_remove)
+				.queue(function(){
+					$(this).remove().dequeue();
+					if ( if_remove_all ) {
+						display.$mark_empty();
+					}
+				});
+		} else {
+			$remove_li.remove();
+			this.$mark_empty(if_remove_all);
+		}
+
+		return this;
+	},
+
+
+	// like remove_tags() followed by update_tags(tags) except order preserving for existing tags
+	set_tags: function( tags, options ){
+		var allowed_tags = map_list_to_set(tags = list_as_array(tags), bare_tag);
+		var removed_tags = this.map_tags(function(bt){
+			return !(bt in allowed_tags);
+		})[0];
+
+		return this.
+			remove_tags(removed_tags, options).
+			update_tags(tags, options);
+	},
+
+
+	$mark_empty: function( if_empty ){
+		var $this = $(this);
+		if ( if_empty === undefined ) {
+			if_empty = ! $this.is(':has(span.tag)');
+		}
+		return $this.toggleClassTo('no-tags', if_empty);
+	},
+
+
+	$mark_dirty: function( if_dirty ){
+		return $(this).toggleClassTo('dirty', if_dirty);
+	},
+
+
+	receive_broadcast: function( tags, context, options ){
+		return this.set_tags(tags, options);
+	}
+
+}; // tag_display_fns
+
+
+function markup_menu( label ){
+	var css_class;
+	if ( label in css_classes_for_prefix ) {
+		css_class = css_classes_for_prefix[label];
+	} else if ( label[0] in css_classes_for_prefix ) {
+		css_class = css_classes_for_prefix[ label[0] ];
+	} else if ( label == 'x' ) {
+		css_class = css_classes_for_prefix['-'];
+	} else {
+		css_class = label;
+	}
+
+	return '<li class="'+css_class+'"><span>'+label+'</span></li>';
+}
+
+
+function $init_tag_displays( $stubs, options ){
+	options = options || {};
+
+	$stubs.
+		each(function(){
+			var $this = $(this);
+
+			var init_data = $this.metadata({type:'attr', name:'init'});
+			$this.removeAttr('init');
+
+			var menu_items = '';
+			if ( init_data.menu === undefined || init_data.menu === true ) {
+				menu_items = $init_tag_displays.default_menu;
+			} else if ( init_data.menu ) {
+				menu_items = init_data.menu;
+			}
+
+			var menu_template = menu_items ? (
+					'<ul class="tmenu">' +
+					$.map(list_as_array(menu_items), function(label){
+						return markup_menu(label);
+					}).join('') +
+					'</ul>' ) : '';
+
+			var legend = init_data.legend ? '<h1 class="legend">' + init_data.legend + '</h1>' : '';
+
+			var tags = $this.text();
+			$this.html(legend+'<ul></ul>');
+
+			$.extend(
+				this,
+				tag_display_fns,
+				{
+					tag_display_data: {
+						menu_template:	menu_template,
+						$list_el:	$this.find('ul')
+					}
+				},
+				options );
+
+			$this.mapClass({
+				'tag-display-stub': 'tag-display ready no-tags dirty'
+			});
+
+			if ( tags ) {
+				this.set_tags(tags);
+			}
+		});
+
+	return $stubs;
+}
+
+$init_tag_displays.default_menu = 'x !';
+
+$(function(){
+	if ( fh_is_admin ) {
+		$init_tag_displays.default_menu = 'x ! # ## _ )';
+	}
+});
+
+
+function cached_user_tags( selector ){
+	return $(selector).
+		find('.tag-display.ready[context=user] span.tag').
+			map(function(){
+				return $(this).text();
+			}).
+			get();
+}
+
+function normalize_tag_menu_command( tag, op ){
+	if ( op == "x" ) {
+		return '-' + tag;
+	} else if ( tag.length > 1 && op.length == 1 && op == tag[0] ) {
+		return tag.slice(1);
+	} else if ( op != tag ) {
+		return op + tag;
+	} else {
+		return tag;
+	}
+}
+
+
+
+// Tags.pm doesn't automatically handle '!(nod|nix)'
+//	and requires (some) hand-holding to prevent an item from being tagged both nod and nix at once
+var nodnix_commands = {
+	'nod':		['nod', '-nix'],
+	'nix':		['nix', '-nod'],
+	'!nod':		['nix', '-nod'],
+	'!nix':		['nod', '-nix'],
+	'-nod':		['-nod'],
+	'-nix':		['-nix'],
+	'-!nod':	['-nix'],
+	'-!nix':	['-nod']
+};
+
+function normalize_nodnix( commands ){
+	return $.map(commands, function( cmd ){
+		return (cmd in nodnix_commands) ? nodnix_commands[cmd] : cmd;
+	});
+}
+
+// filters commands, returning a list 'normalized' (as per comment at 'nodnix_commands', above)
+// and omitting any "add" commands for tags in excludes, or "deactivate" commands for tags _not_ in excludes
+// commands is a list (string or array)
+// excludes is either a list or set of tags/commands to remove,
+//	or else a jQuery selector (DOM element, string selector, or jQuery wrapped list) under which
+//	exists a user tag list... we'll build the real exclusion list from that
+function normalize_tag_commands( commands, excludes ){
+
+	// want to iterate over commands, so ensure it is an array
+	commands = list_as_array(commands);
+	if ( !commands.length ) {
+		return [];
+	}
+
+	// beware, provide a complete list for excludes, or nothing at all,
+	// else -tag commands can be dropped on the floor
+
+	// want to repeatedly test for inclusion in excludes, so ensure excludes is a set
+	if ( excludes ) {
+		try {
+			// if excludes looks like a string
+			if ( excludes.split ) {
+				// and that string works as a jQuery selector
+				var $temp = $(excludes);
+				if ( $temp.length ) {
+					// treat it as such
+					excludes = $temp;
+				}
+				// otherwise a string is probably a space-separated command list
+			}
+
+			// if excludes is dom element or a jquery wrapped list...
+			if ( excludes.nodeType !== undefined || excludes.jquery !== undefined ) {
+				// ...caller means a list of the user tags within (returns an array)
+				excludes = cached_user_tags(excludes);
+			}
+
+			// if excludes is a list (string or array)...
+			if ( excludes.length !== undefined ) {
+				excludes = map_list_to_set(excludes);
+			}
+
+			// excludes should already be a set, let's make sure it's not empty
+			if ( !keys(excludes).length ) {
+				excludes = null;
+			}
+		} catch (e) {
+			excludes = null;
+		}
+	}
+
+	var filter_minus = true;
+	if ( !excludes ) {
+		filter_minus = false;
+		excludes = {};
+	}
+
+	function un( tag ){
+		return tag[0]=='-' ? tag.substring(1) : '-'+tag;
+	}
+
+	// .reverse(): process the commands from right to left
+	// so only the _last_ occurance is kept in case of duplicates
+	var already = {};
+	return $.map(commands.reverse(), function( cmd ){
+		if ( cmd &&
+			!(cmd in already) &&
+			!(cmd in excludes) &&
+			( !filter_minus ||
+				cmd[0] != '-' ||
+				un(cmd) in excludes ) ) {
+
+			already[ cmd ] = true;
+			already[ un(cmd) ] = true;
+			return cmd;
+		}
+	}).reverse();
+}
+
+
+function $position_context_display( $display ){
+	var RIGHT_PADDING = 18;
+
+	var $entry = $display.nearest_parent('[tag-server]');
+	var left_edge = $entry.offset().left;
+	var right_edge = left_edge + $entry.width() - RIGHT_PADDING;
+
+	var global_align = $related_trigger.offset().left;
+	global_align = Math.max(left_edge, global_align);
+
+	var need_minimal_fix = true;
+	if ( $display.nearest_parent(':hidden').length===0 ) {
+		try {
+			var display_width = $display.children('ul:first').width();
+			$display.css({
+				right: '',
+				width: display_width
+			});
+
+			global_align = Math.max(
+				left_edge,
+				Math.min(right_edge-display_width, global_align) );
+			var distance = global_align - $display.offset().left;
+			if ( distance ) {
+				$display.animate({left: '+='+distance});
+			}
+
+			need_minimal_fix = false;
+		} catch (e0) {
+		}
+	}
+
+	if ( need_minimal_fix ) {
+		try {
+			var BROKEN_NEGATIVE_MARGIN_CALCULATION = -10;
+
+			// we may not be visible, so can't trust offsetParent() on ourself
+			// better get it from our parent
+			var x_adjust = -$display.parent().offsetParent().offset().left;
+			$display.css({
+				left: global_align + x_adjust + BROKEN_NEGATIVE_MARGIN_CALCULATION,
+				right: right_edge + x_adjust
+			});
+		} catch (e1) {
+		}
+	}
+
+	return $display;
+}
+
+function $queue_reposition( $display, if_only_width ){
+	return $display.queue(function(){
+		$position_context_display($display, if_only_width).dequeue();
+	});
+}
+
+var gFocusedText;
+var $previous_context_trigger = $().filter();
+
+var tag_widget_fns = {
+
+	init: function(){
+		$init_tag_displays($('.tag-display-stub', this));
+
+		$(this).find('.tag-entry').
+				focus(function(event){
+					gFocusedText = this;
+				}).
+				blur(function(event){
+					if ( gFocusedText === this ) {
+						gFocusedText = null;
+					}
+				}).
+				keypress(function(event){
+					var ESC=27, SPACE=32;
+
+					var $this = $(this);
+					switch ( event.which || event.keyCode ) {
+						case ESC:
+							$this.val('');
+							return false;
+						case SPACE:
+							var $form = $this.parent();
+							setTimeout(function(){
+								$form.trigger("onsubmit");
+							}, 0);
+							return true;
+						default:
+							return true;
+					}
+				}).
+				autocomplete('/ajax.pl', {
+					loadingClass:		'working',
+					minChars:		3,
+					autoFill:		true,
+					max:			25,
+					extraParams: {
+						op:		'tags_list_tagnames'
+					}
+				}).
+				result(function(){
+					$(this).parent().trigger("onsubmit");
+				});
+		return this;
+	},
+
+
+	set_context: function( context, force ){
+		var widget = this;
+		if ( context ) {
+			if ( context == this._current_context &&
+				(!$previous_context_trigger.length ||
+					$related_trigger[0] === $previous_context_trigger[0]) && !force ) {
+				context = '';
+			} else {
+				if ( !(context in suggestions_for_context) && context in context_triggers ) {
+					context = (this._current_context != 'default') ? 'default' : '';
+				}
+
+			}
+		}
+
+		// cancel any existing timeout... the context to be hidden is going away
+		if ( this._context_timeout ) {
+			clearTimeout(this._context_timeout);
+			this._context_timeout = null;
+		}
+
+		// only have to set_tags on the display if the context really is changing
+		if ( context != this._current_context ) {
+			var context_tags = [];
+			if ( context && context in suggestions_for_context ) {
+				context_tags = list_as_array(suggestions_for_context[context]);
+			}
+
+			var has_tags = context_tags.length !== 0;
+
+			$('.ready[context=related]', this)
+				.each(function(){
+					var display = this;
+					var $display = $(display);
+
+					var had_tags = $display.find('span.tag').length !== 0;
+
+					// animations are automatically queued...
+					if ( had_tags < has_tags ) {
+						$display.css('display', 'none');
+					} else if ( had_tags > has_tags ) {
+						$display.slideUp(400);
+					}
+					// ...when regular code needs to synchronize with animation
+					$display.queue(function(){
+						// I have to queue that code up myself
+						display.set_tags(context_tags, { classes: 'suggestion' });
+						if ( has_tags && widget.modify_context ) {
+							widget.modify_context(display, context);
+						}
+						$display.dequeue();
+					});
+					if ( has_tags ) {
+						$queue_reposition($display);
+						if ( !had_tags ) {
+							$queue_reposition($display.slideDown(400));
+						}
+					}
+				});
+
+			this._current_context = context;
+		} else if ( $previous_context_trigger.length &&
+			$previous_context_trigger[0] !== $related_trigger[0] ) {
+
+			$position_context_display($('.ready[context=related]', this));
+		}
+
+		$previous_context_trigger = $related_trigger;
+
+		// if there's a context to hide, and hiding on a timeout is requested...
+		if ( context && this.tag_widget_data.context_timeout ) {
+			this._context_timeout = setTimeout(function(){
+				widget.set_context();
+			}, this.tag_widget_data.context_timeout);
+		}
+
+		return this;
+	}
+
+}; // tag_widget_fns
+
+function $init_tag_widgets( $stubs, options ){
+	options = options || {};
+
+	$stubs
+		.each(function(){
+			var $this = $(this);
+
+			var init_data = $this.metadata({type:'attr', name:'init'});
+			$this.removeAttr('init');
+
+			var local_state = { tag_widget_data: {} };
+			if ( init_data.context_timeout ) {
+				local_state.tag_widget_data.context_timeout = init_data.context_timeout;
+			}
+
+			$.extend(
+				this,
+				tag_widget_fns,
+				local_state,
+				options ).
+				init();
+		}).
+		mapClass({'tag-widget-stub': 'tag-widget'});
+
+	return $stubs;
+}
+
+
+
+
+
+
+
+
+
+
+/*
+	'w'	warning
+	'u'	user tag
+	't'	top tag
+	's'	system tag
+	'd'	data type
+	'e'	editor tag ('hold', 'back', etc)
+	'f'	feedback tag ('error', 'dupe', etc)
+	'p'	private tag
+	't2'	topic
+	's1'	section
+	'y'	nod
+	'x'	nix
+	'bang'
+	'pound'
+	'paren'
+	'underscore'
+ */
+
+
+function update_class_map( css_class_map, css_class, tags ){
+	var sp_css_class = ' ' + css_class;
+
+	function update( tag ){
+		if ( tag in css_class_map ) {
+			css_class_map[tag] += sp_css_class;
+		} else {
+			css_class_map[tag] = css_class;
+		}
+	}
+
+	function update_from_set( key, value ){ update(key); }
+	function update_from_list(){ update(this); }
+
+	$.each(tags, (tags.length === undefined) ? update_from_set : update_from_list);
+}
+
+$(function(){
+	var data_types = [
+		'submission',
+		'journal',
+		'bookmark',
+		'feed',
+		'story',
+		'vendor',
+		'misc',
+		'comment',
+		'discussion',
+		'project'
+	];
+
+	context_triggers = map_list_to_set(data_types);
+
+
+	well_known_tags = {};
+	update_class_map(well_known_tags, 's1', YAHOO.slashdot.sectionTags);
+	update_class_map(well_known_tags, 't2', YAHOO.slashdot.topicTags);
+	update_class_map(well_known_tags, 'y p', ['nod', 'metanod']);
+	update_class_map(well_known_tags, 'x p', ['nix', 'metanix']);
+	update_class_map(well_known_tags, 'd', data_types);
+
+	if ( fh_is_admin ) {
+		update_class_map(well_known_tags, 'w p', ['signed', 'unsigned', 'signoff']);
+	}
+});
+
+var css_classes_for_prefix = {
+	'!': 'bang',
+	'#': 'pound',
+	')': 'descriptive',
+	'_': 'ignore',
+	'-': 'minus'
+};
+
+function static_css_classes_for( tag ){
+
+	var css_class = '';
+	var sep = '';
+
+	function include( expr ){
+		if ( expr ){
+			css_class += sep + expr;
+			sep = ' ';
+		}
+	}
+
+	include(well_known_tags[bare_tag(tag)]);
+	include(css_classes_for_prefix[ tag[0] ]);
+
+	return css_class;
+}
+
+var css_class_for_context = { user: 'u', top: 't', system: 's' };
+
+function recompute_css_classes( root ){
+	var already = {};
+	var computed_css_classes_for = {};
+
+	var $displays = $('.tag-display', root);
+
+	// Step 1: build one big dictionary mapping tag names to 'computed' css classes
+	// that is, classes we deduce from where a tag appears.  If a tag appears
+	// in the user tag-display, then every occurance of that tag will be styled
+	// to indicate that.
+
+	// So, for each of the big three (user, top, system) tag-displays; extract
+	// their tags, and update our css class map for that display
+	$displays.
+		filter('.ready[context]:not(.no-tags)').
+			each(function(){
+				var display = $(this).attr('context');
+				var css_class = css_class_for_context[display];
+
+				// css_class true for a display that exclusively gets one of the big three
+				// so: if it's one of the big three that we haven't yet seen...
+				if ( css_class && !already[display] ) {
+					update_class_map(
+						computed_css_classes_for,
+						css_class,
+
+						// build an array of all the tag names in this display
+						$('span.tag', this).map(function(){
+							return $(this).text();
+						}) );
+					already[display] = true;
+				}
+			});
+
+	// computed_css_classes_for now contains every tag in the user, top, and system displays
+	// (i.e., all tags that globally influence each other) and maps those
+	// tag names to strings containing a css class for each display in which
+	// the tag appeared, e.g., if 'hello' is in both the user and top tag
+	// displays, then computed_css_classes_for['hello'] == 'u t' (mod order)
+
+	// Step 2: for tags that are sections, topics, etc., add corresponding classes
+	$.each(computed_css_classes_for, function(k, v){
+		var static_css_classes = static_css_classes_for(k);
+		if ( static_css_classes ) {
+			computed_css_classes_for[k] += ' ' + static_css_classes;
+		}
+	});
+
+	// Step 3: find every tag span and apply the css classes we've calculated
+	$displays.
+		find('span.tag').
+			each(function(){ // for each tag
+				var $tag = $(this);
+				var tag = $tag.text();
+
+				var class_list = '';
+				if ( tag in computed_css_classes_for ) {
+					// we saw this tag, and know all the classes
+					class_list = computed_css_classes_for[tag];
+				} else {
+					// didn't see this tag on the global phase, so it has
+					// no 'computed' classes, but it _might_ still have static classes
+					// which we'll cache in case we see this tag again
+					var static_css_classes = (computed_css_classes_for[tag] = static_css_classes_for(tag));
+					if ( static_css_classes ) {
+						class_list = static_css_classes;
+					}
+				}
+
+				$tag.parent().setClass(class_list);
+			}).
+		end().
+		filter('[context=user]').
+			each(function(){ // for each display of user tags
+				var $this = $(this);
+				$this.toggleClassTo(
+					'no-visible-tags',
+					! $this.is(':has(li.u:not(.t,.s,.p,.minus))') );
+			});
+}
+
+function init_tagui_styles( $entries ){
+	$entries.each(function(){
+		recompute_css_classes(this);
+	});
+}

Modified: slashjp/trunk/plugins/Ajax/htdocs/preferences.pl
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/preferences.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/htdocs/preferences.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: preferences.pl,v 1.3 2008/02/12 23:40:20 entweichen Exp $
+# $Id$
 
 use strict;
 

Copied: slashjp/trunk/plugins/Ajax/templates/combined_tags;misc;default (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/templates/combined_tags;misc;default)
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/combined_tags;misc;default	                        (rev 0)
+++ slashjp/trunk/plugins/Ajax/templates/combined_tags;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,30 @@
+__section__
+default
+__description__
+Used to produce an easily parse-able, comprehensive list of tags, e.g., as
+needed by the tag widget.
+
+You supply vote_tags, user_tags, top_tags, and system_tags.
+
+In the output, the lists will be separated by newlines.  The tags within each
+list will be separated by whatever you used in the caller (hopefully spaces).
+Each list in the output will be prefixed with a header of the form '<category>',
+where category is 'vote', 'user', 'top', or 'system'.  As an empty list is
+meaningful, all four lists are always present and labeled.
+__title__
+Useless title to template
+__page__
+misc
+__lang__
+en_US
+__name__
+combined_tags
+__seclev__
+10000
+__template__
+<vote>[% vote_tags %]
+<user>[% user_tags %]
+<top>[% top_tags %]
+<system>[% system_tags %]
+__version__
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/edit_comment;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/edit_comment;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/edit_comment;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -22,12 +22,12 @@
 [% IF user.is_anon %]
 <div class="warning">
 	[% IF constants.allow_anonymous %]
-You are not logged in.  You can <a href=\"${gSkin.rootdir}/login.pl\">log
-in now</a>, or <a href="[% gSkin.rootdir %]/users.pl">Create an Account</a>.
-	[% ELSE %]
-You are not logged in.  You can <a href=\"${gSkin.rootdir}/login.pl\">log
+You are not logged in.  You can <a href="[% gSkin.rootdir %]/login.pl">log
 in now</a>, <a href="[% gSkin.rootdir %]/users.pl">Create an Account</a>,
 or post as <b>[% user.nickname | strip_literal %]</b>.
+	[% ELSE %]
+You are not logged in.  You can <a href="[% gSkin.rootdir %]/login.pl">log
+in now</a>, or <a href="[% gSkin.rootdir %]/users.pl">Create an Account</a>.
 	[% END %]
 </div>
 [% END %]
@@ -55,8 +55,7 @@
 				</div>
 			</div>
 			<div class="generalbody">
-				<p>If you have difficulty with this form, please use the <a href="[% gSkin.rootdir %]/comments.pl?op=Reply&amp;sid=[% sid %]&amp;pid=[% pid %]">old form</a>.</p>
-				<textarea wrap="virtual" name="postercomment_[% pid %]" id="postercomment_[% pid %]" rows="[% user.textarea_rows || constants.textarea_rows %]" cols="[% user.textarea_cols || constants.textarea_cols %]"></textarea>	
+				<textarea wrap="virtual" name="postercomment_[% pid %]" id="postercomment_[% pid %]" rows="[% user.textarea_rows || constants.textarea_rows %]" cols="[% user.textarea_cols || constants.textarea_cols %]"></textarea>
 			</div>
 		</div>
 		<div id="replyto_msg_[% pid %]" class="replyto_msg" style="display: none"></div>
@@ -83,4 +82,4 @@
 __seclev__
 1000
 __version__
-$Id: edit_comment;ajax;default,v 1.1 2008/02/28 21:39:31 pudge Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/hc_comment;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/hc_comment;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/hc_comment;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -26,4 +26,4 @@
 __seclev__
 1000
 __version__
-$Id: hc_comment;ajax;default,v 1.1 2008/03/25 18:46:24 pudge Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_admin;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_admin;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_admin;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -84,4 +84,4 @@
 __seclev__
 500
 __version__
-$Id: prefs_admin;ajax;default,v 1.1 2008/02/12 22:15:36 entweichen Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_authors;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_authors;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_authors;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -65,4 +65,4 @@
 __seclev__
 500
 __version__
-$Id: prefs_authors;ajax;default,v 1.1 2008/01/31 16:26:05 entweichen Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -46,6 +46,13 @@
                         </div>
                         <br>
 
+                        <input type="checkbox" id="d2_reverse_switch" name="d2_reverse_switch"[% constants.markup_checked_attribute IF user.d2_reverse_switch %] onclick="d2_reverse_shift = $('#d2_reverse_switch').attr('checked') ? 1 : 0">&nbsp;<b>Collapse Comments After Reading</b>&nbsp;<a href="#" onclick="displayModalPrefHelp('modalprefhelp_discussion_shift_key');" class="help">?</a>
+                        <br>
+                        <div id="modalprefhelp_discussion_shift_key" class="modalprefhelp" style="display: none;">
+                                Collapse a comment when you navigate away from it when using the <a href="http://slashdot.org/faq/com-mod.shtml#cm128">Discussion 2 keybindings</a>.
+                        </div>
+                        <br>
+
                         <div>
                         Retrieve [% comment_q_name = (user.is_subscriber || user.is_admin) ? 'd2_comment_q_all' : 'd2_comment_q';
                            comment_q = Slash.db.getDescriptions(comment_q_name);

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_home;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_home;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_home;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -165,4 +165,4 @@
 __seclev__
 500
 __version__
-$Id: prefs_home;ajax;default,v 1.1 2007/12/19 18:15:36 entweichen Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_main;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_main;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_main;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -72,4 +72,4 @@
 __seclev__
 500
 __version__
-$Id: prefs_main;ajax;default,v 1.3 2008/02/20 16:53:02 entweichen Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_sectional;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_sectional;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_sectional;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -103,4 +103,4 @@
 __seclev__
 500
 __version__
-$Id: prefs_sectional;ajax;default,v 1.1 2007/11/29 18:01:04 entweichen Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_slashboxes;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_slashboxes;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_slashboxes;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -87,4 +87,4 @@
 __seclev__
 500
 __version__
-$Id: prefs_slashboxes;ajax;default,v 1.2 2008/01/31 17:02:34 entweichen Exp $
+$Id$

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_user;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_user;ajax;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_user;ajax;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -119,4 +119,4 @@
 __seclev__
 500
 __version__
-$Id: prefs_user;ajax;default,v 1.1 2007/11/29 16:33:12 entweichen Exp $
+$Id$

Copied: slashjp/trunk/plugins/Ajax/templates/tag_display;misc;default (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/templates/tag_display;misc;default)
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/tag_display;misc;default	                        (rev 0)
+++ slashjp/trunk/plugins/Ajax/templates/tag_display;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,37 @@
+__section__
+default
+__description__
+This builds a tag-display
+
+context	        = what tags to programmatically insert, e.g., 'user', 'top'
+tags	        = array of initial tags
+label	        = optional display legend, e.g., "My Tags"
+class           = additional class(es)
+attributes      = additional attributes, e.g., 'stoid="247"'
+nomenu
+menu
+__title__
+Useless title to template
+__page__
+misc
+__lang__
+en_US
+__name__
+tag_display
+__seclev__
+10000
+__template__
+[% sep = '' -%]
+<div class="tag-display stub[% IF class %] [% class %][% END %]"
+	[%- IF context %] context="[% context %]"[% END -%]
+	[%- IF label %] label="[% label %]"[% END -%]
+	[%- IF nomenu %] nomenu="nomenu"[% ELSIF menu %] menu="[% menu %]"[% END -%]
+	[%- IF attributes %] [% attributes %][% END %]>
+	[%- IF tags.size -%]
+		[%- FOR t = tags -%]
+			[%- sep %][% t.split(':').0 -%]
+		[%- sep = ' '; END -%]
+	[%- END -%]
+</div>
+__version__
+$Id$

Copied: slashjp/trunk/plugins/Ajax/templates/tag_widget;misc;default (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Ajax/templates/tag_widget;misc;default)
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/tag_widget;misc;default	                        (rev 0)
+++ slashjp/trunk/plugins/Ajax/templates/tag_widget;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,52 @@
+__section__
+default
+__description__
+This builds a tag-widget bound to a containing firehose entry.
+
+item_id = the firehose id to which this widget will be bound
+__title__
+Useless title to template
+__page__
+misc
+__lang__
+en_US
+__name__
+tag_widget
+__seclev__
+10000
+__template__
+<div id="tag-widget-[% item_id %]" class="tag-widget stub">
+	[% IF user.is_admin && !user.firehose_usermode %]
+	<span class="admin-buttons">
+		<div class="note-wrapper[% IF !item.note %] no-note[% END %]">
+			<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="save" 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>
+		</div>
+		<span id="taghist-[% id %]"><a href="#" onclick="tagsHistory('[% id %]','firehose'); return false">History</a></span>
+	</span>
+	[% END %]
+	<div class="tags">
+		<div class="tagtitleclosed">
+			<a><span class="tagsheader">[+]</span></a>
+		</div>
+	</div>
+	<div class="tag-display-set train">
+		<div class="tag-display stub" context="user" label="My Tags"></div>
+		<div class="tag-display stub" context="top" label="Top Tags"></div>
+		<div class="tag-display stub" context="system" label="System Tags"></div>
+	</div>
+	<form class="tag-editor" onsubmit="form_submit_tags(this); return false">
+		<input class="tag-entry" type="text" size="10">
+		<span class="tag-server-busy"><img src="[% constants.imagedir %]/spinner2.gif"></span>
+	</form>
+	<div class="context-sensitive">
+		<div class="tag-display stub" context="related"></div>
+	</div>
+</div>
+__version__
+$Id$

Modified: slashjp/trunk/plugins/Blob/Blob.pm
===================================================================
--- slashjp/trunk/plugins/Blob/Blob.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Blob/Blob.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Blob;
 
@@ -12,11 +11,10 @@
 use MIME::Types;
 use Digest::MD5 'md5_hex';
 
-use vars qw($VERSION);
 use base 'Exporter';
 use base 'Slash::DB::Utility';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # When this plugin was first written, it used a hardcoded hash to
 # store MIME types.  Now we use the MIME::Types module.  But for

Modified: slashjp/trunk/plugins/Blob/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Blob/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Blob/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Blob',
-    'VERSION_FROM' => 'Blob.pm', # finds $VERSION
     'PM'	=> { 'Blob.pm' => '$(INST_LIBDIR)/Blob.pm' },
 );

Modified: slashjp/trunk/plugins/BlockProxyNet/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/BlockProxyNet/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/BlockProxyNet/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'BlockProxyNet',
-    'VERSION_FROM' => 'block_proxy_net.pl', # finds $VERSION
 );

Modified: slashjp/trunk/plugins/Bookmark/Bookmark.pm
===================================================================
--- slashjp/trunk/plugins/Bookmark/Bookmark.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Bookmark/Bookmark.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Bookmark;
 
@@ -32,9 +31,8 @@
 
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Utility::VERSION;
 
 sub createBookmark {
 	my($self, $data) = @_;
@@ -109,6 +107,3 @@
 
 Slash(3).
 
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/plugins/Bookmark/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Bookmark/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Bookmark/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Bookmark',
-    'VERSION_FROM' => 'Bookmark.pm', # finds $VERSION
     'PM'	=> { 'Bookmark.pm' => '$(INST_LIBDIR)/Bookmark.pm' },
 );

Modified: slashjp/trunk/plugins/Bookmark/bookmark.pl
===================================================================
--- slashjp/trunk/plugins/Bookmark/bookmark.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Bookmark/bookmark.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -54,9 +54,7 @@
 		my $tags = getObject('Slash::Tags');
 		my $tag_ar = $tags->getTagsByNameAndIdArrayref("urls", $url_id, { uid => $user->{uid} });
 		$tags_str = join ' ', sort map { $_->{tagname}} @$tag_ar;
-		
 	}
-	
 	my $reskey = getObject('Slash::ResKey');
 	my $rkey = $reskey->key('bookmark');
 	unless ($rkey->create) {
@@ -67,8 +65,8 @@
 			$options->{errors}{reskey} = $rkey->errstr;
 		}
 	}
-	print slashDisplay("bookmark", { 
-		fudgedurl	=> $fudgedurl, 
+	print slashDisplay("bookmark", {
+		fudgedurl	=> $fudgedurl,
 		errors		=> $options->{errors},
 		tags_string	=> $tags_str
 	}, { Return => 1 });
@@ -125,11 +123,14 @@
 		if ($constants->{plugin}{FireHose}) {
 			my $firehose = getObject("Slash::FireHose");
 			my $the_bookmark = $bookmark->getBookmark($bookmark_id);
-			$firehose->createUpdateItemFromBookmark($bookmark_id, {
+			my $id = $firehose->createUpdateItemFromBookmark($bookmark_id, {
 				type		=> "bookmark",
 			});
+			if ($user->{is_admin} && $id) {
+				$firehose->setSectionTopicsFromTagstring($id, $form->{tags});
+			}
+
 		}
-					
 	}
 
 	my $tags = getObject('Slash::Tags');

Modified: slashjp/trunk/plugins/Console/Console.pm
===================================================================
--- slashjp/trunk/plugins/Console/Console.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Console/Console.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Console;
 
@@ -32,9 +31,8 @@
 
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Utility::VERSION;
 
 
 sub ajaxConsoleUpdate {
@@ -45,6 +43,7 @@
 	$html->{'storyadmin-content'}	= $admindb->showStoryAdminBox("", { contents_only => 1});
 	$html->{'performancebox-content'}	= $admindb->showPerformanceBox({ contents_only => 1});
 	$html->{'authoractivity-content'}	= $admindb->showAuthorActivityBox({ contents_only => 1});
+	$html->{'admintodo-wrap'}		= $admindb->showAdminTodo();
 	if (my $tagsdb = getObject('Slash::Tags')) {
 		$html->{'recenttagnames-content'} = $tagsdb->showRecentTagnamesBox({ contents_only => 1 });
 	}
@@ -61,7 +60,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/plugins/Console/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Console/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Console/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Console',
-    'VERSION_FROM' => 'Console.pm', # finds $VERSION
     'PM'	=> { 'Console.pm' => '$(INST_LIBDIR)/Console.pm' },
 );

Modified: slashjp/trunk/plugins/Console/console.pl
===================================================================
--- slashjp/trunk/plugins/Console/console.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Console/console.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -56,6 +56,7 @@
 	my $storyadmin 	= $admindb->showStoryAdminBox("");
 	my $perfbox	= $admindb->showPerformanceBox();
 	my $authorbox	= $admindb->showAuthorActivityBox();
+	my $admintodo	= $admindb->showAdminTodo();
 	my $firehosebox = "";
 	if ($constants->{plugin}{FireHose}) {
 		my $firehose = getObject("Slash::FireHose");

Modified: slashjp/trunk/plugins/Console/templates/display;console;default
===================================================================
--- slashjp/trunk/plugins/Console/templates/display;console;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Console/templates/display;console;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -13,6 +13,7 @@
 __template__
 <div id="slashboxes">
 	[% authorbox %]
+	<span id="admintodo-wrap"></span>
 	[% storyadmin %]
 	[% tagnamesbox %]
 	[% perfbox %]

Modified: slashjp/trunk/plugins/Daypass/Daypass.pm
===================================================================
--- slashjp/trunk/plugins/Daypass/Daypass.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Daypass/Daypass.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Daypass;
 
@@ -9,10 +8,9 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 use Apache::Cookie;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: And where would a giant nerd be? THE LIBRARY!
 

Modified: slashjp/trunk/plugins/Daypass/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Daypass/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Daypass/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Daypass',
-    'VERSION_FROM' => 'Daypass.pm', # finds $VERSION
     'PM'	=> { 'Daypass.pm' => '$(INST_LIBDIR)/Daypass.pm' },
 );

Modified: slashjp/trunk/plugins/Dilemma/Dilemma.pm
===================================================================
--- slashjp/trunk/plugins/Dilemma/Dilemma.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Dilemma/Dilemma.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 #
 # XXX Every place we have getDilemmaInfo() needs to (a) know the $trid
 # for the tournament and (b) change to getDilemmaTournamentInfo($trid)
@@ -11,13 +10,12 @@
 use strict;
 use Time::HiRes;
 use Safe;
-use Storable qw( freeze thaw dclone );
+use Storable qw( nfreeze thaw dclone );
 use Slash::Utility;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # ZOIDBERG: Friends! Help! A guinea pig tricked me!
 
@@ -434,7 +432,7 @@
 		delete $new_hr->{code};
 		delete $new_hr->{species_name};
 		if (defined $new_hr->{memory}) {
-			my $frozen_memory = freeze(\$new_hr->{memory});
+			my $frozen_memory = nfreeze(\$new_hr->{memory});
 			# Agents can't save memories longer than a certain
 			# limit;  those that try get BRAIN-WIPED.  Mwoohaha.
 			$frozen_memory = "" if length($frozen_memory) > 10_000;

Modified: slashjp/trunk/plugins/Dilemma/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Dilemma/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Dilemma/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Dilemma',
-    'VERSION_FROM' => 'Dilemma.pm', # finds $VERSION
     'PM'	=> { 'Dilemma.pm' => '$(INST_LIBDIR)/Dilemma.pm' },
 );

Modified: slashjp/trunk/plugins/Email/Email.pm
===================================================================
--- slashjp/trunk/plugins/Email/Email.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Email/Email.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,12 +1,10 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Email;
 
 use strict;
-use vars qw($VERSION);
 
 use Slash 2.003;	# require Slash 2.3
 
@@ -15,7 +13,7 @@
 
 use Slash::Utility;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 ########################################################
 

Modified: slashjp/trunk/plugins/Email/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Email/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Email/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Email',
-    'VERSION_FROM' => 'Email.pm', # finds $VERSION
     'PM'	=> {
     	'Email.pm'			=> '$(INST_LIBDIR)/Email.pm',
     },


Property changes on: slashjp/trunk/plugins/Email/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Email/templates/email_subj;email;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Events/Events.pm
===================================================================
--- slashjp/trunk/plugins/Events/Events.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Events/Events.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is released under the GPL.
 # Copyright 2001 by Brian Aker. See README
 # and COPYING for more information, or see http://software.tangent.org/.
-# $Id$
 
 package Slash::Events;
 
@@ -14,12 +13,10 @@
 use HTML::CalendarMonth;
 use HTML::AsSubs;
 
-use vars qw($VERSION @EXPORT);
-use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # On a side note, I am not sure if I liked the way I named the methods either.
 # -Brian


Property changes on: slashjp/trunk/plugins/Events/Events.pm
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Events/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Events/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Events/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Events',
-    'VERSION_FROM' => 'Events.pm', # finds $VERSION
     'PM'	=> { 'Events.pm' => '$(INST_LIBDIR)/Events.pm' },
 );


Property changes on: slashjp/trunk/plugins/Events/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Events/PLUGIN
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Events/templates/editevent;eventsadmin;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Events/templates/events;misc;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Events/templates/eventsadmin;misc;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Events/templates/index;eventsadmin;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Events/templates/listevents;eventsadmin;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/FAQ/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/FAQ/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FAQ/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,5 +4,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'FAQ',
-    'VERSION_FROM' => 'faq.shtml', # finds $VERSION
 );


Property changes on: slashjp/trunk/plugins/FAQ/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/FAQSlashdot/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/FAQSlashdot/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FAQSlashdot/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,5 +4,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'FAQSlashdot',
-    'VERSION_FROM' => 'faq/index.shtml', # finds $VERSION
 );


Property changes on: slashjp/trunk/plugins/FAQSlashdot/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/FAQSlashdot/faq/badges.shtml
===================================================================
--- slashjp/trunk/plugins/FAQSlashdot/faq/badges.shtml	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FAQSlashdot/faq/badges.shtml	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,7 +3,7 @@
 <html>
 <head>
         <title>Slashdot FAQ - Badges How-To</title>
-<!-- $Id: badges.shtml,v 1.2 2007/10/10 18:34:45 scc Exp $ -->
+<!-- $Id$ -->
 <!--#include virtual="/slashcssbase.inc"-->
 <!--#include virtual="/slashhead-gen-full.inc"-->
 

Modified: slashjp/trunk/plugins/FAQSlashdot/faq/editorial.shtml
===================================================================
--- slashjp/trunk/plugins/FAQSlashdot/faq/editorial.shtml	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FAQSlashdot/faq/editorial.shtml	2008-09-09 13:07:58 UTC (rev 742)
@@ -70,7 +70,7 @@
         </small></em></p>
 
 <h2><a name="ed150" id="ed150">How do I Ask Slashdot?</a></h2>
-        <p>Ask Slashdot is maintained by <a href="mailto:cliff****@slash*****">Cliff</a>. We prefer that you submit questions through <a href="http://slashdot.org/submit.pl">the submissions form</a>, selecting the section "Ask Slashdot" so we know to route the question to Cliff.</p>
+        <p>Ask Slashdot is maintained by the editorial staff. We prefer that you submit questions through <a href="http://slashdot.org/submit.pl">the submissions form</a>, selecting the section "Ask Slashdot" so we know to route the question appropriately.</p>
         <p><em><small>
                 Answered by: <a href="mailto:malda****@slash*****">CmdrTaco</a><br>
                 Last Modified: 10/29/00
@@ -96,7 +96,7 @@
         </small></em></p>
 
 <h2><a name="ed220" id="ed220">Why hasn't my story been accepted or rejected yet?</a></h2>
-        <p>Usually stories are examined within a few hours of their submission. Sometimes, however (and usually with stories that are submitted as Ask Slashdot or chosen as potential quickies), it might be weeks before it closes. Usually these things aren't time dependent... the answer won't change if the question is posed tomorrow or in a week, and since Ask Slashdot gets 5x more submissions then we use, there's some delay there. So be patient. You can <a href="mailto:cliff****@slash*****">mail Cliff</a> if you have a specific question about an Ask Slashdot.</p>
+        <p>Usually stories are examined within a few hours of their submission. Sometimes, however (and usually with stories that are submitted as Ask Slashdot or chosen as potential quickies), it might be weeks before it closes. Usually these things aren't time dependent... the answer won't change if the question is posed tomorrow or in a week, and since Ask Slashdot gets 5x more submissions then we use, there's some delay there. So be patient.</p>
         <p><em><small>
                 Answered by: <a href="mailto:malda****@slash*****">CmdrTaco</a><br>
                 Last Modified: 10/29/00
@@ -210,7 +210,6 @@
         <p><strong>Editor</strong> <a href="mailto:pudge****@slash*****">pudge****@slash*****</a></p>
         <h3>Ask Slashdot</h3>
         <p>If you're seeking advice from the Slashdot readership about jobs, computer hardware, software glitches, philosophical problems, etc, select the Ask Slashdot section. Regarding Legal Advice: When seeking advice on topics that touch on legal aspects, please remember that you should always be prepared to consult professional legal representation. It doesn't hurt to Ask Slashdot for pointers, and suggestions to save you some time, but Ask Slashdot should not be used in place of professional legal representation.</p>
-        <p><strong>Editor</strong> <a href="mailto:cliff****@slash*****">cliff****@slash*****</a></p>
         <h3>Book Reviews</h3>This section is for your original book reviews on (not necessarily) tech books, the more recent the better. If you're interested in submitting book reviews to slashdot, make sure you've read through the <a href="https://slashdot.org/book.review.guidelines.shtml">book review guidelines</a>, too.
         <p><strong>Editor</strong> <a href="mailto:timot****@slash*****">timot****@slash*****</a></p>
         <h3>BSD</h3>The BSD section hosts news about the various modern UNIXes derived from Berkeley's distribution (like Free, Open and NetBSD).

Modified: slashjp/trunk/plugins/FAQSlashdot/faq/firehose.shtml
===================================================================
--- slashjp/trunk/plugins/FAQSlashdot/faq/firehose.shtml	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FAQSlashdot/faq/firehose.shtml	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,7 +3,7 @@
 <html>
 <head>
         <title>Slashdot FAQ - Firehose</title>
-<!-- $Id: firehose.shtml,v 1.2 2007/10/04 16:42:37 scc Exp $ -->
+<!-- $Id$ -->
 <!--#include virtual="/slashcssbase.inc"-->
 <!--#include virtual="/slashhead-gen-full.inc"-->
 

Modified: slashjp/trunk/plugins/FAQSlashdot/faq/index.shtml
===================================================================
--- slashjp/trunk/plugins/FAQSlashdot/faq/index.shtml	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FAQSlashdot/faq/index.shtml	2008-09-09 13:07:58 UTC (rev 742)
@@ -25,7 +25,7 @@
         <ul>
                 <li><strong><a href="/faq/faq-meta.shtml#fm100">What is this document?</a></strong></li>
                 <li><strong><a href="/faq/faq-meta.shtml#fm200">I have a question that is not answered in this FAQ. What should I do?</a></strong></li>
-                <li><strong><a href="/faq/faq-meta.shtml#fm300">Who is responsible for the FAQ?</a></strong></li>
+                <li><strong><a href="/faq/faq-meta.shtml#fm300">Who is responsible for this FAQ?</a></strong></li>
         </ul><!-- Editorial -->
         <h2><strong><a href="/faq/editorial.shtml">Editorial</a></strong></h2>
         <ul>

Modified: slashjp/trunk/plugins/FireHose/FireHose.pm
===================================================================
--- slashjp/trunk/plugins/FireHose/FireHose.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/FireHose.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: FireHose.pm,v 1.176 2007/10/04 15:47:38 jamiemccarthy Exp $
 
 package Slash::FireHose;
 
@@ -40,9 +39,9 @@
 
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision: 1.176 $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
+
 sub createFireHose {
 	my($self, $data) = @_;
 	$data->{dept} ||= "";
@@ -103,12 +102,12 @@
 		my($itemid) = $self->sqlSelect("*", "firehose", "globjid=$globjid_q");
 		if ($itemid) {
 			my $introtext = balanceTags(strip_mode($journal->{article}, $journal->{posttype}), { deep_nesting => 1 });
-			$self->setFireHose($itemid, { 
-				introtext => $introtext, 
-				title => $journal->{description}, 
-				tid => $journal->{tid}, 
-				discussion => $journal->{discussion}, 
-				word_count => countWords($introtext) 
+			$self->setFireHose($itemid, {
+				introtext => $introtext,
+				title => $journal->{description},
+				tid => $journal->{tid},
+				discussion => $journal->{discussion},
+				word_count => countWords($introtext)
 			});
 			$self->setFireHose($itemid, { public => "no" }) if (getCurrentStatic("firehose_disable_to_show_publicized_journals") && $journal->{promotetype} eq "publicize");
 		} else {
@@ -131,8 +130,57 @@
 	return $colors;
 }
 
+sub createItemFromComment {
+	my($self, $cid) = @_;
+	my $comment = $self->getComment($cid);
+	my $text = $self->getCommentText($cid);
+	my $globjid = $self->getGlobjidCreate("comments", $cid);
+	my $score = constrain_score($comment->{points} + $comment->{tweak});
 
+	# Set initial popularity scores, but we'll be forcing a quick
+	# recalculation of them.
+	my($popularity, $editorpop, $neediness);
+	if ($score >= 3) {
+		$popularity = $self->getEntryPopularityForColorLevel(4);
+	} elsif ($score == 2) {
+		$popularity = $self->getEntryPopularityForColorLevel(5);
+	} elsif ($score >= 0) {
+		$popularity = $self->getEntryPopularityForColorLevel(6);
+	} else {
+		$popularity = $self->getEntryPopularityForColorLevel(7);
+	}
+	$editorpop = $self->getEntryPopularityForColorLevel(5);
+	$neediness = $self->getEntryPopularityForColorLevel(5);
 
+	my $data = {
+		uid		=> $comment->{uid},
+		public		=> "yes",
+		title		=> $comment->{subject},
+		introtext	=> $text,
+		ipid		=> $comment->{ipid},
+		subnetid 	=> $comment->{subnetid},
+		type		=> "comment",
+		srcid		=> $comment->{cid},
+		popularity	=> $popularity,
+		editorpop	=> $editorpop,
+		globjid		=> $globjid,
+		discussion	=> $comment->{sid},
+	};
+	my $fhid = $self->createFireHose($data);
+
+	my $tagboxdb = getObject('Slash::Tagbox');
+	if ($tagboxdb) {
+		for my $tbname (qw( FHPopularity FHEditorPop CommentScoreReason )) {
+			my $tagbox = $tagboxdb->getTagboxes($tbname);
+			next unless $tagbox;
+			$tagboxdb->forceFeederRecalc($tagbox->{tbid}, $globjid);
+		}
+	}
+
+	return $fhid;
+}
+
+
 sub createItemFromJournal {
 	my($self, $id) = @_;
 	my $user = getCurrentUser();
@@ -186,6 +234,7 @@
 	my $url_globjid = $self->getGlobjidCreate("urls", $bookmark->{url_id});
 	my $type = $options->{type} || "bookmark";
 	my($count) = $self->sqlCount("firehose", "globjid=$url_globjid");
+	my $firehose_id;
 	my $popularity = defined $options->{popularity}
 		? $options->{popularity}
 		: $type eq "feed"
@@ -212,12 +261,12 @@
 		};
 		$data->{introtext} = $options->{introtext} if $options->{introtext};
 		if ($type eq "feed") {
-			my $feed = $bookmark_db->getBookmarkFeedByUid($bookmark->{uid});	
+			my $feed = $bookmark_db->getBookmarkFeedByUid($bookmark->{uid});
 			if ($feed && $feed->{feedname}) {
-				$data->{srcname} = $feed->{feedname};	
+				$data->{srcname} = $feed->{feedname};
 			}
 		}
-		my $firehose_id = $self->createFireHose($data);
+		$firehose_id = $self->createFireHose($data);
 		if ($firehose_id && $type eq "feed") {
 			my $discussion_id = $self->createDiscussion({
 				uid		=> 0,
@@ -231,8 +280,7 @@
 					discussion	=> $discussion_id,
 				});
 			}
-			
-		}		
+		}
 
 		if (!isAnon($bookmark->{uid})) {
 			my $constants = getCurrentStatic();
@@ -245,6 +293,7 @@
 			});
 		}
 	}
+	return $firehose_id;
 }
 
 sub createItemFromSubmission {
@@ -290,6 +339,61 @@
 
 }
 
+sub createItemFromProject {
+	my($self, $id) = @_;
+	my $constants = getCurrentStatic();
+	my $proj = $self->getProject($id);
+	my $globjid = $self->getGlobjidCreate("projects", $proj->{id});
+	my $midpop = $self->getEntryPopularityForColorLevel(5);
+
+	my $data = {
+		uid		=> $proj->{uid},
+		title		=> $proj->{textname},
+		srcid		=> $proj->{id},
+		type		=> "project",
+		url_id		=> $proj->{url_id},
+		globjid		=> $globjid,
+		srcname		=> $proj->{srcname},
+		introtext 	=> $proj->{description},
+		public		=> "yes",
+		editorpop	=> $midpop,
+		popularity	=> $midpop,
+		createtime	=> $proj->{createtime}
+	};
+	my $firehose_id = $self->createFireHose($data);
+	my $discussion_id = $self->createDiscussion({
+		uid		=> 0,
+		kind		=> 'project',
+		title		=> $proj->{textname},
+		commentstatus	=> 'logged_in',
+		url		=> "$constants->{rootdir}/firehose.pl?op=view&id=$firehose_id"
+	});
+
+	if ($discussion_id) {
+		$self->setFireHose($firehose_id, {
+			discussion	=> $discussion_id,
+		});
+	}
+	return $firehose_id;
+}
+
+sub updateItemFromProject {
+	my($self, $id);
+	my $proj = $self->getProject($id);
+	if ($proj && $proj->{id}) {
+		my $item = $self->getFireHoseByTypeSrcid("projects", $proj->{id});
+		if ($item && $item->{id}) {
+			my $data = {
+				uid		=> $proj->{uid},
+				url_id		=> $proj->{url_id},
+				title 		=> $proj->{textname},
+				introtext 	=> $proj->{description},
+				createtime	=> $proj->{createtime}
+			};
+			$self->setFireHose($item->{id}, $data);
+		}
+	}
+}
 sub updateItemFromStory {
 	my($self, $id) = @_;
 	my $constants = getCurrentStatic();
@@ -316,8 +420,14 @@
 				body_length	=> $story->{body_length},
 				word_count	=> $story->{word_count},
 				thumb		=> $story->{thumb},
-				
 			};
+			if(defined $story->{mediatype}) {
+				if(!$story->{mediatype}) {
+					$data->{mediatype} = "none";
+				} else {
+					$data->{mediatype} = $story->{mediatype};
+				}
+			}
 			$self->setFireHose($id, $data);
 		}
 	}
@@ -357,6 +467,13 @@
 			discussion	=> $story->{discussion},
 			thumb		=> $story->{thumb},
 		};
+		if(defined $story->{mediatype}) {
+			if(!$story->{mediatype}) {
+				$data->{mediatype} = "none";
+			} else {
+				$data->{mediatype} = $story->{mediatype};
+			}
+		}
 		$self->createFireHose($data);
 	}
 }
@@ -389,7 +506,7 @@
 	$options->{limit} += $options->{more_num} if $options->{more_num};
 
 	my $fetch_size = $options->{limit};
-	if ($options->{orderby} eq "createtime") {
+	if ($options->{orderby} && $options->{orderby} eq "createtime") {
 		$fetch_extra = 1;
 		$fetch_size++;
 	}
@@ -535,10 +652,16 @@
 		my $st_q  = $self->sqlQuote(timeCalc($options->{startdate}, '%Y-%m-%d %T', -$user->{off_set}));
 
 		if ($options->{startdate}) {
-			push @where, "createtime >= $st_q";
 
 			if ($options->{duration} && $options->{duration} >= 0 ) {
+				push @where, "createtime >= $st_q";
 				push @where, "createtime <= DATE_ADD($st_q, INTERVAL $dur_q DAY)";
+			} elsif ($options->{duration} == -1) {
+				if ($options->{orderdir} eq "ASC") {
+					push @where, "createtime >= $st_q";
+				} else {
+					my $end_q = $self->sqlQuote(timeCalc("$options->{startdate} 23:59:59", '%Y-%m-%d %T', -$user->{off_set}));				   push @where, "createtime <= $end_q";
+				}
 			}
 		} elsif (defined $options->{duration} && $options->{duration} >= 0) {
 			push @where, "createtime >= DATE_SUB(NOW(), INTERVAL $dur_q DAY)";
@@ -711,9 +834,9 @@
 	my $where = join ' AND ', @$where_ar, "createtime $it_cmp $i_time_q", "createtime $bt_cmp $border_time_q";
 
 	my $day_count = $self->sqlSelect("count(*)", $tables, $where, $other);
-	
-	my $day_labels = getOlderDaysFromDay($item_day, 0, 0, { skip_add_today => 1, show_future_days => 1 });
 
+	my $day_labels = getOlderDaysFromDay($item_day, 0, 0, { skip_add_today => 1, show_future_days => 1, force => 1 });
+
 	return($day_labels->[0]->[0], $day_labels->[0]->[1], $day_count);
 }
 
@@ -739,26 +862,30 @@
 	return {} if @$globjs < 1;
 	my $uid_q = $self->sqlQuote($uid);
 	my $glob_str = join ",", map { $self->sqlQuote($_) } @$globjs;
-	
+
 	my $upvote   = $constants->{tags_upvote_tagname}   || 'nod';
 	my $downvote = $constants->{tags_downvote_tagname} || 'nix';
 
+	my $metaup =   "metanod";
+	my $metadown = "metanix";
+
 	my $tags = getObject("Slash::Tags", { db_type => "reader" });
 	my $upid = $tags->getTagnameidCreate($upvote);
 	my $dnid = $tags->getTagnameidCreate($downvote);
+	my $metaupid = $tags->getTagnameidCreate($metaup);
+	my $metadnid = $tags->getTagnameidCreate($metadown);
 
 	my $results = $self->sqlSelectAllKeyValue(
 		"globjid,tagnameid",
-		"tags", 
+		"tags",
 		"globjid IN ($glob_str) AND inactivated IS NULL
-		 AND uid = $uid_q AND tagnameid IN ($upid,$dnid)"
+		 AND uid = $uid_q AND tagnameid IN ($upid,$dnid,$metaupid,$metadnid)"
 	);
 
 	foreach (keys %$results) {
-		$results->{$_} = "up" if $results->{$_} == $upid;
-		$results->{$_} = "down" if $results->{$_} == $dnid;
+		$results->{$_} = "up" if $results->{$_} == $upid || $results->{$_} == $metaupid;
+		$results->{$_} = "down" if $results->{$_} == $dnid || $results->{$_} == $metadnid;
 	}
-	
 	return $results;
 }
 
@@ -799,9 +926,10 @@
 	# instead.  Firehose notes are/were designed to never be undef,
 	# the empty string instead.
 	$answer->{note} = $self->getGlobjAdminnote($answer->{globjid}) || '';
-	
+
 	if ($mcd && $answer->{title}) {
-		my $item = $mcd->set("$mcdkey:$id", $answer);
+		my $exptime = $constants->{firehose_memcached_exptime} || 600;
+		$mcd->set("$mcdkey:$id", $answer, $exptime);
 	}
 
 	return $answer;
@@ -931,10 +1059,14 @@
 	if ($user->{is_admin}) {
 		$firehose->setFireHoseSession($item->{id});
 	}
+
+	my $tags = getObject("Slash::Tags", { db_type => 'reader' })->setGetCombinedTags($id, 'firehose');
 	my $data = {
 		item		=> $item,
 		mode		=> "bodycontent",
-		tags_top	=> $tags_top,
+		tags_top	=> $tags_top,		# old-style
+		top_tags	=> $tags->{top},	# new-style
+		system_tags	=> $tags->{'system'},	# new-style
 	};
 
 	my $slashdb = getCurrentDB();
@@ -993,7 +1125,7 @@
 				private	=> 	1
 			});
 		}
-		
+
 		if ($item->{type} eq "submission") {
 			if ($item->{srcid}) {
 				my $n_q = $self->sqlQuote($item->{srcid});
@@ -1048,29 +1180,17 @@
 	});
 }
 
-sub ajaxFireHoseSetOptions {
-	my($slashdb, $constants, $user, $form, $options) = @_;
-	$options->{content_type} = 'application/json';
-	my $firehose = getObject("Slash::FireHose");
-	my $opts = $firehose->getAndSetOptions();
 
-	$firehose->createSettingLog({ 
-		uid => $user->{uid}, 
-		name => $form->{setting_name}, 
-		value => $form->{$form->{setting_name}}, 
-		"-ts" => "NOW()"}
-	);
+sub genSetOptionsReturn {
+	my($slashdb, $constants, $user, $form, $options, $opts) = @_;
+	my $data = {};
+	$data->{html}->{fhtablist} = slashDisplay("firehose_tabs", { nodiv => 1, tabs => $opts->{tabs}, options => $opts, section => $form->{section}  }, { Return => 1});
+	$data->{html}->{fhoptions} = slashDisplay("firehose_options", { nowrapper => 1, options => $opts }, { Return => 1});
+	$data->{html}->{fhadvprefpane} = slashDisplay("fhadvprefpane", { options => $opts }, { Return => 1});
 
-	my $html = {};
-	$html->{fhtablist} = slashDisplay("firehose_tabs", { nodiv => 1, tabs => $opts->{tabs}, options => $opts, section => $form->{section}  }, { Return => 1});
-	$html->{fhoptions} = slashDisplay("firehose_options", { nowrapper => 1, options => $opts }, { Return => 1});
-	$html->{fhadvprefpane} = slashDisplay("fhadvprefpane", { options => $opts }, { Return => 1});
-
-	my $values = {};
-	$values->{'firehose-filter'} = $opts->{fhfilter};
-	my $eval_last = "";
+	$data->{value}->{'firehose-filter'} = $opts->{fhfilter};
 	if ($form->{tab} || $form->{tabtype}) {
-		$eval_last = "firehose_slider_set_color('$opts->{color}')";
+		$data->{eval_last} = "firehose_slider_set_color('$opts->{color}');";
 	}
 
 	my $eval_first = "";
@@ -1085,15 +1205,26 @@
 		if ($o eq 'more_num') {
 			$value ||= 0;
 		}
-		$eval_first .= "firehose_settings.$o = " . Data::JavaScript::Anon->anon_dump("$value") . "; ";
+		$data->{eval_first} .= "firehose_settings.$o = " . Data::JavaScript::Anon->anon_dump("$value") . "; ";
 	}
+	return $data;
+}
 
-	return Data::JavaScript::Anon->anon_dump({
-		html		=> $html,
-		value		=> $values,
-		eval_first	=> $eval_first,
-		eval_last	=> $eval_last
-	});
+sub ajaxFireHoseSetOptions {
+	my($slashdb, $constants, $user, $form, $options) = @_;
+	$options->{content_type} = 'application/json';
+	my $firehose = getObject("Slash::FireHose");
+	my $opts = $firehose->getAndSetOptions();
+
+	$firehose->createSettingLog({
+		uid => $user->{uid},
+		name => $form->{setting_name},
+		value => $form->{$form->{setting_name}},
+		"-ts" => "NOW()"}
+	);
+
+	my $data = genSetOptionsReturn($slashdb, $constants, $user, $form, $options, $opts);
+	return Data::JavaScript::Anon->anon_dump($data);
 }
 
 sub ajaxSaveNoteFirehose {
@@ -1138,7 +1269,7 @@
 			my $uid_q = $slashdb->sqlQuote($user->{uid});
 			my $tabid_q = $slashdb->sqlQuote($tabid);
 			my $tabname_q = $slashdb->sqlQuote($tabname);
-		
+
 			$slashdb->sqlDelete("firehose_tab", "uid=$uid_q and tabname=$tabname_q and tabid!=$tabid_q");
 			$slashdb->sqlUpdate("firehose_tab", { tabname => $tabname }, "tabid=$tabid_q");
 			$slashdb->setUser($user->{uid}, { last_fhtab_set => $slashdb->getTime() });
@@ -1186,9 +1317,18 @@
 	my $newtagspreloadtext = join ' ', @newtagspreload;
 	#print STDERR "ajaxGetUserFirehose $newtagspreloadtext\n\n";
 
-	return slashDisplay($form->{nodnix} ? 'tagsnodnixuser' : 'tagsfirehosedivuser', {
+	my $template;
+	if ( $form->{no_markup} ) {
+		$template = 'combined_tags';
+	} elsif ( $form->{nodnix} ) {
+		$template = 'tagsnodnixuser';
+	} else {
+		$template = 'tagsfirehosedivuser';
+	}
+
+	return slashDisplay($template, {
 		id =>		$id,
-		newtagspreloadtext =>	$newtagspreloadtext,
+		user_tags =>	$newtagspreloadtext,
 	}, { Return => 1 });
 }
 
@@ -1210,8 +1350,11 @@
 
 sub ajaxFireHoseGetUpdates {
 	my($slashdb, $constants, $user, $form, $options) = @_;
+	my $gSkin = getCurrentSkin();
 	my $start = Time::HiRes::time();
 
+	slashProfInit();
+
 	my $update_data = { removals => 0, items => 0, updates => 0, new => 0 };
 
 	$options->{content_type} = 'application/json';
@@ -1223,7 +1366,9 @@
 	my %ids = map { $_ => 1 } @ids;
 	my %ids_orig = ( %ids ) ;
 	my $opts = $firehose->getAndSetOptions({ no_set => 1 });
+	slashProf("firehose_update_gfe");
 	my($items, $results, $count, $future_count, $day_num, $day_label, $day_count) = $firehose_reader->getFireHoseEssentials($opts);
+	slashProf("","firehose_update_gfe");
 	my $num_items = scalar @$items;
 	my $future = {};
 	my $globjs = [];
@@ -1235,11 +1380,11 @@
 			$base_page = "users.pl";
 		}
 	}
-	
+
 	$update_data->{items} = scalar @$items;
 
 	foreach (@$items) {
-		push @$globjs, $_->{globjid} if $_->{globjid} 
+		push @$globjs, $_->{globjid} if $_->{globjid}
 	}
 
 
@@ -1261,7 +1406,13 @@
 	my $mode = $opts->{mode};
 	my $curmode = $opts->{mode};
 	my $mixed_abbrev_pop = $firehose->getMinPopularityForColorLevel(1);
+	my $vol = $firehose->getSkinVolume($gSkin->{skid});
+	$vol->{story_vol} ||= 0;
+	if ($vol->{story_vol} < 25) {
+		$mixed_abbrev_pop = $firehose->getMinPopularityForColorLevel(3);
+	}
 
+
 	foreach (@$items) {
 		if ($opts->{mixedmode}) {
 			$curmode = "full";
@@ -1298,7 +1449,19 @@
 				push @$updates, ["add", $_->{id}, slashDisplay("daybreak", { options => $opts, cur_day => $_->{day}, last_day => $_->{last_day}, id => "firehose-day-$_->{day}", fh_page => $base_page }, { Return => 1, Page => "firehose" }) ];
 			} else {
 				$update_data->{new}++;
-				push @$updates, ["add", $_->{id}, slashDisplay("dispFireHose", { mode => $curmode, item => $item, tags_top => $tags_top, vote => $votes->{$item->{globjid}}, options => $opts }, { Return => 1, Page => "firehose" })];
+				my $tags = getObject("Slash::Tags", { db_type => 'reader' })->setGetCombinedTags($_->{id}, 'firehose');
+				my $data = {
+					mode => $curmode,
+					item => $item,
+					tags_top => $tags_top,			# old-style
+					top_tags => $tags->{top},		# new-style
+					system_tags => $tags->{'system'},	# new-style
+					vote => $votes->{$item->{globjid}},
+					options => $opts
+				};
+				slashProf("firehosedisp");
+				push @$updates, ["add", $_->{id}, $firehose->dispFireHose($item, $data) ];
+				slashProf("","firehosedisp");
 			}
 			$added->{$_->{id}}++;
 		}
@@ -1323,9 +1486,9 @@
 	if (scalar (keys %$next_to_old) == 1) {
 		my ($key) = keys %$next_to_old;
 		$target_pos = $pos->{$key};
-		
+
 	}
-	
+
 	@$updates  = sort {
 		$next_to_old->{$a->[1]} <=> $next_to_old->{$b->[1]} ||
 		abs($pos->{$b->[1]} - $target_pos) <=> abs($pos->{$a->[1]} - $target_pos);
@@ -1335,12 +1498,12 @@
 		push @$updates, ["remove", $_, ""];
 		$update_data->{removals}++;
 	}
-	
-	my $firehose_more_data = { 
-		future_count => $future_count, 
+
+	my $firehose_more_data = {
+		future_count => $future_count,
 		options => $opts,
 		day_num	=> $day_num,
-		day_label => $day_label, 
+		day_label => $day_label,
 		day_count => $day_count,
 		contentsonly => 0,
 	};
@@ -1369,6 +1532,9 @@
 		search_results	=> $results
 	}, { Return => 1 });
 
+	my $recent = $slashdb->getTime({ add_secs => "-300"});
+	$update_time = $recent if $recent gt $update_time;
+
 	$html->{local_last_update_time} = timeCalc($slashdb->getTime(), "%H:%M");
 	$html->{filter_text} = "Filtered to ".strip_literal($opts->{color})." '".strip_literal($opts->{fhfilter})."'";
 	$html->{gmt_update_time} = " (".timeCalc($slashdb->getTime(), "%H:%M", 0)." GMT) " if $user->{is_admin};
@@ -1384,15 +1550,17 @@
 		future		=> $future,
 	});
 	my $reskey_dump = "";
+	my $update_time_dump;
 	my $reskey = getObject("Slash::ResKey");
 	my $user_rkey = $reskey->key('ajax_user_static', { no_state => 1 });
 	$reskey_dump .= "reskey_static = '" . $user_rkey->reskey() . "';\n" if $user_rkey->create();
 
 	my $duration = Time::HiRes::time() - $start;
 	my $more_num = $options->{more_num} || 0;
-	
-	my $retval =  "$data_dump\n$reskey_dump";
 
+	$update_time_dump = "update_time= ".Data::JavaScript::Anon->anon_dump($update_time);
+	my $retval =  "$data_dump\n$reskey_dump\n$update_time_dump";
+
 	my $updatelog = {
 		uid 		=> $user->{uid},
 		new_count 	=> $update_data->{new},
@@ -1404,23 +1572,28 @@
 		bytes 		=> length($retval)
 	};
 	$firehose->createUpdateLog($updatelog);
+	slashProfEnd();
 
 	return $retval;
 
 }
 
 sub firehose_vote {
-	my($self, $id, $uid, $dir) = @_;
-
-	my $tag; 
+	my($self, $id, $uid, $dir, $meta) = @_;
+	my $tag;
 	my $constants = getCurrentStatic();
 	my $tags = getObject('Slash::Tags');
 	my $item = $self->getFireHose($id);
 	return if !$item;
-	
+
 	my $upvote   = $constants->{tags_upvote_tagname}   || 'nod';
 	my $downvote = $constants->{tags_downvote_tagname} || 'nix';
-	
+
+	if ($meta) {
+		$upvote = "metanod";
+		$downvote = "metanix";
+	}
+
 	if ($dir eq "+") {
 		$tag = $upvote;
 	} elsif ($dir eq "-") {
@@ -1445,11 +1618,12 @@
 	my $firehose = getObject('Slash::FireHose');
 	my $item = $firehose->getFireHose($id);
 	my $tags = getObject('Slash::Tags');
+	my $meta = $form->{meta};
 
 	my($table, $itemid) = $tags->getGlobjTarget($item->{globjid});
 
-	$firehose->firehose_vote($id, $user->{uid}, $form->{dir});
-	
+	$firehose->firehose_vote($id, $user->{uid}, $form->{dir}, $meta);
+
 	my $now_tags_ar = $tags->getTagsByNameAndIdArrayref($table, $itemid,
 		{ uid => $user->{uid}, include_private => 1 });
 	my $newtagspreloadtext = join ' ', sort map { $_->{tagname} } @$now_tags_ar;
@@ -1461,6 +1635,10 @@
 	#$html->{"updown-$id"} = "Voted $votetype";
 	$value->{"newtags-$id"} = $newtagspreloadtext;
 
+	if ($user->{is_admin}) {
+		$firehose->setFireHoseSession($id, "rating");
+	}
+
 	return Data::JavaScript::Anon->anon_dump({
 		html	=> $html,
 		value	=> $value
@@ -1494,7 +1672,7 @@
 
 	my $retval = slashDisplay('tagsfirehosedivuser', {
 		id =>		$id,
-		newtagspreloadtext =>	$newtagspreloadtext,
+		content =>	$newtagspreloadtext,
 	}, { Return => 1 });
 
 #print STDERR scalar(localtime) . " ajaxCreateForFirehose 4 for id=$id tagnames='@tagnames' newtagspreloadtext='$newtagspreloadtext' returning: $retval\n";
@@ -1572,7 +1750,8 @@
 sub setSectionTopicsFromTagstring {
 	my($self, $id, $tagstring) = @_;
 	my $constants = getCurrentStatic();
-
+	
+	print STDERR "sstft $id: $tagstring\n";
 	my @tags = split(/\s+/, $tagstring);
 	my $data = {};
 
@@ -1611,10 +1790,11 @@
 
 sub setFireHose {
 	my($self, $id, $data) = @_;
+	my $constants = getCurrentStatic();
 	return undef unless $id && $data;
 	return 0 if !%$data;
 	my $id_q = $self->sqlQuote($id);
-	
+
 	my $mcd = $self->getMCD();
 	my $mcdkey;
 	if ($mcd) {
@@ -1655,8 +1835,13 @@
 	$rows += $self->sqlUpdate('firehose_text', $text_data, "id=$id_q") if keys %$text_data;
 #{ use Data::Dumper; my $dstr = Dumper($text_data); $dstr =~ s/\s+/ /g; print STDERR "setFireHose B rows=$rows for id=$id_q data: $dstr\n"; }
 
-	if ($mcd) {
+	if ($mcd && $constants->{firehose_mcd_disp}) {
 		 $mcd->delete("$mcdkey:$id", 3);
+		 my $keys = $self->genFireHoseMCDAllKeys($id);
+		 foreach (@$keys) {
+			$mcd->delete($_, 3);
+		 }
+
 	}
 
 	my $searchtoo = getObject('Slash::SearchToo');
@@ -1670,20 +1855,79 @@
 	return $rows;
 }
 
+
+# This generates the key for memcaching dispFireHose results
+# if no key is returned no caching or fetching from cache will
+# take place
+
+sub genFireHoseMCDKey {
+	my($self, $id, $options) = @_;
+	my $gSkin = getCurrentSkin();
+	my $user = getCurrentUser();
+	my $form = getCurrentForm();
+	my $constants = getCurrentStatic();
+
+	my $mcd = $self->getMCD();
+	my $mcdkey;
+
+	return if $gSkin->{skid} != $constants->{mainpage_skid};
+	return if !$constants->{firehose_mcd_disp};
+
+	if ($mcd && !$options->{nodates} && !$options->{nobylines} && !$options->{nocolors} && !$options->{nothumbs} && !$form->{skippop} && !$form->{index} && !$options->{vote} && !$user->{is_admin}) {
+		$mcdkey = "$self->{_mcd_keyprefix}:dispfirehose-$options->{mode}:$id";
+	}
+	return $mcdkey;
+
+}
+
+sub genFireHoseMCDAllKeys {
+	my($self, $id) = @_;
+	my $keys = [];
+	my $mcd = $self->getMCD();
+	my $mcdkey;
+	if ($mcd) {
+		foreach my $mode (qw(full fulltitle)) {
+			push @$keys, "$self->{_mcd_keyprefix}:dispfirehose-$mode:$id";
+		}
+	}
+	return $keys;
+}
+
+
 sub dispFireHose {
 	my($self, $item, $options) = @_;
 	$options ||= {};
+	my $mcd = $self->getMCD();
+	my $mcdkey;
+	if ($mcd) {
+		$mcdkey = $self->genFireHoseMCDKey($item->{id}, $options);
+		my $cached;
+		if ($mcdkey) {
+			$cached = $mcd->get("$mcdkey");
+		}
+		return $cached if $cached;
+	}
 
-	slashDisplay('dispFireHose', {
+	my $retval = slashDisplay('dispFireHose', {
 		item			=> $item,
 		mode			=> $options->{mode},
-		tags_top		=> $options->{tags_top},
+		tags_top		=> $options->{tags_top},	# old-style
+		top_tags		=> $options->{top_tags},	# new-style
+		system_tags		=> $options->{system_tags},	# new-style
 		options			=> $options->{options},
 		vote			=> $options->{vote},
 		bodycontent_include	=> $options->{bodycontent_include},
 		nostorylinkwrapper	=> $options->{nostorylinkwrapper},
 		view_mode		=> $options->{view_mode}
 	}, { Page => "firehose",  Return => 1 });
+
+	if ($mcd) {
+		$mcdkey = $self->genFireHoseMCDKey($item->{id}, $options);
+		if ($mcdkey) {
+			$mcd->set($mcdkey, $retval, 180);
+		}
+	}
+	return $retval;
 }
 
 sub getMemoryForItem {
@@ -1756,8 +2000,8 @@
 	$opts 	        ||= {};
 	my $options 	= {};
 
-	my $types = { feed => 1, bookmark => 1, submission => 1, journal => 1, story => 1, vendor => 1, misc => 1 }; 
-	my $tabtypes = { tabsection => 1, tabpopular => 1, tabrecent => 1, tabuser => 1, aretama => 1 };
+	my $types = { feed => 1, bookmark => 1, submission => 1, journal => 1, story => 1, vendor => 1, misc => 1, comment => 1, project => 1 }; 
+	my $tabtypes = { tabsection => 1, tabpopular => 1, tabrecent => 1, tabuser => 1, metamod => 1, aretama => 1 };
 	
 	my $tabtype = '';
 	$tabtype = $form->{tabtype} if $form->{tabtype} && $tabtypes->{ $form->{tabtype} };
@@ -1825,8 +2069,8 @@
 			$form->{issue} = "";
 		}
 	}
-	
 
+
 	my $colors = $self->getFireHoseColors();
 	if ($form->{color} && $colors->{$form->{color}}) {
 		$options->{color} = $form->{color};
@@ -1840,6 +2084,8 @@
 			} else {
 				$options->{orderby} = 'popularity';
 			}
+		} elsif ($form->{orderby} eq 'neediness') {
+			$options->{orderby} = 'neediness';
 		} else {
 			$options->{orderby} = "createtime";
 		}
@@ -1894,7 +2140,6 @@
 		$form->{color} = "black";
 	} elsif ($tabtype eq 'tabuser') {
 		$form->{fhfilter} = "\"user:$user->{nickname}\"";
-		$options->{orderby} = "popularity";
 		$options->{color} = "black";
 		$form->{color} = "black";
 		$options->{orderdir} = "DESC";
@@ -1904,6 +2149,14 @@
 		$options->{orderdir} = "DESC";
 		$options->{orderby} = "createtime";
 		$options->{color} = "indigo";
+	} elsif ($tabtype eq 'metamod') {
+		$form->{fhfilter} = "comment";
+		$options->{color} = "black";
+		$form->{color} = "black";
+		$options->{orderdir} = "DESC";
+		$options->{orderby} = "neediness";
+		$options->{mode} = "full";
+		$options->{mixedmode} = 0;
 	}
 
 	if ($tabtype) {
@@ -1930,7 +2183,7 @@
 	if ($the_skin && $the_skin->{name} && $the_skin->{skid} != $constants->{mainpage_skid})  {
 		$skin_prefix = "$the_skin->{name} ";
 	}
-	my $system_tabs = [ 
+	my $system_tabs = [
 		{ tabtype => 'aretama', color => 'indigo', filter => $skin_prefix, orderby => 'createtime'},
 		{ tabtype => 'tabsection', color => 'black', filter => $skin_prefix . "story", orderby => 'createtime'},
 		{ tabtype => 'tabpopular', color => 'black', filter => "$skin_prefix\-story", orderby => 'popularity'},
@@ -1944,8 +2197,8 @@
 	my $sel_tabtype;
 
 	my $tab_compare = {
-		color		=> "color",
-		filter		=> "fhfilter"
+		color 		=> "color",
+		filter 		=> "fhfilter"
 	};
 
 	my $tab_match = 0;
@@ -1970,10 +2223,10 @@
 			if (defined $tab->{tabtype}) {
 				$sel_tabtype = $tab->{tabtype};
 			}
-			
+
 			# Tab match if new option is being set update tab
 			if ($form->{orderdir} || $form->{orderby} || $form->{mode}) {
-				
+
 				my $data = {};
 				$data->{orderdir} = $options->{orderdir};
 				$data->{orderby}  = $options->{orderby};
@@ -2025,36 +2278,6 @@
 		}
 	}
 
-	# 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;
-		} else {
-			$options->{limit} = $pagesize eq "large" ? 25 : 15;
-		}
-	} else {
-		if ($user->{is_admin}) {
-			$options->{limit} = 50;
-		} else {
-			$options->{limit} = $pagesize eq "large" ? 30 : 25;
-		}
-	}
-
-	# 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) {
-			$force_smaller = 1;
-		}
-	}
-
-	# ...for which we'll have fewer items per page
-	if ($force_smaller) {
-		$options->{smalldevices} = 1;
-		$options->{limit} = 10;
-	}
-
 	if ($user->{is_admin} && $form->{setusermode}) {
 		$self->setUser($user->{uid}, { firehose_usermode => $form->{firehose_usermode} ? 1 : "" });
 	}
@@ -2086,7 +2309,6 @@
 		}
 	}
 	my $fh_ops = $self->splitOpsFromString($fhfilter);
-	
 
 	my $skins = $self->getSkins();
 	my %skin_names = map { $skins->{$_}{name} => $_ } keys %$skins;
@@ -2176,7 +2398,6 @@
 			$options->{mixedmode} = 0;
 		}
 	}
-	
 
 	foreach (keys %$fh_options) {
 		$options->{$_} = $fh_options->{$_};
@@ -2225,7 +2446,7 @@
 		if ($firehose_page ne "user") {
 			$options->{accepted} = "no" if !$options->{accepted};
 		}
-		
+
 		$options->{duration} ||= 1;
 		if ($user->{is_subscriber} && !$no_saved) {
 			$options->{createtime_subscriber_future} = 1;
@@ -2252,10 +2473,92 @@
 			$self->setUser($user->{uid}, { firehose_max_more_num => $options->{more_num}});
 		}
 	}
-
+	if ($user->{state}{firehose_init_list} && $options->{sel_tabtype}) {
+		my $set_opts = $self->getInitTabtypeOptions($options->{sel_tabtype});
+		foreach (keys %$set_opts) {
+			$options->{$_} = $set_opts->{$_};
+		}
+	}
+	$options->{smalldevices} = 1 if $self->shouldForceSmall();
+	$options->{limit} = $self->getFireHoseLimitSize($options->{mode}, $pagesize, $options->{smalldevices});
 	return $options;
 }
 
+sub getFireHoseLimitSize {
+	my($self, $mode, $pagesize, $forcesmall) = @_;
+	my $user = getCurrentUser();
+	my $constants = getCurrentStatic();
+	my $form = getCurrentForm();
+
+	my $limit;
+
+	if ($mode eq "full") {
+		if ($user->{is_admin}) {
+			$limit = $pagesize eq "large" ? 50 : 25;
+		} else {
+			$limit = $pagesize eq "large" ? 25 : 15;
+		}
+	} else {
+		$limit = $user->{is_admin} ? 50 :
+			$pagesize eq "large" ? 30 : 25;
+	}
+
+	$limit = 10 if $forcesmall || $form->{metamod};
+	return $limit;
+}
+
+sub shouldForceSmall {
+	my($self) = @_;
+	my $form = getCurrentForm();
+	my $constants = getCurrentStatic();
+
+	# the non-normal cases: a small device (e.g., iPhone) or an embedded use (e.g., Google Gadget)
+	my $force_smaller = $form->{embed} ? 1 : 0;
+	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) {
+			$force_smaller = 1;
+		}
+	}
+	return $force_smaller;
+}
+
+sub getInitTabtypeOptions {
+	my($self, $name) = @_;
+	my $gSkin = getCurrentSkin();
+	my $form = getCurrentForm();
+	my $vol = $self->getSkinVolume($gSkin->{skid});
+	my $day_specified = $form->{startdate} || $form->{issue};
+	my $set_option;
+
+	$vol ||= { story_vol => 0, other_vol => 0};
+
+	if ($name eq "tabsection") {
+		$set_option->{mixedmode} = "1";
+		$set_option->{mode} = "full";
+		if (!$day_specified) {
+			if ($vol->{story_vol} > 25) {
+				$set_option->{duration} = 7;
+			} else {
+				$set_option->{duration} = -1;
+			}
+		}
+		$set_option->{startdate} = "";
+	} elsif (($name eq "tabpopular" || $name eq "tabrecent") && !$day_specified) {
+		if ($vol->{story_vol} > 25) {
+			$set_option->{duration} = 7;
+		} else {
+			$set_option->{duration} = -1;
+		}
+		$set_option->{startdate} = "";
+		$set_option->{mixedmode} = "1";
+	} elsif ($name eq "metamod") {
+		$set_option->{duration} = 7;
+		$set_option->{startdate} = '';
+	}
+	return $set_option;
+}
+
 sub getFireHoseTagsTop {
 	my($self, $item) = @_;
 	my $user 	= getCurrentUser();
@@ -2276,7 +2579,7 @@
 	} else {
 		push @$tags_top, $item->{type};
 	}
-	
+
 	if ($item->{primaryskid} && $item->{primaryskid} != $constants->{mainpage_skid}) {
 		my $the_skin = $self->getSkin($item->{primaryskid});
 		push @$tags_top, "$the_skin->{name}:2";
@@ -2286,7 +2589,7 @@
 		push @$tags_top, "$the_topic->{keyword}:3";
 	}
 	my %seen_tags = map { $_ => 1 } @$tags_top;
-	
+
 	# 0 = is a link, not a menu
 	my $user_tags_top = [];
 	push @$user_tags_top, map { "$_:0" } grep {!$seen_tags{$_}} split (/\s+/, $item->{toptags});
@@ -2294,17 +2597,16 @@
 	if ($constants->{smalldevices_ua_regex}) {
 		my $smalldev_re = qr($constants->{smalldevices_ua_regex});
 		if ($ENV{HTTP_USER_AGENT} =~ $smalldev_re) {
-			$#{@$user_tags_top} = 2;
+			$#$user_tags_top = 2;
 		}
 	}
 
 	if ($form->{embed}) {
-		$#{@$user_tags_top} = 2;
+		$#$user_tags_top = 2;
 	}
 
 	push @$tags_top, @$user_tags_top;
 
-	
 	return $tags_top;
 }
 
@@ -2352,6 +2654,8 @@
 	my $gSkin = getCurrentSkin();
 	my $form = getCurrentForm();
 
+	$user->{state}{firehose_init_list} = 1;
+
 	my $firehose_reader = getObject('Slash::FireHose', {db_type => 'reader'});
 	my $featured;
 
@@ -2370,21 +2674,22 @@
 		}
 	}
 	my $initial = ($form->{tab} || $form->{tabtype} || $form->{fhfilter} || defined $form->{page} || $lv_opts->{fh_page} eq "console.pl" || $form->{ssi} && defined $form->{fhfilter}) ? 0 : 1;
-
 	my $options = $lv_opts->{options} || $self->getAndSetOptions({ initial => $initial });
 	my $base_page = $lv_opts->{fh_page} || "firehose.pl";
 
 	if ($featured && $featured->{id}) {
 		$options->{not_id} = $featured->{id};
 	}
+	slashProf("get_fhe");
 	my($items, $results, $count, $future_count, $day_num, $day_label, $day_count) = $firehose_reader->getFireHoseEssentials($options);
+	slashProf("","get_fhe");
 
 	my $itemnum = scalar @$items;
 
 	my $globjs;
 
 	foreach (@$items) {
-		push @$globjs, $_->{globjid} if $_->{globjid} 
+		push @$globjs, $_->{globjid} if $_->{globjid}
 	}
 
 	if ($options->{orderby} eq "createtime") {
@@ -2405,8 +2710,13 @@
 	my $mode = $options->{mode};
 	my $curmode = $options->{mode};
 	my $mixed_abbrev_pop = $self->getMinPopularityForColorLevel(1);
+	my $vol = $self->getSkinVolume($gSkin->{skid});
+	$vol->{story_vol} ||= 0;
+	if ($vol->{story_vol} < 25) {
+		$mixed_abbrev_pop = $self->getMinPopularityForColorLevel(3);
+	}
 	my $constants = getCurrentStatic();
-	
+
 	foreach (@$items) {
 		if ($options->{mixedmode}) {
 			$curmode = "full";
@@ -2416,19 +2726,24 @@
 		$maxtime = $_->{createtime} if $_->{createtime} gt $maxtime && $_->{createtime} lt $now;
 		my $item =  $firehose_reader->getFireHose($_->{id});
 		my $tags_top = $firehose_reader->getFireHoseTagsTop($item);
+		my $tags = getObject("Slash::Tags", { db_type => 'reader' })->setGetCombinedTags($_->{id}, 'firehose');
 		if ($_->{day}) {
 			my $day = $_->{day};
 			$day =~ s/ \d{2}:\d{2}:\d{2}$//;
 			$itemstext .= slashDisplay("daybreak", { options => $options, cur_day => $day, last_day => $_->{last_day}, id => "firehose-day-$day", fh_page => $base_page }, { Return => 1, Page => "firehose" });
 		} else {
 	$last_day = timeCalc($item->{createtime}, "%Y%m%d");
+			slashProf("firehosedisp");
 			$itemstext .= $self->dispFireHose($item, {
 				mode			=> $curmode,
-				tags_top		=> $tags_top,
+				tags_top		=> $tags_top,		# old-style
+				top_tags		=> $tags->{top},	# new-style
+				system_tags		=> $tags->{'system'},	# new-style
 				options			=> $options,
 				vote			=> $votes->{$item->{globjid}},
 				bodycontent_include	=> $user->{is_anon} 
 			});
+			slashProf("","firehosedisp");
 		}
 		$i++;
 	}
@@ -2440,23 +2755,23 @@
 	} else {
 		$refresh_options->{insert_new_at} = "top";
 	}
-	
+
 	my $section = 0;
 	if ($gSkin->{skid} != $constants->{mainpage_skid}) {
 		$section = $gSkin->{skid};
 	}
-	my $firehose_more_data = { 
-		future_count => $future_count, 
+	my $firehose_more_data = {
+		future_count => $future_count,
 		options => $options,
 		day_num	=> $day_num,
-		day_label => $day_label, 
+		day_label => $day_label,
 		day_count => $day_count
 	};
 
 	slashDisplay("list", {
-		itemstext		=> $itemstext, 
+		itemstext		=> $itemstext,
 		itemnum			=> $itemnum,
-		page			=> $options->{page}, 
+		page			=> $options->{page},
 		options			=> $options,
 		refresh_options		=> $refresh_options,
 		votes			=> $votes,
@@ -2474,21 +2789,25 @@
 }
 
 sub setFireHoseSession {
-	my ($self, $id) = @_;
+	my ($self, $id, $action) = @_;
 	my $user = getCurrentUser();
 	my $item = $self->getFireHose($id);
+
+	$action ||= "reviewing";
+
 	my $data = {};
 	$data->{lasttitle} = $item->{title};
 	if ($item->{type} eq "story") {
 		my $story = $self->getStory($item->{srcid});
 		$data->{last_sid} = $story->{sid} if $story && $story->{sid};
-	} 
+	}
 
 	if (!$data->{last_sid}) {
 		$data->{last_fhid} = $item->{id};
 	}
 	$data->{last_subid} ||= '';
 	$data->{last_sid} ||= '';
+	$data->{last_action} = $action;
 	$self->setSession($user->{uid}, $data);
 }
 
@@ -2503,12 +2822,12 @@
 	my $where = join ' AND ', @where;
 
 	my $tabs = $self->sqlSelectAllHashrefArray("*", "firehose_tab", $where, "ORDER BY tabname ASC");
-	@$tabs = sort { 
-			$b->{tabname} eq "untitled" ? -1 : 
+	@$tabs = sort {
+			$b->{tabname} eq "untitled" ? -1 :
 				$a->{tabname} eq "untitled" ? 1 : 0	||
-			$b->{tabname} eq "User" ? -1 : 
+			$b->{tabname} eq "User" ? -1 :
 				$a->{tabname} eq "User" ? 1 : 0	||
-			$a->{tabname} cmp $b->{tabname} 
+			$a->{tabname} cmp $b->{tabname}
 	} @$tabs;
 	return $tabs;
 }
@@ -2545,7 +2864,7 @@
 	my ($self, $str) = @_;
 	my @fh_ops_orig = map { lc($_) } split((/\s+|"/), $str);
 	my @fh_ops;
-	
+
 	my $in_quotes = 0;
 	my $cur_op = "";
 	foreach (@fh_ops_orig) {
@@ -2583,7 +2902,7 @@
 		} else {
 			$last_days_processed++;
 		}
-		
+
 		push @retitems, $_;
 		$last_day = $cur_day;
 		$days_processed++;
@@ -2634,29 +2953,40 @@
 sub ajaxFireHoseUsage {
 	my($slashdb, $constants, $user, $form) = @_;
 
-	my $tags = getObject('Slash::Tags');
+	my $tags_reader = getObject('Slash::Tags', { db_type => 'reader' });
+
 	my $downlabel = $constants->{tags_downvote_tagname} || 'nix';
-	my $down_id = $tags->getTagnameidFromNameIfExists($downlabel);
-	
+	my $down_id = $tags_reader->getTagnameidFromNameIfExists($downlabel);
+
 	my $uplabel = $constants->{tags_upvote_tagname} || 'nod';
-	my $up_id = $tags->getTagnameidFromNameIfExists($uplabel);
+	my $up_id = $tags_reader->getTagnameidFromNameIfExists($uplabel);
 	my $data = {};
 
+#	$data->{fh_users} = $tags_reader->sqlSelect("COUNT(DISTINCT uid)", "tags",
+#		"tagnameid IN ($up_id, $down_id)");
+	my $d_clause = " AND created_at > DATE_SUB(NOW(), INTERVAL 1 DAY)";
+	my $h_clause = " AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)";
+	$data->{fh_users_day} = $tags_reader->sqlSelect("COUNT(DISTINCT uid)", "tags",
+		"tagnameid IN ($up_id, $down_id) $d_clause");
+	$data->{fh_users_hour} = $tags_reader->sqlSelect("COUNT(DISTINCT uid)", "tags",
+		"tagnameid IN ($up_id, $down_id) $h_clause");
+	$data->{tag_cnt_day} = $tags_reader->sqlSelect("COUNT(*)", "tags,users,firehose",
+		"firehose.globjid=tags.globjid AND tags.uid=users.uid AND users.seclev = 1 $d_clause");
+	$data->{tag_cnt_hour} = $tags_reader->sqlSelect("COUNT(*)", "tags,users,firehose",
+		"firehose.globjid=tags.globjid AND tags.uid=users.uid AND users.seclev = 1 $h_clause");
+	$data->{nod_cnt_day} = $tags_reader->sqlSelect("COUNT(*)", "tags,users",
+		"tags.uid=users.uid AND users.seclev = 1 AND tagnameid IN ($up_id) $d_clause");
+	$data->{nod_cnt_hour} = $tags_reader->sqlSelect("COUNT(*)", "tags,users",
+		"tags.uid=users.uid AND users.seclev = 1 AND tagnameid IN ($up_id) $h_clause");
+	$data->{nix_cnt_day} = $tags_reader->sqlSelect("COUNT(*)", "tags,users",
+		"tags.uid=users.uid AND users.seclev = 1 AND tagnameid IN ($down_id) $d_clause");
+	$data->{nix_cnt_hour} = $tags_reader->sqlSelect("COUNT(*)", "tags,users",
+		"tags.uid=users.uid AND users.seclev = 1 AND tagnameid IN ($down_id) $h_clause");
+	$data->{globjid_cnt_day} = $tags_reader->sqlSelect("COUNT(DISTINCT globjid)", "tags,users",
+		"tags.uid=users.uid AND users.seclev = 1 AND tagnameid IN ($up_id, $down_id) $d_clause");
+	$data->{globjid_cnt_hour} = $tags_reader->sqlSelect("COUNT(DISTINCT globjid)", "tags,users",
+		"tags.uid=users.uid AND users.seclev = 1 AND tagnameid IN ($up_id, $down_id) $h_clause");
 
-	$data->{fh_users} = $slashdb->sqlSelect("count(distinct uid)", "tags", "tagnameid in($up_id, $down_id)");
-	my $d_clause = " and created_at > date_sub(now(), interval 1 day)";
-	my $h_clause = " and created_at > date_sub(now(), interval 1 hour)";
-	$data->{fh_users_day} = $slashdb->sqlSelect("count(distinct uid)", "tags", "tagnameid in($up_id, $down_id) $d_clause");
-	$data->{fh_users_hour} = $slashdb->sqlSelect("count(distinct uid)", "tags", "tagnameid in($up_id, $down_id) $h_clause");
-	$data->{tag_cnt} = $slashdb->sqlSelect("count(*)", "tags,users,firehose", "firehose.globjid=tags.globjid AND tags.uid=users.uid AND users.seclev = 1 $d_clause");
-	$data->{tag_cnt_hour} = $slashdb->sqlSelect("count(*)", "tags,users,firehose", "firehose.globjid=tags.globjid AND tags.uid=users.uid AND users.seclev = 1 $h_clause");
-	$data->{nod_cnt} = $slashdb->sqlSelect("count(*)", "tags,users", "tags.uid=users.uid AND users.seclev = 1 AND tagnameid in($up_id) $d_clause");
-	$data->{nod_cnt_hour} = $slashdb->sqlSelect("count(*)", "tags,users", "tags.uid=users.uid AND users.seclev = 1 AND tagnameid in($up_id) $h_clause");
-	$data->{nix_cnt} = $slashdb->sqlSelect("count(*)", "tags,users", "tags.uid=users.uid AND users.seclev = 1 AND tagnameid in($down_id) $d_clause");
-	$data->{nix_cnt_hour} = $slashdb->sqlSelect("count(*)", "tags,users", "tags.uid=users.uid AND users.seclev = 1 AND tagnameid in($down_id) $h_clause");
-
-	$data->{globjid_cnt} = $slashdb->sqlSelect("count(distinct globjid)", "tags,users", "tags.uid=users.uid AND users.seclev = 1 AND tagnameid in($up_id, $down_id) $d_clause");
-	$data->{globjid_cnt_hour} = $slashdb->sqlSelect("count(distinct globjid)", "tags,users", "tags.uid=users.uid AND users.seclev = 1 AND tagnameid in($up_id, $down_id) $h_clause");
 	slashDisplay("firehose_usage", $data, { Return => 1 });
 }
 
@@ -2682,14 +3012,13 @@
 			$menu->{$skid} = $skins->{$skid}{title};
 		}
 	}
-	my $onchange = $user->{is_anon} 
-		? "firehose_change_section_anon(this.options[this.selectedIndex].value)" 
+	my $onchange = $user->{is_anon}
+		? "firehose_change_section_anon(this.options[this.selectedIndex].value)"
 		: "firehose_set_options('tabsection', this.options[this.selectedIndex].value)";
 
 	@$ordered = sort {$a == 0 ? -1 : $b == 0 ? 1 : 0 || $menu->{$a} cmp $menu->{$b} } keys %$menu;
 	return createSelect("section", $menu, { default => $default, return => 1, nsort => 0, ordered => $ordered, multiple => 0, onchange => $onchange });
 
-	
 }
 
 sub linkFireHose {
@@ -2710,7 +3039,10 @@
 		$link_url = $story_link_ar->[0];
 	} elsif ($item->{type} eq "journal") {
 		my $the_user = $self->getUser($item->{uid});
-		$link_url = $constants->{rootdir} . "/~" . fixparam($the_user->{nickname}) . "/journal/$item->{srcid}"; 
+		$link_url = $constants->{rootdir} . "/~" . fixparam($the_user->{nickname}) . "/journal/$item->{srcid}";
+	} elsif ($item->{type} eq "comment") {
+		my $com = $self->getComment($item->{srcid});
+		$link_url = $gSkin->{rootdir} . "/comments.pl?sid=$com->{sid}&amp;cid=$com->{cid}";
 	} else {
 		$link_url = $gSkin->{rootdir} . '/firehose.pl?op=view&amp;id=' . $item->{id};
 	}
@@ -2728,13 +3060,13 @@
 	my @params;
 
 	foreach my $label (qw(fhfilter color orderdir orderby startdate duration mode)) {
-	
+
 		my $value = defined $data->{$label} ? $data->{$label} : $options->{$label};
 		if ($label eq "startdate") {
 			$value =~s /-//g;
 		}
 		push @params, "$label=$value";
-		
+
 	}
 
 	my $str =  join('&amp;', @params);
@@ -2751,9 +3083,48 @@
 sub createSettingLog {
 	my($self, $data) = @_;
 	return if !getCurrentStatic("firehose_logging");
+	return if !$data->{name};
+
+	$data->{value} ||= "";
 	$data->{uid} ||= getCurrentUser('uid');
 	$self->sqlInsert("firehose_setting_log", $data);
 }
+
+sub getSkinVolume {
+	my($self, $skid) = @_;
+	my $skid_q = $self->sqlQuote($skid);
+	return $self->sqlSelectHashref("*", "firehose_skin_volume", "skid=$skid_q");
+}
+
+sub genFireHoseWeeklyVolume {
+	my($self, $options) = @_;
+	$options ||= {};
+	my $colors = $self->getFireHoseColors();
+	my @where;
+
+	if ($options->{type}) {
+		push @where, "type=" . $self->sqlQuote($options->{type});
+	}
+	if ($options->{not_type}) {
+		push @where, "type!=" . $self->sqlQuote($options->{not_type});
+	}
+	if ($options->{color}) {
+		my $pop;
+		$pop = $self->getMinPopularityForColorLevel($colors->{$options->{color}});
+		push @where, "popularity >= " . $self->sqlQuote($pop);
+	}
+	if ($options->{primaryskid}) {
+		push @where, "primaryskid=" . $self->sqlQuote($options->{primaryskid});
+	}
+	push @where, "createtime >= DATE_SUB(NOW(), INTERVAL 7 DAY)";
+	my $where = join ' AND ', @where;
+	return $self->sqlCount("firehose", $where);
+}
+
+sub setSkinVolume {
+	my($self, $data) = @_;
+	$self->sqlReplace("firehose_skin_volume", $data);
+}
 1;
 
 __END__
@@ -2762,7 +3133,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id: FireHose.pm,v 1.176 2007/10/04 15:47:38 jamiemccarthy Exp $

Modified: slashjp/trunk/plugins/FireHose/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/FireHose/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::FireHose',
-    'VERSION_FROM' => 'FireHose.pm', # finds $VERSION
     'PM'	=> { 'FireHose.pm' => '$(INST_LIBDIR)/FireHose.pm' },
 );

Modified: slashjp/trunk/plugins/FireHose/PLUGIN
===================================================================
--- slashjp/trunk/plugins/FireHose/PLUGIN	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/PLUGIN	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,11 @@
-# $Id: PLUGIN,v 1.25 2007/09/13 18:52:50 tvroom Exp $
+# $Id$
 name=FireHose
 description="FireHose"
-css=firehose.css
+glob=firehosecss:htdocs/firehose.css
+firehosecss=firehose.css
+firehosecss=../Ajax/htdocs/images/tagui.css
+firehosecss=../Ajax/htdocs/images/jquery/jquery.autocomplete.css
+css=htdocs/firehose.css
 htdoc=firehose.pl
 mysql_dump=mysql_dump.sql
 mysql_schema=mysql_schema.sql
@@ -24,7 +28,6 @@
 template=templates/firehose_options;misc;default
 template=templates/formatHoseIntro;misc;default
 template=templates/formatHoseTitle;misc;default
-template=templates/tagstack;firehose;default
 template=templates/nodnix_menus;firehose;default
 template=templates/paginate;firehose;default
 template=templates/portalmap;firehose;default
@@ -33,8 +36,12 @@
 template=templates/tagsfirehosedivtagbox;misc;default
 template=templates/tagsfirehosedivuser;misc;default
 template=templates/tagsnodnixuser;misc;default
+template=templates/tag_widget;firehose;default
+template=templates/init_tagui;firehose;default
 task=firehose_reject_old.pl
+task=firehose_track_volume.pl
 task=firehose_backend.pl
 task=firehose_get_thumbnails.pl
+task=firehose_track_volume.pl
 image=images/colorscale.png
 image=images/slidethumb.png

Modified: slashjp/trunk/plugins/FireHose/firehose.css
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose.css	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/firehose.css	2008-09-09 13:07:58 UTC (rev 742)
@@ -145,6 +145,7 @@
 .daybreak,
 .paginate { background: #666 url('//images.slashdot.org/block-title-bg.png') repeat-x; }
 .paginate { margin-right: 18.5em; }
+#metamodwrap .paginate { margin-right: 0em}
 #users .paginate { margin-right: 0em; }
 
 .admin .paginate { margin-right: 0; }
@@ -167,6 +168,7 @@
 .storylinks li.comments {border-left: 1px solid #ccc; padding-left: 1em !important}
 #firehoselist { padding: 1em 0 0 0; }
 #firehoselist, #firehose #message, .firemenu { margin-right: 18.5em; }
+#metamodwrap #firehoselist, #firehose #metamodwrap #message { margin-right: 0em; }
 #users #firehoselist, #users #firehose #message, #users .firemenu { margin-right: 0em; }
 .admin #firehoselist, .admin #firehose #message, .admin .firemenu { margin-right: 0; }
 .article .generaltitle .title .date,
@@ -255,6 +257,8 @@
 right: 0;
 }
 
+div.briefarticle[type=comment] .title a span { background: transparent !important }
+
 /* Icons and imagery for articles */
 
 .edit
@@ -401,7 +405,7 @@
 
 .story .date, .story a.skin {color: #699 !important;}
 .future .date, .future a.skin {color: #c99 !important;}
-.firehose .date, .firehose a.skin {color: #777 !important;}
+.firehose .date, .firehose a.skin, .firehose span.skin, .firehose span.reason {color: #777 !important;}
 
 .article .generaltitle, .briefarticle .generaltitle { min-height: 25px; position: relative; background-image: url('//images.slashdot.org/fh_btr_s.png') !important; background-position: top right !important;}
 .briefarticle .generaltitle .title { background-image: url('//images.slashdot.org/fh_br_s.png') !important; background-position: bottom right !important;}
@@ -470,3 +474,29 @@
 .briefarticle .storylinks .comments.nocomment, .briefarticle .storylinks .comments span  {display: none}
 
 .embed .paginate, .embed .firemenu, .embed a.skin, .copyright.embed { display: none; }
+#fhtablist li:before { content: "";}
+#fhtablist li { padding-left: 0.5em }
+
+.view div.tags div.tagtitleclosed, .view div.tags div.tagtitleopen {
+margin:0pt 0pt -1.4em 0pt;
+text-align:right;
+}
+
+.view .article div.tagtitleclosed{
+width: 90%;
+left:0pt;
+}
+
+* html .view .article div.tagtitleclosed{ /* IE6 */
+right:0pt;
+}
+
+* html body .view .article div.tagtitleclosed{ /* IE6 as well */
+left:auto;
+right:0pt;
+}
+
+*+html  .view .article div.tagtitleclosed{ /* IE7 */
+left:auto;
+right:0pt;
+}

Modified: slashjp/trunk/plugins/FireHose/firehose.pl
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/firehose.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: firehose.pl,v 1.44 2007/09/13 18:44:11 pudge Exp $
+# $Id$
 
 use strict;
 use warnings;
@@ -14,7 +14,7 @@
 use Slash::XML;
 use vars qw($VERSION);
 
-($VERSION) = ' $Revision: 1.44 $ ' =~ /\$Revision:\s+([^\s]+)/;
+($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
 
 
 sub main {
@@ -31,6 +31,7 @@
 		view		=> [1, 	\&view, 0,  ""],
 		default		=> [1,	\&list, 1,  $anonval, { index => 1, issue => 1, page => 1, query_apache => -1, virtual_user => -1, startdate => 1, duration => 1, tab => 1, tabtype => 1, change => 1, section => 1 }],
 		edit		=> [1,	\&edit, 100,  ""],
+		metamod		=> [1,  \&metamod, 1, ""],
 		rss		=> [1,  \&rss, 1, ""]
 	);
 
@@ -76,6 +77,12 @@
 		if ($constants->{firehose_name}) {
 			$title = "$constants->{sitename} - $constants->{firehose_name}";
 		}
+		if ($gSkin->{name} eq "idle") {
+			$title = "$gSkin->{hostname} - $constants->{firehose_name}";
+		}
+		if ($op eq "metamod") {
+			$title = "$constants->{sitename} - Metamod";
+		}
 		if ($form->{index}) {
 			$title = "$constants->{sitename} - $constants->{slogan}";
 		}
@@ -92,10 +99,25 @@
 
 sub list {
 	my($slashdb, $constants, $user, $form, $gSkin) = @_;
+	slashProfInit();
 	my $firehose = getObject("Slash::FireHose");
 	print $firehose->listView();
+	slashProfEnd();
 }
 
+sub metamod {
+	my($slashdb, $constants, $user, $form, $gSkin) = @_;
+	my $firehose = getObject("Slash::FireHose");
+	$form->{tabtype} 	= "metamod";
+	$form->{skipmenu} 	= 1;
+	$form->{metamod} 	= 1;
+	$form->{pause} 		= 1;
+	$form->{no_saved} 	= 1;
+	print $firehose->listView();
+}
+
+
+
 sub view {
 	my($slashdb, $constants, $user, $form, $gSkin) = @_;
 	my $firehose = getObject("Slash::FireHose");
@@ -148,6 +170,35 @@
 		return;
 	}
 	my $item = $firehose->getFireHose($form->{id});
+
+	if ($item->{type} eq 'submission') {
+		# here we fix up some things for authors, namely the subject
+		# line and do some (extremely) simple quote manipulation. This
+		# is also where someday we'll contact the jabber bot to alert
+		# authors that a story is being edited.         --Pater
+		if ($item->{introtext} =~ m/^[^"]*"[^"]*"[^"]*$/s) {
+			$item->{introtext} =~ s/"/'/g;
+		}
+
+		my @words = split / /, $item->{title};
+		my @newwords;
+
+		for (my $i = 0; $i < @words; $i++) {
+			my $word = $words[$i];
+			if ($i == 0) {
+				$word = ucfirst $word;
+			} elsif ($word =~ m/^a(n|nd)?$|^the$|^of$/i) {
+				$word = lcfirst $word;
+			} else {
+				$word = ucfirst $word;
+			}
+
+			push @newwords, $word;
+		}
+
+		$item->{title} = join(' ', @newwords);
+	}
+
 	my $url;
 	$url = $slashdb->getUrl($item->{url_id}) if $item->{url_id};
 	my $the_user = $slashdb->getUser($item->{uid});

Modified: slashjp/trunk/plugins/FireHose/firehose_backend.pl
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose_backend.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/firehose_backend.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: firehose_backend.pl,v 1.1 2007/09/13 18:51:46 tvroom Exp $
+# $Id$
 
 use strict;
 use Slash;
@@ -22,62 +22,73 @@
 
 	my $rss = {};
 
-	$rss->{"firehose"} = [ "green", "" ];
-	$rss->{"firehose_nostories"} = ["green",  "-story" ];
+	$rss->{"firehose"} = [ "", "green", "" ];
+	$rss->{"firehose_nostories"} = ["Non-Stories", "green",  "-story" ];
+	$rss->{"firehose_stories"} = ["Stories", "black", "story", { limit => 25}];
+	$rss->{"firehose_recent"} = ["Recent", "indigo", "-story", { limit => 25 }];
+	$rss->{"firehose_popular"} = ["Popular", "black", "-story", { orderby => "popularity", limit => 25, duration => 7 }];
 
 	foreach (keys %$rss) {
-		slashdLog("gen firehose $_\n");
-		gen_firehose_rss($virtual_user, $_, $rss->{$_}->[0], $rss->{$_}->[1], "rss");
+		gen_firehose_rss($virtual_user, $_, "", $rss->{$_}->[0], $rss->{$_}->[1], $rss->{$_}->[2],$rss->{$_}->[3], "rss");
 	}
-		
-};
 
-# this normalizes old and new content, stripping data that
-# updates every time
-sub fudge {
-	my($current, $new) = @_;
-	s{[dD]ate>[^<]+</}{} for $current, $new;
-	return($current, $new);
-}
+	my $skins = $slashdb->getSkins();
+	foreach(keys %$skins) {
+		my $skinname = $skins->{$_}{name};
+		foreach (keys %$rss) {
+			gen_firehose_rss($virtual_user, "$skinname\_$_", $skinname, $rss->{$_}->[0], $rss->{$_}->[1], "$skinname $rss->{$_}->[2]", $rss->{$_}->[3], "rss");
+		}
+	}
 
 
+};
+
 sub gen_firehose_rss {
-	my($vu, $base, $color, $filter, $content_type) = @_;
+	my($vu, $base, $skin, $label, $color, $filter, $opts, $content_type) = @_;
 	my $constants = getCurrentStatic();
 	my $slashdb = getCurrentDB();
 	my $gSkin = getCurrentSkin();
 	my $form = getCurrentForm();
+	$opts ||= {};
 	$content_type ||= "rss";
 
+	slashdLog("$base $skin $label $color '$filter'");
+	use Data::Dumper;
+	slashdLog(Dumper($opts)) if $opts;
+
 	$form->{color} = $color;
 	$form->{fhfilter} = $filter;
 	$form->{duration} = -1;
 	$form->{startdate} = '';
-	$form->{pagesize} = "large";
-	
+
+
 	my $firehose = getObject("Slash::FireHose");
 	my $options = $firehose->getAndSetOptions({ no_set => 1 });
+	$options->{limit} = 10;
 
-	#use Data::Dumper;
-	#slashdLog(Dumper($options));
+	foreach (keys %$opts) {
+		$options->{$_} = $opts->{$_};
+	}
 
+
 	my ($its, $results) = $firehose->getFireHoseEssentials($options);
 	my @items;
 	foreach (@$its) {
 		my $item = $firehose->getFireHose($_->{id});
+		my $link = $firehose->linkFireHose($item);
 		push @items, {
 			title 		=> $item->{title},
 			time 		=> $item->{createtime},
 			creator 	=> $slashdb->getUser($item->{uid}, 'nickname'),
-			'link'		=> "$gSkin->{absolutedir}/firehose.pl?op=view&id=$item->{id}",
+			'link'		=> $link,
 			description	=> $item->{introtext}
 		};
 	}
 	my $rss = xmlDisplay($content_type, {
 		channel => {
-			title		=> "$constants->{sitename} Firehose",
+			title		=> "$constants->{sitename} $skin Firehose $label",
 			'link'		=> "$gSkin->{absolutedir}/firehose.pl",
-			descriptions 	=> "$constants->{sitename} Firehose"
+			descriptions 	=> "$constants->{sitename} $skin Firehose $label"
 		},
 		image	=> 1,
 		items	=> \@items,
@@ -87,5 +98,15 @@
 }
 
 
+# this normalizes old and new content, stripping data that
+# updates every time
+sub fudge {
+	my($current, $new) = @_;
+	s{[dD]ate>[^<]+</}{} for $current, $new;
+	return($current, $new);
+}
 
+
+
+
 1;

Modified: slashjp/trunk/plugins/FireHose/firehose_get_thumbnails.pl
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose_get_thumbnails.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/firehose_get_thumbnails.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
+# $Id$
 
 use strict;
 

Modified: slashjp/trunk/plugins/FireHose/firehose_reject_old.pl
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose_reject_old.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/firehose_reject_old.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: firehose_reject_old.pl,v 1.2 2007/08/15 03:07:29 tvroom Exp $
+# $Id$
 
 use strict;
 

Copied: slashjp/trunk/plugins/FireHose/firehose_track_volume.pl (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/FireHose/firehose_track_volume.pl)
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose_track_volume.pl	                        (rev 0)
+++ slashjp/trunk/plugins/FireHose/firehose_track_volume.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,46 @@
+#!/usr/bin/perl -w
+# This code is a part of Slash, and is released under the GPL.
+# Copyright 1997-2005 by Open Source Technology Group. See README
+# and COPYING for more information, or see http://slashcode.com/.
+# $Id$
+
+use strict;
+
+use Time::HiRes;
+
+use Slash;
+use Slash::Constants ':slashd';
+use Slash::Display;
+use Slash::Utility;
+
+use vars qw(
+	%task	$me	$task_exit_flag
+);
+
+$task{$me}{timespec} = '1 1,7,13,19 * * *';
+$task{$me}{fork} = SLASHD_NOWAIT;
+$task{$me}{code} = sub {
+	my($virtual_user, $constants, $slashdb, $user, $info, $gSkin) = @_;
+
+	my $firehose = getObject("Slash::FireHose");
+	my $skins = $slashdb->getSkins();
+
+	foreach my $skid (%$skins) {
+		my $skid_lookup = $skid == $constants->{mainpage_skid} ? 0 : $skid;
+		my $story_vol = $firehose->genFireHoseWeeklyVolume({
+			type => "story",
+			color => "black",
+			primaryskid => $skid_lookup
+		});
+
+		my $other_vol = $firehose->genFireHoseWeeklyVolume({
+			not_type => "story",
+			color => "indigo",
+			primaryskid => $skid_lookup
+		});
+		$firehose->setSkinVolume({ skid => $skid, story_vol => $story_vol, other_vol => $other_vol });
+	}
+};
+
+1;
+

Modified: slashjp/trunk/plugins/FireHose/mysql_dump.sql
===================================================================
--- slashjp/trunk/plugins/FireHose/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: mysql_dump.sql,v 1.34 2007/09/26 21:25:50 jamiemccarthy Exp $
+# $Id$
 #
 INSERT INTO ajax_ops VALUES (NULL, 'firehose_fetch_text', 'Slash::FireHose', 'fetchItemText', 'ajax_user_static', 'createuse');
 INSERT INTO ajax_ops VALUES (NULL, 'firehose_reject', 'Slash::FireHose', 'rejectItem', 'ajax_admin_static', 'use');
@@ -25,13 +25,16 @@
 INSERT INTO ajax_ops VALUES (NULL, 'firehose_set_options', 'Slash::FireHose', 'ajaxFireHoseSetOptions', 'ajax_user_static', 'use');
 INSERT INTO vars (name, value, description) VALUES ('firehose_admindownclout', '0.5', 'Admin clout for downvotes can be reduced by specifying a number between 0 and 1');
 INSERT INTO vars (name, value, description) VALUES ('firehose_adminudcclout', '0.5', 'Admin clout for udc purposes (number between 0 and 1, probably');
+INSERT INTO vars (name, value, description) VALUES ('firehose_adminupclout', '0.5', 'Admin clout for upvotes can be reduced by specifying a number between 0 and 1');
 INSERT INTO vars (name, value, description) VALUES ('firehose_story_ignore_skids', '', 'list of skids that you want to not want created or shown as firehose entries.  Delimit skids with |');
 INSERT INTO vars (name, value, description) VALUES ('firehose_color_slices', '30|30|0.2|0.2|0.2|0.2|0.2|0.0', 'Number or percent of remaining stories at each color level separated by | 30|0.5|0.5 would mean 30 stories at the level of highest popularity and 50% at each of remainining stories at the next 2 levels');
+INSERT INTO vars (name, value, description) VALUES ('firehose_memcached_exptime', '600', 'Seconds to cache firehose data generally');
 INSERT INTO vars (name, value, description) VALUES ('firehose_slice_points', '290,240 220,200 185,175 155,138 102,93 30,25 0,-20 -60,-999999', 'Seven pairs of numbers: the entry score and minimum score for each color slice (last min should be large negative)');
 INSERT INTO vars (name, value, description) VALUES ('firehose_spam_score', '-50', 'Popularity score assigned to all firehose items with is_spam=yes');
 INSERT INTO vars (name, value, description) VALUES ('firehose_color_labels', 'red|orange|yellow|green|blue|purple|violet|black', 'Firehose color labels');
 INSERT INTO vars (name, value, description) VALUES ('firehose_anonval_param', '', 'String needed to be passed in anonval form param to validate requests, set to a string to enforce this validation');
 INSERT INTO vars (name, value, description) VALUES ('firehose_logging', '0', 'Log firehose usage info?');
+INSERT INTO vars (name, value, description) VALUES ('firehose_mcd_disp', '1', 'Cache dispFireHose results');
 
 INSERT INTO firehose_tab VALUES (1,0,'Firehose','','createtime','DESC','indigo','fulltitle');
 INSERT INTO firehose_tab VALUES (2,0,'Slashdot','story','createtime','DESC','black','full');

Modified: slashjp/trunk/plugins/FireHose/mysql_schema.sql
===================================================================
--- slashjp/trunk/plugins/FireHose/mysql_schema.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/mysql_schema.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: mysql_schema.sql,v 1.22 2007/09/04 07:16:37 pudge Exp $
+# $Id$
 #
 DROP TABLE IF EXISTS firehose;
 CREATE TABLE firehose (
@@ -7,10 +7,11 @@
 	uid mediumint(8) unsigned NOT NULL default '0',
 	globjid int unsigned NOT NULL default '0',
 	discussion mediumint UNSIGNED NOT NULL default '0',
-	type ENUM("submission","journal","bookmark","feed","story","vendor","misc") default 'submission',
+	type ENUM("submission","journal","bookmark","feed","story","vendor","misc", "comment", "discussion","project") default 'submission',
 	createtime datetime NOT NULL default '0000-00-00 00:00:00',
 	popularity float NOT NULL default '0',
 	editorpop float NOT NULL default '0',
+	neediness float NOT NULL default '0',
 	activity float NOT NULL default '0',
 	accepted enum('no','yes') default 'no',
 	rejected enum('no','yes') default 'no',
@@ -19,7 +20,7 @@
 	is_spam enum('no', 'yes') default 'no',
 	primaryskid smallint(5) default '0',
 	tid smallint(6) default '0',
-	srcid mediumint(8) unsigned NOT NULL default '0',
+	srcid int(8) unsigned NOT NULL default '0',
 	url_id mediumint(8) unsigned NOT NULL default '0',
 	toptags varchar(255) default '',
 	email varchar(255) NOT NULL default '',
@@ -40,7 +41,9 @@
 	PRIMARY KEY (id),
 	UNIQUE globjid (globjid),
 	KEY createtime (createtime),
-	KEY popularity (popularity)
+	KEY popularity (popularity),
+	KEY neediness (neediness),
+	KEY url_id (url_id)
 ) TYPE=InnoDB;
 
 # The table giving an Object's Generally Accepted Story Publication Time
@@ -98,3 +101,10 @@
 	PRIMARY KEY (id)
 );
 
+DROP TABLE IF EXISTS firehose_skin_volume;
+CREATE TABLE firehose_skin_volume(
+	skid SMALLINT UNSIGNED NOT NULL,
+	story_vol MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL,
+	other_vol MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL,
+	PRIMARY KEY (skid)
+);

Modified: slashjp/trunk/plugins/FireHose/set_color_ranges.pl
===================================================================
--- slashjp/trunk/plugins/FireHose/set_color_ranges.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/set_color_ranges.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: set_color_ranges.pl,v 1.7 2007/04/25 18:25:16 jamiemccarthy Exp $
+# $Id$
 
 use strict;
 

Modified: slashjp/trunk/plugins/FireHose/templates/admin_extras;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/admin_extras;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/admin_extras;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -70,4 +70,4 @@
 	</table>
 [% END %]
 __version__
-$Id: admin_extras;misc;default,v 1.11 2007/08/07 21:00:22 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/adv_pref_firehose;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/adv_pref_firehose;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/adv_pref_firehose;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -30,4 +30,4 @@
 </div>
 [% END %]
 __version__
-$Id: adv_pref_firehose;misc;default,v 1.12 2007/05/09 18:51:57 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/data;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/data;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/data;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -32,7 +32,7 @@
 		Bookmark
 	[% ELSIF item.type == "feed" %]
 		From feed
-	[% ELSE %]
+	[% ELSIF item.type != "comment" %]
 		Submitted
 	[% END %]
 	[%- IF adminmode && item.type == "submission" %]</a>[% END -%]
@@ -72,7 +72,16 @@
 	[% IF extras && adminmode && num_with_ipid != '0' %]
 		([% accepted_from_ipid %]/[% num_with_ipid %])
 	[% END %]
-	[% user.aton %] <span id="fhtime-[% item.id %]">[% Slash.timeCalc(item.createtime) %]</span></b><br>
+	[% user.aton %] <span id="fhtime-[% item.id %]">[% Slash.timeCalc(item.createtime) %]</span></b>
+	[% IF item.type == "comment" %]
+		(<a href="[% gSkin.rootdir %]/comments.pl?sid=[% item.discussion %]&amp;cid=[% item.srcid %]">#[% item.srcid %]</a>)
+	[% END %]
+	<br>
+	[% IF item.type == "comment";
+		com = Slash.db.getComment(item.srcid);
+		disc = Slash.db.getDiscussion(com.sid); %]
+		Attached to: <a href="[% disc.url %]">[% disc.title | strip_literal %]</a><br>
+	[% END %]
 		[% IF constants.use_dept && item.dept %]<strong>from the <b>[% item.dept %]</b> dept.</strong>[% END %]
 	[% IF !hidediv %]
 
@@ -98,18 +107,25 @@
 		[% IF !contentsonly %]
 		<span id="firehose_more">
 		[% END %]
-		[% label = "Get more &raquo;" %]
+		[% IF !need_label;
+			label = "more &rsaquo;";
+		   END;
+		%]
 		[% IF day_label && day_count && options.duration != -1;
-			label = day_count _ " more &raquo;";
+			IF need_day_label;
+				label = $day_label _ " ";
+			ELSE;
+				label = label _ day_count _ " more &rsaquo;";
+			END;
 		   ELSIF future_count > 0 ;
 		   	IF options.duration == -1;
-			        label = future_count _ " more &raquo;";
+			        label = future_count _ " more &rsaquo;";
 			ELSE;
-			        label = future_count _ " more &raquo;";
+			        label = future_count _ " more &rsaquo;";
 			END;
 		   ELSIF future_count <= 0 ;
-		   	IF !options.startdate && options.duration != -1 && options.orderby == "createtime";
-			   	label = "Get more...";
+			IF options.duration != -1 && options.orderby == "createtime";
+				label = "more &rsaquo;";
 				extra_onclick = 'firehose_set_options(\'duration\', -1); ';
 			ELSIF options.orderby != "createtime";
 				fh = Slash.getObject("Slash::FireHose") 
@@ -129,12 +145,16 @@
 		[% ELSE %]
 			<a href="#" onclick="[% extra_onclick %] firehose_more(); return false;">[% label %]</a>
 		[% END %]
+		<span class="busy" style="display:none"><img src="[% constants.imagedir %]/spinner2.gif"></span>
 		[% IF !contentsonly %]
 		</span>
 		[% END %]
 [% CASE 'notavailable' %]
 	The item you're trying to view either does not exist, or is not viewable to you.
+[% CASE 'metamod_msg' %]
+For [% constants.sitename %]'s moderation system to function properly, we need your help.  Below are a number of random user comments in our system.  You are asked to decide if these are good or bad.  Clicking the + and - indicates that you think that a comment is good or bad.  You are welcome to skip any comment that you are unsure about.  What is most important is that you are objective and honest- a comment that you mark with the '+' means that you think that other [% constants.sitename %] readers would benefit from this comment.  Don't hesitate to flag mediocrity with the '-' graphic either.  The only way the system gets smarter is if you are honest, objective and a little bit harsh.
+
 [% END %]
 
 __version__
-$Id: data;firehose;default,v 1.22 2007/09/25 16:25:48 scc Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/daybreak;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/daybreak;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/daybreak;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -20,10 +20,10 @@
 [% IF fh_page == "users.pl"; day_page = "firehose.pl"; END %]
 [% index_extra = form.index ? "&amp;index=1" : "" %]
 <div align="center" class="daybreak" id="[% id %]">
-	[% last_days = Slash.getOlderDaysFromDay(last_day, 0, 0, { skip_add_today => 1, show_future_days => 1 }) %]
-	[% cur_days = Slash.getOlderDaysFromDay(cur_day, 0, 0, { skip_add_today => 1, show_future_days => 1 }) %]
+	[% last_days = Slash.getOlderDaysFromDay(last_day, 0, 0, { skip_add_today => 1, show_future_days => 1, force => 1 }) %]
+	[% cur_days = Slash.getOlderDaysFromDay(cur_day, 0, 0, { skip_add_today => 1, show_future_days => 1, force => 1 }) %]
 	<a onclick="firehose_set_options('issue', '[% last_day %]'); return false;" href="[% gSkin.rootdir %]/[% day_page %]?[% f = fh.genFireHoseParams(options, { startdate => last_day, duration => 1}); f; %][% index_extra %]">[% last_days.0.1 %]</a><br>
 	<a onclick="firehose_set_options('issue', '[% cur_day %]'); return false;"  href="[% gSkin.rootdir %]/[% day_page %]?[% f = fh.genFireHoseParams(options, {startdate => cur_day, duration => 1 }); f; %][% index_extra %]">[% cur_days.0.1 %]</a><br>
 </div>
 __version__
-$Id: daybreak;firehose;default,v 1.9 2007/09/14 23:43:27 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/dispFireHose;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/dispFireHose;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/dispFireHose;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -65,9 +65,9 @@
 [% the_user = Slash.db.getUser(item.uid) %]
 [% IF full %]
 [% IF divwrapper %]
-<div id="firehose-[% item.id %]" class="[% IF mode == "full" %]article[% ELSE %]briefarticle[% END %][% IF adminmode == 1 %] adminmode[% ELSE %] usermode[% END %]">
+<div id="firehose-[% item.id %]"[% IF item.type %] type="[% item.type %]"[% END %] class="[% IF mode == "full" %]article[% ELSE %]briefarticle[% END %][% IF adminmode == 1 %] adminmode[% ELSE %] usermode[% END %]">
 [% END %]
-	[% PROCESS formatHoseTitle the_user = the_user item = item url = url adminmode=adminmode options = options %]
+	[% PROCESS formatHoseTitle the_user = the_user item = item url = url adminmode=adminmode options = options link_url = link_url %]
 	[% title_type = item.type == "story" ? "story" : "firehose" %]
 	[% PROCESS titlebar h3id="title-" _ item.id id="" future = future title_type = title_type title_type_id = "ttype-" _ item.id options = options %]
 [% END %]
@@ -90,10 +90,15 @@
 			   PROCESS formatHoseIntro; 
 			%]
 			[% introtext %]
-			[% IF view_mode && item.media %]
+			[% IF view_mode %]
+				[% IF item.bodytext %]
+					[% item.bodytext %]
+				[% END %]
+				[% IF item.media %]
 				<div class="media">
 					[% item.media %]
 				</div>
+				[% END %]
 			[% END %]
 			[% END %]
 		</div>
@@ -107,7 +112,7 @@
 			[% END %]
 [% IF full %]
 		[% IF (future || item.type=="story") %]<div class="whitewash">[% END %]
-		[% PROCESS tagsfirehosedivtagbox id = item.id  tags_top = tags_top vote = vote options = options item = item %]
+		[% PROCESS tag_widget id = item.id  top_tags = top_tags system_tags = system_tags vote = vote options = options item = item %]
 		[% IF (future || item.type=="story") %]</div>[% END %]
 [% IF divwrapper; IF storylinkwrapper %]
 <div class="storylinks">
@@ -115,8 +120,8 @@
 		<ul>
 			<li class="more"><b>
 			[% link_url = firehose.linkFireHose(item) %]
-			[% IF item.discussion %]
-				<a href="[% link_url %]">Read More</a>
+			[% IF item.discussion || item.type == "comment" %]
+				<a href="[% link_url %]">[% IF form.metamod %]Context[% ELSE %]Read More[% END %]</a>
 			[% ELSE %]
 				Nothing More
 			[% END %]
@@ -138,4 +143,4 @@
 [% END %]
 [% END %]
 __version__
-$Id: dispFireHose;firehose;default,v 1.62 2007/09/04 20:53:21 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/dispTopicFireHose;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/dispTopicFireHose;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/dispTopicFireHose;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -18,7 +18,7 @@
 	story = Slash.db.getStory(item.srcid);
 	
  END %]
-[% IF item.thumb && ((item.type == "story" && (!story.thumb_signoff_needed || adminmode)) || (item.type == "submission" && adminmode)) %]
+[% IF item.thumb && !(user.noicons || user.simpledesign || user.lowbandwidth || user.pda) && ((item.type == "story" && (!story.thumb_signoff_needed || adminmode)) || (item.type == "submission" && adminmode)) %]
 	[% file = Slash.db.getStaticFile(item.thumb); %]
 	[% fh = Slash.getObject("Slash::FireHose");
 	   link_url = fh.linkFireHose(item);
@@ -33,4 +33,4 @@
 	</a>
 [% END %]
 __version__
-$Id: $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/fhadvprefpane;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/fhadvprefpane;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/fhadvprefpane;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -155,4 +155,4 @@
 </div>
 
 __version__
-$Id: fhadvprefpane;misc;default,v 1.17 2007/08/15 14:23:40 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/fireHoseForm;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/fireHoseForm;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/fireHoseForm;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -52,4 +52,4 @@
 </script>
 [% END %]
 __version__
-$Id: fireHoseForm;misc;default,v 1.9 2006/12/19 22:17:55 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/firehose_options;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/firehose_options;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/firehose_options;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -49,4 +49,4 @@
 [% END %]
 
 __version__
-$Id: firehose_options;misc;default,v 1.5 2007/08/15 03:08:50 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/firehose_pages;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/firehose_pages;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/firehose_pages;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -76,4 +76,4 @@
 __seclev__
 10000
 __version__
-$Id: firehose_pages;misc;default,v 1.14 2007/09/04 20:53:21 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/firehose_tabs;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/firehose_tabs;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/firehose_tabs;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -22,6 +22,12 @@
 	rss_param_str = rss_param_str _ "&amp;=" _ param;
 	rss_param_str = rss_param_str _ "=" _ Slash.strip_attribute(options.${rss_options.$param});
 END %]
+[% rss_skin_pre = "";
+   IF (section && section != constants.mainpage_skid);
+	   rss_skin = Slash.db.getSkin(section);
+	   rss_skin_pre = rss_skin.name _ "_";
+   END;
+%]
 [% END %]
 [% active_set = 0; %]
 [% UNLESS nodiv %]<ul class="menu" id="fhtablist">[% END %]
@@ -35,17 +41,17 @@
 		Slash.createSelect('tab', tabnames, { default => tab_current, return => 1, onchange => "firehose_set_options('tab', this.options[this.selectedIndex].value])"});
 	 ELSE %]
 	 	<li id="fhtab-section" [% IF options.sel_tabtype == "tabsection" && !active_set; active_set = 1; %]class="active"[% END %]>[% UNLESS options.sel_tabtype == "tabsection" %]<a href="/firehose.pl?tabtype=tabsection[% IF form.section %]&amp;section=[% form.section | strip_attribute %][% END %]"
- onclick="firehose_set_options('tabsection',firehose_settings.section); return false">Stories</a>[% END %]
+ [% IF !user.is_anon %]onclick="firehose_set_options('tabsection',firehose_settings.section); return false"[% END %]>Stories</a>[% END %]
 <noscript><form action="/firehose.pl" method="post"><input type="hidden" name="tabtype" value="tabsection"></noscript>
 [% fh.createSectionSelect(section) %]
 <noscript><input type="submit" name="change" value="change"></form></noscript>
-		[% IF options.sel_tabtype == "tabsection" && !user.is_anon && rss_param_str %]<a href="[% Slash.root2abs() %]/firehose.pl?op=rss&amp;content_type=rss[% rss_param_str %]&amp;logtoken=[% Slash.getPublicLogToken() | strip_paramattr %]" title="RSS for Section"><img src="[% constants.imagedir %]/feed.png" alt="rss"></a>[% END %]
+		[% IF options.sel_tabtype == "tabsection" %]<a href="[% Slash.root2abs() %]/[% rss_skin_pre %]firehose_stories.rss" title="RSS for Stories"><img src="[% constants.imagedir %]/feed.png" alt="rss"></a>[% END %]
 </li>
-	 	<li id="fhtab-recent" [% IF options.sel_tabtype == "tabrecent" && !active_set; active_set = 1; %]class="active"[% END %]><a href="/firehose.pl?tabtype=tabrecent[% IF form.section %]&amp;section=[% form.section | strip_attribute %][% END %]" onclick="firehose_set_options('tabtype','tabrecent'); return false">Recent</a>
-		[% IF options.sel_tabtype == "tabrecent" && !user.is_anon && rss_param_str %]<a href="[% Slash.root2abs() %]/firehose.pl?op=rss&amp;content_type=rss[% rss_param_str %]&amp;logtoken=[% Slash.getPublicLogToken() | strip_paramattr %]" title="RSS for Recent"><img src="[% constants.imagedir %]/feed.png" alt="rss"></a>[% END %]
+		<li id="fhtab-recent" [% IF options.sel_tabtype == "tabrecent" && !active_set; active_set = 1; %]class="active"[% END %]><a href="/firehose.pl?tabtype=tabrecent[% IF form.section %]&amp;section=[% form.section | strip_attribute %][% END %]" [% IF !user.is_anon %]onclick="firehose_set_options('tabtype','tabrecent'); return false"[% END %]>Recent</a>
+		[% IF options.sel_tabtype == "tabrecent"  %]<a href="[% Slash.root2abs() %]/[% rss_skin_pre %]firehose_recent.rss" "RSS for Recent"><img src="[% constants.imagedir %]/feed.png" alt="rss"></a>[% END %]
 </li>
-	 	<li id="fhtab-popular" [% IF options.sel_tabtype == "tabpopular" && !active_set; active_set = 1; %]class="active"[% END %]><a href="/firehose.pl?tabtype=tabpopular[% IF form.section %]&amp;section=[% form.section | strip_attribute %][% END %]" onclick="firehose_set_options('tabtype','tabpopular'); return false">Popular</a>
-		[% IF options.sel_tabtype == "tabpopular" && !user.is_anon && rss_param_str %]<a href="[% Slash.root2abs() %]/firehose.pl?op=rss&amp;content_type=rss[% rss_param_str %]&amp;logtoken=[% Slash.getPublicLogToken() | strip_paramattr %]" title="RSS for Popular"><img src="[% constants.imagedir %]/feed.png" alt="rss"></a>[% END %]
+		<li id="fhtab-popular" [% IF options.sel_tabtype == "tabpopular" && !active_set; active_set = 1; %]class="active"[% END %]><a href="/firehose.pl?tabtype=tabpopular[% IF form.section %]&amp;section=[% form.section | strip_attribute %][% END %]" [% IF !user.is_anon %]onclick="firehose_set_options('tabtype','tabpopular'); return false"[% END %]>Popular</a>
+		[% IF options.sel_tabtype == "tabpopular" %]<a href="[% Slash.root2abs() %]/[%rss_skin_pre %]firehose_popular.rss" title="RSS for Popular"><img src="[% constants.imagedir %]/feed.png" alt="rss"></a>[% END %]
 		</li>
 		[% IF !user.is_anon %]
 	 	<li id="fhtab-user" [% IF options.sel_tabtype == "tabuser" && !active_set; active_set = 1; %]class="active"[% END %]><a href="/firehose.pl?tabtype=tabuser[% IF form.section %]&amp;section=[% form.section | strip_attribute %][% END %]" onclick="firehose_set_options('tabtype','tabuser'); return false">[% user.nickname | strip_literal %]</a>
@@ -63,4 +69,4 @@
 	[% END %]
 [% UNLESS nodiv %]</ul>[% END %]
 __version__
-$Id: firehose_tabs;misc;default,v 1.19 2007/08/22 20:26:14 scc Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/firehose_tags_top;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/firehose_tags_top;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/firehose_tags_top;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -35,4 +35,4 @@
 __seclev__
 10000
 __version__
-$Id: firehose_tags_top;misc;default,v 1.22 2007/08/22 20:26:14 scc Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/firehose_usage;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/firehose_usage;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/firehose_usage;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -16,9 +16,9 @@
 <table>
 <tr><td></td><td>1 hr</td><td>1 day</td></tr>
 <tr><td>users</td><td>[% fh_users_hour %]</td><td>[% fh_users_day %]</td></tr>
-<tr><td>nods</td><td>[% nod_cnt_hour %]</td><td>[% nod_cnt %] </td></tr>
-<tr><td>nixes</td><td>[% nix_cnt_hour %]</td><td>[% nix_cnt %]</td></tr>
-<tr><td>tags</td><td>[% tag_cnt_hour %]  </td><td>[% tag_cnt %]</td></tr>
-<tr><td>objects</td><td>[% globjid_cnt_hour %]</td><td>[% globjid_cnt %]</td></tr>
+<tr><td>nods</td><td>[% nod_cnt_hour %]</td><td>[% nod_cnt_day %] </td></tr>
+<tr><td>nixes</td><td>[% nix_cnt_hour %]</td><td>[% nix_cnt_day %]</td></tr>
+<tr><td>tags</td><td>[% tag_cnt_hour %]  </td><td>[% tag_cnt_day %]</td></tr>
+<tr><td>objects</td><td>[% globjid_cnt_hour %]</td><td>[% globjid_cnt_day %]</td></tr>
 </table>
 

Modified: slashjp/trunk/plugins/FireHose/templates/formatHoseIntro;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/formatHoseIntro;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/formatHoseIntro;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -42,4 +42,4 @@
 %]
 
 __version__
-$Id: formatHoseIntro;misc;default,v 1.9 2007/09/04 20:53:21 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/formatHoseTitle;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/formatHoseTitle;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/formatHoseTitle;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -42,8 +42,22 @@
 END;
 
 title = item.title;
+IF item.type == "comment";
+	com = Slash.db.getComment(item.srcid);
+	score = com.points + com.tweak;
+	score = Slash.constrain_score(score);
+	reason = "";
+	IF com.reason;
+		reason = ", " _ constants.reasons.${com.reason}.name;
+	END;
+	title = "<span class='skin'>Comment:</span> " _ item.title _ " <span class='reason'>(Score " _ score _ reason _ ")</span>";
+END;
 onclick = "onclick=\"toggle_firehose_body('$item.id', $adminmode); return false\"";
-title_href="$gSkin.rootdir/firehose.pl?op=view&amp;id=$item.id";
+IF !link_url;
+	link_url = firehose.linkFireHose(item);
+END;
+title_href=link_url;
+
 IF form.index;
 	onclick="";
 	IF item.type == "story";
@@ -109,4 +123,4 @@
 __seclev__
 10000
 __version__
-$Id: formatHoseTitle;misc;default,v 1.36 2007/09/04 20:53:21 tvroom Exp $
+$Id$

Copied: slashjp/trunk/plugins/FireHose/templates/init_tagui;firehose;default (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/FireHose/templates/init_tagui;firehose;default)
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/init_tagui;firehose;default	                        (rev 0)
+++ slashjp/trunk/plugins/FireHose/templates/init_tagui;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,36 @@
+__section__
+default
+__description__
+To get something on this list, make sure it is in tagnames_param for
+posneg='+' or '-', and popup='1'.
+
+__title__
+Useless title to template
+__page__
+firehose
+__lang__
+en_US
+__name__
+init_tagui
+__seclev__
+10000
+__template__
+[% tags_reader = Slash.getObject('Slash::Tags', { db_type => 'reader' });
+   postags = tags_reader.getPositivePopupTags.sort;
+   negtags = tags_reader.getNegativePopupTags.sort;
+ -%]
+<script type="text/javascript">
+var suggestions_for_context = {
+	nod: '[% IF postags.size %][% FOR postag IN postags %][% postag %] [% END %][% ELSE %]fresh funny insightful interesting maybe[% END %]',
+	nix: '[% IF negtags.size %][% FOR negtag IN negtags %][% negtag %] [% END %][% ELSE %]binspam dupe notthebest offtopic slownewsday stale stupid[% END %]',
+[% IF user.is_admin %]
+	story: 'neverdisplay',
+	'default': 'hold quik back typo dupe',
+[% END %]
+	metanod: 'insightful interesting informative funny underrated',
+	metanix: 'offtopic flamebait troll redundant overrated'
+}
+</script>
+
+__version__
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/list;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/list;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/list;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -13,6 +13,10 @@
 __seclev__
 10000
 __template__
+[% IF form.metamod %]
+<div id="metamodwrap">
+[% END %]
+[% PROCESS init_tagui -%]
 [% firehose = Slash.getObject("Slash::FireHose"); %]
 [% IF env.script_name == "/firehose.pl" || form.ssi %]
 <script type="text/javascript">
@@ -45,11 +49,10 @@
 YAHOO.util.Event.addListener(window, "load", YAHOO.slashdot.SlashBoxApp.init);
 </script>
 [% ua = env.HTTP_USER_AGENT %]
-
 <div id="slashboxes">
 [% Slash.getAd(2) %]
 [% UNLESS user.noboxes %]
-  [% IF slashboxes && !(form.smalldevices || form.embed || (constants.smalldevices_ua_regex && ua.match(constants.smalldevices_ua_regex)));
+  [% IF slashboxes && !(form.smalldevices || form.embed || form.metamod || (constants.smalldevices_ua_regex && ua.match(constants.smalldevices_ua_regex)));
     slashboxes %]
   [% END %]
 [% END %]
@@ -57,12 +60,17 @@
 <div id="message">
 	<div class="content">
 		<p>
-		[% PROCESS rand_mesg %]
+		[% IF form.metamod %]
+			Meta-Moderation
+		[% ELSE %]
+			[% PROCESS rand_mesg %]
+		[% END %]
 		</p>
 	</div>
 </div>
 [% END %]
 <div id="messagearea"></div>
+[% IF form.metamod %][% Slash.getData('metamod_msg') %][% END %]
 [% login_block = BLOCK;
    this_fhfilter = form.fhfilter | fixparam;
    PROCESS userlogin_cover
@@ -83,7 +91,7 @@
 [% theupdatetime = Slash.timeCalc(Slash.db.getTime(), "%H:%M"); %]
 [% refresh_text = "";
    IF !user.is_anon;
-   	refresh_text = '<span style="font-size:60%">(<span id="pauseorplay">Paused</span> <span id="local_last_update_time">' _ theupdatetime _ '</span><span id="gmt_update_time"></span>)</span><span id="busy" class="hide"><img src="' _ constants.imagedir _ '/spinner.gif" alt="*"></span>';
+	refresh_text = '<span style="font-size:60%">(<span id="pauseorplay">Paused</span> <span id="local_last_update_time">' _ theupdatetime _ '</span><span id="gmt_update_time"></span>)</span><span class="busy" style="display:none"><img src="' _ constants.imagedir _ '/spinner.gif" alt="*"></span>';
    END;
 %]
 [% PROCESS titlebar title="$constants.sitename Firehose $refresh_text" %]
@@ -164,6 +172,7 @@
 	[% END %]
 	firehose_settings.issue = [% firehose.js_anon_dump(options.issue) %];
 	firehose_settings.section = [% firehose.js_anon_dump(section) %];
+	firehose_settings.metamod = [% form.metamod ? 1 : 0 %];
 	[% IF fh_page == "console.pl" %]
 		firehose_settings.pageval = 1;
 	[% ELSIF fh_page == "users.pl" %]
@@ -171,6 +180,9 @@
 	[% END %]
 
 	var firehose_action_time = 0;
+	[% IF options.pagesize == "large" && !form.metamod %]
+	firehose_more_increment = 15;
+	[% END %]
 	[% options_color = (options.color || user.firehose_color || "indigo") %]
 	var fh_color = [% firehose.js_anon_dump(options_color) %];
 	fh_colors = [% firehose.js_anon_dump(colors) %];
@@ -180,7 +192,7 @@
 	}
 	var fh_view_mode = [% firehose.js_anon_dump(options.mode) %];
 	firehose_settings.page = [% firehose.js_anon_dump(page) %];
-	[% IF form.embed %]
+	[% IF form.embed || form.tabtype == "1" %]
 	firehose_settings.is_embedded = 1; // defined in common.js
 	[% END %]
 	fh_is_admin = [% IF user.is_admin && !user.firehose_usermode %]1[% ELSE %]0[% END %];
@@ -197,11 +209,18 @@
 
 fh_ticksize = 15;
 firehose_slider_init();
+$(function(){
+	$('#firehoselist').click(firehose_click_tag);
+	firehose_init_tagui();
+});
 
 
 
 [% END %]
 </script>
+[% IF form.metamod %]
+</div>
+[% END %]
 
 __version__
-$Id: list;firehose;default,v 1.103 2007/10/11 22:14:06 pudge Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/nodnix_menus;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/nodnix_menus;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/nodnix_menus;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -42,5 +42,6 @@
   <div id="nix-completions" class="menu autocomplete"></div>
 </div>
 [% END %]
+
 __version__
-$Id: nodnix_menus;firehose;default,v 1.3 2007/07/18 18:22:21 scc Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/paginate;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/paginate;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/paginate;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -21,42 +21,47 @@
 [% index_extra = form.index ? "&amp;index=1" : "" %]
 [% idle_submit_plug = "";
    IF gSkin.name == "idle";
-   	idle_submit_plug = '<span class="inactive"><a href="' _ gSkin.rootdir _ '/submit.pl?primaryskid=' _ gSkin.skid _ '">Submit Idle Story</a></span>';
+   	idle_submit_plug = '<span class="nbutton" style="margin-left: 1em"><p><b><a href="' _ gSkin.rootdir _ '/submit.pl?primaryskid=' _ gSkin.skid _ '">Submit Idle Story</a></b></p></span>';
    END;
 
 %]
 
-
 [% IF !contentsonly %]
 <div class="paginate" [% IF divid %]id="[% divid %]"[% END %]>
 <div class="menu" [% IF ulid %]id="[% ulid %]"[% END %]>
 [% END %]
+[% IF form.metamod %]
+	You are welcome to do <a href="#" onclick="firehose_more(); return false">more than 10</a> metamods per day but note that those votes will weigh less.
+[% ELSE %]
+[% IF options.duration == 7 && !options.startdate %]
+	[% day = Slash.db.getDay(0);
+		got_more_link = 0;
+	%]
 
-[% IF options.duration == 7 && !options.startdate %]
-	[% day = Slash.db.getDay(0) %]
-	<span class="inactive">
+	<span class="[% IF day!=last_day %]in[% END %]active">
 		<a href="[% gSkin.rootdir %]/[% day_page %]?[% f = fh.genFireHoseParams(options, { startdate => '', duration => 7 }); f; %][% IF form.index %]&amp;index=1[% END %]">Today</a>
+		[% IF day == last_day;
+			got_more_link = 1;
+		%]
+			[% Slash.getData('firehose_more_link', firehose_more_data, 'firehose'); %]
+		[% END %]
 	</span>
 	[% IF options.orderby == "createtime";
 		 max_days_ahead = options.smalldevices ? 1 : 2;
-		days = Slash.getOlderDaysFromDay(last_day, -1, max_days_ahead, { "show_future_days" => 1, skip_add_today => 1 }); 
+		days = Slash.getOlderDaysFromDay(last_day, -1, max_days_ahead, { skip_add_today => 1, skip_future => 1 }); 
 	   ELSE;
 		max_days_ahead = options.smalldevices ? 2 : 3;
-		days = Slash.getOlderDaysFromDay(day, 1, max_days_ahead, { "show_future_days" => 1, skip_add_today => 1 }); 
+		days = Slash.getOlderDaysFromDay(day, 1, max_days_ahead, {  skip_add_today => 1, skip_future => 1 });
 	   END;
 	%]
 		[%
-		got_more_link = 0;
 		FOREACH cur_day = days;
 		%]
-		<span class="[% IF cur_day.0 != last_day %]in[% END %]active">
+		<span class="[% IF (cur_day.0 != last_day || options.orderby != "createtime") || firehose_more_data.future_count <= 0 %]in[% END %]active">
 			<a onclick="firehose_set_options('issue','[% cur_day.0 %]'); return false;" href="[% gSkin.rootdir %]/[% day_page %]?[% f = fh.genFireHoseParams(options, { startdate => cur_day.0, duration => 1}); f; %][% index_extra %]">[% cur_day.1 | strip_literal %]</a>
-				[% IF firehose_more_data.day_num == cur_day.0 %]
+				[% IF firehose_more_data.day_num == cur_day.0 && firehose_more_data.future_count >=0 %]
 					[% Slash.getData('firehose_more_link', firehose_more_data, 'firehose'); %]
 					[% got_more_link = 1; %]
-				[% ELSIF firehose_more_data.future_count <= 0 && cur_day.0 == last_day %]
-					[% Slash.getData('firehose_more_link', firehose_more_data, 'firehose'); %]
-					[% got_more_link = 1; %]
 				[% END %]
 		</span>
 		[% END %]
@@ -64,11 +69,14 @@
 		<span class="active">
 			[% IF options.orderby != "createtime" %]
 				<a href="#" onclick="firehose_slider_set_color('[% options.color %]'); return false">[% options.color.ucfirst %]</a>
+			[% ELSIF firehose_more_data.future_count <=0  %]
+				Archive
+			[% ELSE %]
+				[% firehose_more_data.need_day_label = 1 %]
 			[% END %]
 			[% Slash.getData('firehose_more_link', firehose_more_data, 'firehose'); %]
 		</span>
 		[% END %]
-		[% idle_submit_plug %]
 [% ELSIF options.startdate && options.duration == 1;
 	day = day || options.startdate;
 	day = day.replace('-','');
@@ -79,7 +87,7 @@
 	[% FOREACH cur_day = days;
 		IF day == cur_day.0; %]
 			<span class="active">
-				<a onclick="firehose_set_options('issue','[% cur_day.0 %]'); return false;" href="[% gSkin.rootdir %]/[% day_page %]?[% f = fh.genFireHoseParams(options, { startdate => cur_day.0, duration => 1}); f; %][% index_extra %]">[% cur_day.1 | strip_literal %]</a>
+				<a onclick="firehose_set_options('issue','[% cur_day.0 %]'); return false;" href="[% gSkin.rootdir %]/[% day_page %]?[% f = fh.genFireHoseParams(options, { startdate => cur_day.0, duration => 1}); f; %][% index_extra %]">[% cur_day.1 | strip_literal %]</a> [% Slash.getData('firehose_more_link', firehose_more_data, 'firehose'); %]
 			</span>
 		[% ELSE %]
 			<span class="inactive">
@@ -91,8 +99,7 @@
 			</span>
 		[% END %]
 		
-[%	END %]
-	[% idle_submit_plug %]
+[% END %]
 [% ELSIF options.startdate && options.duration >= 28 && options.duration <= 31;
 	firehose = Slash.getObject("Slash::FireHose");
 	days = firehose.getOlderMonthsFromDay(options.startdate,-2, 2);
@@ -104,22 +111,21 @@
 			[% PROCESS firehose_pages page = page num_items = num_items day_page = fh_page options=options %]
 		</span>
 		[% ELSE %]
-		<span>
+		<span class="inactive">
 			<a href="[% gSkin.rootdir %]/[% day_page %]?startdate=[% cur_day.0 %]&amp;duration=[% cur_day.2 %]">[% cur_day.1 | strip_literal %]</a>
 		</span>
 		[%
 		END;
 	END;
-	idle_submit_plug;
 %]
-[% ELSIF options.duration == -1 && !options.startdate %]
+[% ELSIF options.duration == -1  %]
 	<span class="inactive">
-		<a href="[% gSkin.rootdir %]/[% day_page %]?[% f = fh.genFireHoseParams(options, { startdate => '', duration => 7}); f; %][% IF form.index %]index=1[% END %]">Today</a>
+		<a href="[% gSkin.rootdir %]/[% day_page %]?[% f = fh.genFireHoseParams(options, { startdate => '', duration => 7, no_label => "1"}); f; %][% IF form.index %]index=1[% END %]">Today</a>
+	</span>
 	<span class="active">
-		<a href="#">Archive</a> [% Slash.getData('firehose_more_link', firehose_more_data, 'firehose'); %]
+		Archive
+		[% Slash.getData('firehose_more_link', firehose_more_data, 'firehose'); %]
 	</span>
-	[% idle_submit_plug %]
-	</span>
 [% ELSE %]
 	[% time_label = "";
 	   IF options.duration == -1;
@@ -140,9 +146,13 @@
 
 	[% END %]
 [% END %]
+[% idle_submit_plug %]
+[% END %]
+
 [% IF !contentsonly %]
 </div>
 </div>
 [% END %]
+
 __version__
-$Id: paginate;firehose;default,v 1.28 2007/09/14 23:34:58 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/portalmap;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/portalmap;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/portalmap;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -21,4 +21,4 @@
 __seclev__
 500
 __version__
-$Id: portalmap;firehose;default,v 1.1 2007/02/23 02:47:36 scc Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/reject;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/reject;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/reject;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -15,4 +15,4 @@
 __template__
 <label class="reject" title="Reject this item"><input type="checkbox" value=[% id %] id="reject-[% id %]" onclick="firehose_reject(this)"><span id="reject-msg-[% id %]"></span></label>
 __version__
-$Id: reject;firehose;default,v 1.3 2006/08/30 16:13:26 lancelot Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/reject_firehose;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/reject_firehose;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/reject_firehose;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -15,4 +15,4 @@
 __template__
 <label class="reject" title="Reject this item"><input type="checkbox" value=[% id %] id="reject-[% id %]" onclick="firehose_reject(this)"><span id="reject-msg-[% id %]"></span></label>
 __version__
-$Id: reject_firehose;misc;default,v 1.2 2006/10/27 15:56:36 tvroom Exp $
+$Id$

Copied: slashjp/trunk/plugins/FireHose/templates/tag_widget;firehose;default (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/FireHose/templates/tag_widget;firehose;default)
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/tag_widget;firehose;default	                        (rev 0)
+++ slashjp/trunk/plugins/FireHose/templates/tag_widget;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,101 @@
+__section__
+default
+__description__
+This builds a tag-widget bound to a containing firehose entry.
+
+__title__
+Useless title to template
+__page__
+firehose
+__lang__
+en_US
+__name__
+tag_widget
+__seclev__
+10000
+__template__
+[% IF user.tags_canread_stories %]
+	[%# the nod/nix 'capsule' %]
+	[% IF !form.skipvote && !options.nothumbs && !skipvote %]
+	<div class="tags">
+		<span id="updown-[% item.id %]" class="vote[% IF vote == "down" %]ddown[% ELSIF vote == "up" %]dup[% END %]">
+			<a href="#" class="up" title="Vote this item up">+</a>
+			<a href="#" class="down" title="Vote this item down">-</a>
+		</span>
+	</div>
+	[% END %]
+
+	[% IF user.tags_canwrite_stories %]
+	[%# if you can tag... %]
+	<div class="tagshide" id="toggletags-body-[% id %]">
+		[% 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="#" onclick="firehose_get_admin_extras('[% item.id %]'); return false">Get extras</a></div>
+		[% END %]
+		<div id="toggletags-message-[% id %]" class="message"></div>
+	</div>
+
+	[%# the tag-widget itself %]
+	<div id="tag-widget-[% id %]" class="tag-widget-stub body-widget" init="context_timeout:15000">
+		[% IF user.is_admin && !user.firehose_usermode %]
+		<span class="admin-buttons">
+			[%# the note %]
+			<div class="note-wrapper[% IF !item.note %] no-note[% END %]">
+				[%# the note edit field (hidden by default) %]
+				<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="save" onclick="firehose_save_note('[% item.id %]')">
+				</span>
+				[%# the note button %]
+				<span class="admin-note">
+				<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>
+				</span>
+			</div>
+		</span>
+		[% END %]
+		[%# the disclosure triangle %]
+		<a class="edit-toggle" href="#" onclick="this.blur(); firehose_toggle_tagui(this); return false">
+			<span class="button collapse"></span>
+		</a>
+		[%# the tag input field %]
+		<form class="tag-editor" onsubmit="form_submit_tags(this, {fade_remove: 400, order: 'prepend', classes:'not-saved'}); return false">
+			<input class="tag-entry" type="text" size="10">
+			<span class="tag-server-busy"><img src="[% constants.imagedir %]/spinner2.gif"></span>
+		</form>
+		[%# the tag 'bars' %]
+		<div class="tag-display-set train">
+			<div class="tag-display-stub" context="user" init="legend:'my&nbsp;tags'"></div>
+			<div class="tag-display-stub" context="top" init="legend:'top&nbsp;tags'">[% top_tags %]</div>
+			<div class="tag-display-stub" context="system" init="legend:'system&nbsp;tags'">[% system_tags %]</div>
+			[%- IF item.type == "story" &&
+				constants.signoff_use &&
+				((user.is_admin && !user.firehose_usermode) || user.acl.signoff_allowed) &&
+				! Slash.db.hasUserSignedStory(item.srcid, user.uid) -%]
+				<div class="tag-display-stub" context="signoff" stoid="[% item.srcid %]" init="legend:'signoff', menu:false">unsigned</div>
+			[%- END -%]
+		</div>
+		[%# the suggestions bar %]
+		<div class="related">
+			<div class="tag-display-stub" context="related" init="legend:'suggestions', menu:false"></div>
+		</div>
+	</div>
+	[% ELSE %]
+	[%# ...else if you _can't_ tag, it's all easy %]
+	<div id="tag-widget-[% id %]" class="tag-widget-stub body-widget">
+		[%# the disclosure triangle %]
+		<a class="edit-toggle"
+		[%- IF user.is_anon			%] href="#" onclick="this.blur(); show_login_box(); return false"
+		[%- ELSE				%] href="[% gSkin.rootdir %]/subscribe.pl"
+		[%- END %]><span class="button collapse"></span></a>
+		[%# the tag 'bars' %]
+		<div class="tag-display-set train">
+			<div class="tag-display-stub" context="top" init="legend:'top&nbsp;tags'">[% top_tags %]</div>
+			<div class="tag-display-stub" context="system" init="legend:'system&nbsp;tags'">[% system_tags %]</div>
+		</div>
+	</div>
+	[% END %]
+[% END %]
+__version__
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivadmin;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivadmin;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivadmin;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -13,7 +13,7 @@
 tagsfirehosedivadmin
 __template__
 
-[% IF user.is_admin && !user.firehose_usermode %]
+[% IF 0 && user.is_admin && !user.firehose_usermode %]
 
 [% 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')">
@@ -26,4 +26,4 @@
 __seclev__
 10000
 __version__
-$Id: tagsfirehosedivadmin;misc;default,v 1.2 2006/10/31 17:05:38 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivtagbox;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivtagbox;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivtagbox;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -17,10 +17,10 @@
 <div id="tagbox-[% id %]" class="tags">
 [% IF !form.skipvote && !options.nothumbs && !skipvote %]
 	<span id="updown-[% item.id %]" class="vote[% IF vote == "down" %]ddown[% ELSIF vote == "up" %]dup[% END %]">
-	  <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="#" 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>
+	  <!-- click test--> <a href="#" onclick="firehose_up_down('[% item.id %]','+','[% item.type %]'); return false" class="up" title="Vote this item up"
+	     [% IF !user.is_anon && !user.is_admin %]onMouseDown="show_nod_menu(this, '[% item.id %]')" onMouseOver="show_nod_menu(this, '[% item.id %]', 1200, 5200)" onMouseOut="dont_show_nodnix_menu()"[% END %]>+</a>
+	  <!-- click test2 --> <a href="#" onclick="firehose_up_down('[% item.id %]','-','[% item.type %]'); return false" class="down" title="Vote this item down"
+	     [% IF !user.is_anon && !user.is_admin %]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">
@@ -31,7 +31,7 @@
 		[%- 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}); return false">feedback</a></span></span>
 		[% END %]
-		[% IF user.is_admin && !user.firehose_usermode -%]
+		[% IF 0 && !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 %]" href="#" onclick="firehose_open_note('[% item.id %]'); return false">[% IF !item.note  %]Note[% END %][% item.note | strip_literal %]</a>)</i>
 		[%- END -%]
 	</div>
@@ -46,7 +46,7 @@
 		</div>
 	[% END %]
 	[%# The tags-user-# div starts out empty, we only populate it if the user expands the toggletags-body-# div, because it requires a read of the user's tags and a write to generate a reskey. %]
-		<div id="tags-user-[% id %]" class="taguser"></div>
+		[% IF ! user.is_admin %]<div id="tags-user-[% id %]" class="taguser"></div>[% END %]
 	[% 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="#" onclick="firehose_get_admin_extras('[% item.id %]'); return false">Get extras</a></div>
@@ -59,4 +59,4 @@
 __seclev__
 10000
 __version__
-$Id: tagsfirehosedivtagbox;misc;default,v 1.35 2007/08/22 20:57:09 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivuser;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivuser;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/tagsfirehosedivuser;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 default
 __description__
 id = id
-newtagspreloadtext = text to preload the newtags-# field with
+user_tags = text to preload the newtags-# field with
 __title__
 
 __page__
@@ -14,10 +14,10 @@
 __template__
 
 [% PROCESS ajax_reskey_tag reskey_label => 'newtags-reskey-' _ id, reskey_name => 'ajax_tags_write' %]
-<input type="text" class="slashdot-tag-completer" id="newtags-[% id %]" name="newtags-[% id %]" value="[% newtagspreloadtext | strip_attribute %]" size=50 maxlength=60 autocomplete="off" onkeyup="handleEnter(event, tagsCreateForFirehose, '[% id %]','firehose')" onfocus="focusCompleter(this,'[% id %]','[% user.is_admin && !user.firehose_usermode %]','firehose', 0)">
+<input type="text" class="slashdot-tag-completer" id="newtags-[% id %]" name="newtags-[% id %]" value="[% user_tags | strip_attribute %]" size=50 maxlength=60 autocomplete="off" onkeyup="handleEnter(event, tagsCreateForFirehose, '[% id %]','firehose')" onfocus="focusCompleter(this,'[% id %]','[% user.is_admin && !user.firehose_usermode %]','firehose', 0)">
 <input type="button" value="Tag" onclick="tagsCreateForFirehose('[% id %]')" class="button">
 
 __seclev__
 10000
 __version__
-$Id: tagsfirehosedivuser;misc;default,v 1.7 2007/08/22 20:26:14 scc Exp $
+$Id$

Modified: slashjp/trunk/plugins/FireHose/templates/tagsnodnixuser;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/tagsnodnixuser;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/tagsnodnixuser;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 default
 __description__
 id = id
-newtagspreloadtext = text to preload the newtags-# field with
+user_tags = text to preload the newtags-# field with
 
 WARNING: keep the related string in nodnix.js in sync with the <li> expansion, below
 __title__
@@ -14,10 +14,10 @@
 __name__
 tagsnodnixuser
 __template__
-[% FOREACH tag = newtagspreloadtext.split(' ') %]
+[% FOREACH tag = user_tags.split(' ') %]
 <li>[% tag %]<span class="tag-actions"><a class="not-tag" onmousedown="nodnix_not_tag('[% tag %]'); return false" href="#">!</a> <a class="del-tag" onmousedown="nodnix_del_tag('[% tag %]'); return false" href="#">x</a></span></li>
 [% END %]
 __seclev__
 10000
 __version__
-$Id: tagsnodnixuser;misc;default,v 1.4 2008/03/03 20:54:00 scc Exp $
+$Id$

Deleted: slashjp/trunk/plugins/FireHose/templates/tagstack;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/tagstack;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/tagstack;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,23 +0,0 @@
-__section__
-default
-__description__
-This div gets filled in with the results of tag queries, and appears near nod/nix menus.
-
-__title__
-Useless title to template
-__page__
-firehose
-__lang__
-en_US
-__name__
-tagstack
-__seclev__
-10000
-__template__
-<div id="tagstack">
-  <ul id="stack-system">system tags</ul>
-  <ul id="stack-top">top tags</ul>
-  <ul id="stack-user">my tags</ul>
-</div>
-__version__
-$Id: tagstack;firehose;default,v 1.2 2008/02/19 16:43:30 scc Exp $

Modified: slashjp/trunk/plugins/FireHose/templates/view;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/view;firehose;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/FireHose/templates/view;firehose;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -28,5 +28,13 @@
 		[% firehosetext %]
 	</div>
 </div>
+[% PROCESS init_tagui %]
+<script type="text/javascript">
+$(function(){
+	firehose_init_tagui(
+		$('#firehose > .view > .head > [id^=firehose-]')
+			.click(firehose_click_tag) );
+});
+</script>
 __version__
-$Id: view;firehose;default,v 1.8 2007/10/11 22:14:06 pudge Exp $
+$Id$

Modified: slashjp/trunk/plugins/Hof/Hof.pm
===================================================================
--- slashjp/trunk/plugins/Hof/Hof.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Hof/Hof.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,17 +1,15 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Hof;
 
 use strict;
 use Slash::Utility;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: And where would a giant nerd be? THE LIBRARY!
 
@@ -110,7 +108,7 @@
 	my($self) = @_;
 	my $authors = $self->sqlSelectAll('storycount, nickname, homepage',
 		'authors_cache', '',
-		'GROUP BY uid ORDER BY storycount DESC LIMIT 10'
+		'ORDER BY storycount DESC LIMIT 10'
 	);
 	return $authors;
 }
@@ -161,6 +159,7 @@
 # time to finish this right now so I've also commented out the code
 # that calls this method, see themes/slashcode/htdocs/hof.pl.
 # - Jamie 2001/07/12
+# Adding "XXX" just in case we ever, you know, fix bugs - Jamie 2008/07/15
 sub getCommentsTop {
 	my($self, $sid) = @_;
 	my $user = getCurrentUser();
@@ -172,12 +171,10 @@
 		pid, subject, date, time, comments.uid, cid, points',
 		'stories, comments, users',
 		$where,
-		' ORDER BY points DESC, date DESC LIMIT 10 '
+		'ORDER BY points DESC, date DESC LIMIT 10'
 	);
 
 	my $reader = getObject('Slash::DB', { db_type => 'reader' });
-	# XXXSKIN - not sure if this is the best way to do this, but
-	# i figure it is fine ... please change or advise if should be changed ...
 	for (@$stories) {
 		$_->[0] = $reader->getSkin($_->[0])->{name};
 	}

Modified: slashjp/trunk/plugins/Hof/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Hof/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Hof/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Hof',
-    'VERSION_FROM' => 'Hof.pm', # finds $VERSION
     'PM'	=> { 'Hof.pm' => '$(INST_LIBDIR)/Hof.pm' },
 );

Modified: slashjp/trunk/plugins/HumanConf/HumanConf.pm
===================================================================
--- slashjp/trunk/plugins/HumanConf/HumanConf.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/HumanConf/HumanConf.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::HumanConf;
 
@@ -11,12 +10,10 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION);
-use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;

Modified: slashjp/trunk/plugins/HumanConf/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/HumanConf/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/HumanConf/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::HumanConf',
-    'VERSION_FROM' => 'HumanConf.pm', # finds $VERSION
     'PM'	=> {
     	'HumanConf.pm' => '$(INST_LIBDIR)/HumanConf.pm',
     },


Property changes on: slashjp/trunk/plugins/HumanConf/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/HumanConf/Static/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/HumanConf/Static/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/HumanConf/Static/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,5 +2,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::HumanConf::Static',
-    'VERSION_FROM' => 'Static.pm', # finds $VERSION
 );

Modified: slashjp/trunk/plugins/HumanConf/Static/Static.pm
===================================================================
--- slashjp/trunk/plugins/HumanConf/Static/Static.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/HumanConf/Static/Static.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::HumanConf::Static;
 
@@ -14,12 +13,11 @@
 use Slash;
 use Slash::Utility;
 
-use vars qw($VERSION);
 use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;
@@ -57,15 +55,19 @@
 	my $cursize = $self->getPoolSize();
 	if (!defined($want_delete_fraction)) {
 		# Delete at least enough to recycle the pool regularly.
-		# Since by default hc_maintain_pool runs 2 times an hour,
-		# the default fraction is enough to guarantee complete
-		# pool turnover every day.
+		# The default fraction is enough to guarantee the pool
+		# turns over once every 3 days.
+		my $turnover_secs = $constants->{hc_turnover_secs} || 86400*3;
 		# Note that $runs_per_hour should be coordinated with
 		# the timespec in the task .pl file;  there isn't a good
-		# way to do this at the moment.  Eventually we'll have
-		# DB-based timespecs and we can read that...
-		my $runs_per_hour = 2;
-		$want_delete_fraction = 1/($runs_per_hour*24)
+		# way to do this at the moment.  Maybe someday we'll have
+		# DB-based timespecs and we can read that.
+		my $runs_per_hour = 4;
+		# I'll spell out the arithmetic with intermediate variables
+		# for clarity.
+		my $secs_between_run = 3600/$runs_per_hour;
+		my $runs_for_turnover = $turnover_secs/$secs_between_run;
+		$want_delete_fraction = 1/$runs_for_turnover;
 	}
 	my $want_delete = int($cursize*$want_delete_fraction);
 		# Don't delete so many that the pool will get too empty,

Modified: slashjp/trunk/plugins/HumanConf/hc_maintain_pool.pl
===================================================================
--- slashjp/trunk/plugins/HumanConf/hc_maintain_pool.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/HumanConf/hc_maintain_pool.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -9,7 +9,7 @@
 
 use vars qw( %task $me $task_exit_flag );
 
-$task{$me}{timespec} = '10,40 * * * *';
+$task{$me}{timespec} = '10-59/15 * * * *';
 $task{$me}{timespec_panic_1} = '';
 $task{$me}{on_startup} = 1;
 $task{$me}{resource_locks} = getCurrentStatic('hc_cepstral') ? { cepstral => 1 } : { };

Modified: slashjp/trunk/plugins/HumanConf/mysql_dump
===================================================================
--- slashjp/trunk/plugins/HumanConf/mysql_dump	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/HumanConf/mysql_dump	2008-09-09 13:07:58 UTC (rev 742)
@@ -10,6 +10,7 @@
 INSERT INTO vars (name, value, description) VALUES ('hc_cepstral_voices', 'William', 'Space-sep list of Cepstral voices to use, if hc_cepstral is set');
 INSERT INTO vars (name, value, description) VALUES ('hc_fontpath', '/usr/share/fonts/truetype', 'GD::Text font_path');
 INSERT INTO vars (name, value, description) VALUES ('hc_formname_regex', '^(?:comments|(?:login|users)/(?:nu|mp))$', 'Formnames which (may) require HumanConf');
+INSERT INTO vars (name, value, description) VALUES ('hc_image_format','jpeg','Format for HC images (png, jpeg, etc.)');
 INSERT INTO vars (name, value, description) VALUES ('hc_maxkarma', '25', 'Maximum karma at which users need HumanConf (beyond this we assume they are human) - set large negative to exempt all logged-in users, set large positive if all users must comply');
 INSERT INTO vars (name, value, description) VALUES ('hc_q1_lettersomit', 'hlou', 'For question 1 (images), which letters should never appear?');
 INSERT INTO vars (name, value, description) VALUES ('hc_q1_linethick', '2', 'For question 1 (images), thickness of the lines that are drawn to confuse OCR');
@@ -28,5 +29,5 @@
 INSERT INTO vars (name, value, description) VALUES ('hc_sw_comments', '0', 'HumanConf switch for posting comments: 0=off, 1=anon only, 2=also logged-in with low karma');
 INSERT INTO vars (name, value, description) VALUES ('hc_sw_mailpasswd', '1', 'HumanConf switch for mailing a password');
 INSERT INTO vars (name, value, description) VALUES ('hc_sw_newuser', '1', 'HumanConf switch for creating a new user');
-INSERT INTO vars (name, value, description) VALUES ('hc_image_format','jpeg','Format for HC images (png, jpeg, etc.)');
+INSERT INTO vars (name, value, description) VALUES ('hc_turnover_secs', '259200', 'Seconds in which the entire humanconf pool should be replaced out');
 


Property changes on: slashjp/trunk/plugins/HumanConf/templates/data;humanconf;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Journal/Journal.pm
===================================================================
--- slashjp/trunk/plugins/Journal/Journal.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Journal/Journal.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Journal;
 
@@ -11,11 +10,10 @@
 use Slash::Constants qw(:messages);
 use Slash::Utility;
 
-use vars qw($VERSION);
-use base 'Exporter';
+use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # On a side note, I am not sure if I liked the way I named the methods either.
 # -Brian

Modified: slashjp/trunk/plugins/Journal/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Journal/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Journal/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Journal',
-    'VERSION_FROM' => 'Journal.pm', # finds $VERSION
     'PM'	=> { 'Journal.pm' => '$(INST_LIBDIR)/Journal.pm' },
 );


Property changes on: slashjp/trunk/plugins/Journal/templates/friendsview;journal;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Journal/templates/journalhead;journal;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Journal/templates/messagenew;journal;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Journal/templates/messagenew_subj;journal;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Journal/templates/meta;journal;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Journal/templates/pagination;journal;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Journal/templates/searchusers;journal;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Journal/templates/slashdot;journal;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Login/login.pl
===================================================================
--- slashjp/trunk/plugins/Login/login.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Login/login.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -239,6 +239,11 @@
 
 	my $user_send = $reader->getUser($uid);
 
+	if ($user->{acl}{nopasswd}) {
+		push @note, getData('mail_acl_nopasswd');
+		$error = 1;
+	}
+
 	if (!$error) {
 		# A user coming from a srcid that's been marked as not
 		# acceptable for posting from also does not get to
@@ -250,7 +255,7 @@
 		@srcids{keys %{$user->{srcids}}} = values %{$user->{srcids}};
 		delete $srcids{uid};
 
-		if ($reader->checkAL2(\%srcids, [qw( nopost nopostanon spammer )])) {
+		if ($reader->checkAL2(\%srcids, [qw( nopost nopostanon spammer openproxy )])) {
 			push @note, getData('mail_readonly');
 			$error = 1;
 

Modified: slashjp/trunk/plugins/Login/templates/data;login;default
===================================================================
--- slashjp/trunk/plugins/Login/templates/data;login;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Login/templates/data;login;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -112,6 +112,10 @@
 	password mailed to you</a>.
 
 
+[% CASE 'mail_acl_nopasswd' %]
+	[% returnme.data_constant = 1 %]
+	This account is not allowed to log in normally.  No password was mailed.
+
 [% CASE 'mail_nonickname' %]
 	[% returnme.data_constant = 1 %]
 	User was not found.  No password was mailed.


Property changes on: slashjp/trunk/plugins/Messages/DB/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/DB/MySQL/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Messages/DB/MySQL/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Messages/DB/MySQL/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Messages/DB/MySQL/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,5 +3,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Messages::DB::MySQL',
-    'VERSION_FROM' => 'MySQL.pm', # finds $VERSION
 );


Property changes on: slashjp/trunk/plugins/Messages/DB/MySQL/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Messages/DB/MySQL/MySQL.pm
===================================================================
--- slashjp/trunk/plugins/Messages/DB/MySQL/MySQL.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Messages/DB/MySQL/MySQL.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Messages::DB::MySQL;
 
@@ -24,14 +23,13 @@
 use Slash::DB;
 use Slash::Constants qw(:messages);
 use Slash::Utility;
-use Storable qw(freeze thaw);
+use Storable qw(nfreeze thaw);
 
-use vars '$VERSION';
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 my %descriptions = (
 	'deliverymodes'
@@ -195,7 +193,7 @@
 	my $prime = $self->{_drop_prime};
 
 	# fix scalar to be a ref for freezing
-	my $frozen = freeze(ref $message ? $message : \$message);
+	my $frozen = nfreeze(ref $message ? $message : \$message);
 	$self->sqlInsert($table, {
 		user	=> $user,
 		fuser	=> $fuser,


Property changes on: slashjp/trunk/plugins/Messages/DB/MySQL/MySQL.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Messages/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Messages/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Messages/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Messages',
-    'VERSION_FROM' => 'Messages.pm', # finds $VERSION
     'PM'	=> {
     	'Messages.pm'				=> '$(INST_LIBDIR)/Messages.pm',
     },


Property changes on: slashjp/trunk/plugins/Messages/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Messages/Messages.pm
===================================================================
--- slashjp/trunk/plugins/Messages/Messages.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Messages/Messages.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Messages;
 
@@ -35,13 +34,12 @@
 
 use strict;
 use base qw(Slash::Messages::DB::MySQL);
-use vars qw($VERSION);
 use Slash 2.003;	# require Slash 2.3.x
 use Slash::Constants ':messages';
 use Slash::Display;
 use Slash::Utility;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 
 #========================================================================
@@ -1134,7 +1132,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/plugins/Messages/Messages.pm
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/PLUGIN
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/dump
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/mysql_schema
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/commnew;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/commnew_sub;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/dailyheadlines;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/dailynews;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/data;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/display;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/display_prefs;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/emailsponsor;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/html_invalid;misc;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/html_invalid_subj;misc;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/journrep;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/journrep_subj;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/journuserboxes;misc;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/list_messages;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/messagenew;submit;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/messagenew_subj;submit;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/mod_msg;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/mod_msg_subj;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/msg_email;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/msg_email_subj;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/msg_m2;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/msg_m2_subj;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/msg_web_subj;messages;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/reply_msg;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/reply_msg_subj;comments;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Messages/templates/storynew;messages;default
===================================================================
--- slashjp/trunk/plugins/Messages/templates/storynew;messages;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Messages/templates/storynew;messages;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -27,4 +27,4 @@
 __seclev__
 500
 __version__
-$Id: storynew;messages;default,v 1.2 2007/07/31 17:28:24 entweichen Exp $
+$Id$

Modified: slashjp/trunk/plugins/Messages/templates/storynew_msg_subj;messages;default
===================================================================
--- slashjp/trunk/plugins/Messages/templates/storynew_msg_subj;messages;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Messages/templates/storynew_msg_subj;messages;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -15,4 +15,4 @@
 __seclev__
 500
 __version__
-$Id: storynew_msg_subj;messages;default,v 1.1 2007/07/31 18:11:43 entweichen Exp $
+$Id$


Property changes on: slashjp/trunk/plugins/Messages/templates/unmod_msg;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Messages/templates/unmod_msg_subj;comments;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Metamod/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Metamod/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Metamod',
-    'VERSION_FROM' => 'Metamod.pm', # finds $VERSION
     'PM'	=> {
     	'Metamod.pm' => '$(INST_LIBDIR)/Metamod.pm',
     },

Modified: slashjp/trunk/plugins/Metamod/Metamod.pm
===================================================================
--- slashjp/trunk/plugins/Metamod/Metamod.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/Metamod.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: Metamod.pm,v 1.7 2007/10/09 18:57:09 jamiemccarthy Exp $
 
 package Slash::Metamod;
 
@@ -11,12 +10,11 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION);
 use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision: 1.7 $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;

Modified: slashjp/trunk/plugins/Metamod/PLUGIN
===================================================================
--- slashjp/trunk/plugins/Metamod/PLUGIN	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/PLUGIN	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: PLUGIN,v 1.2 2006/10/26 17:33:04 jamiemccarthy Exp $
+# $Id$
 name=Metamod
 description="Metamoderation"
 htdoc=metamod.pl

Modified: slashjp/trunk/plugins/Metamod/Static/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Metamod/Static/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/Static/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,5 +2,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::Metamod::Static',
-    'VERSION_FROM' => 'Static.pm', # finds $VERSION
 );

Modified: slashjp/trunk/plugins/Metamod/Static/Static.pm
===================================================================
--- slashjp/trunk/plugins/Metamod/Static/Static.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/Static/Static.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,19 +1,17 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: Static.pm,v 1.4 2007/06/19 21:20:46 jamiemccarthy Exp $
 
 package Slash::Metamod::Static;
 
 use strict;
 use Slash::Utility;
 
-use vars qw($VERSION);
 use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision: 1.4 $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;

Modified: slashjp/trunk/plugins/Metamod/metamod.pl
===================================================================
--- slashjp/trunk/plugins/Metamod/metamod.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/metamod.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: metamod.pl,v 1.4 2006/10/26 17:33:04 jamiemccarthy Exp $
+# $Id$
 
 use strict;
 use Slash;
@@ -18,6 +18,10 @@
 	my $op = getCurrentForm('op') || '';
 	my $section = $slashdb->getSection($form->{section});
 
+	if ($user->{is_subscriber} && $constants->{plugin}{FireHose}) {
+		redirect("$constants->{rootdir}/firehose.pl?op=metamod");
+	}
+
 	header(getData('header'), $section->{section}) or return;
 
 	if (!$constants->{m1}) {

Modified: slashjp/trunk/plugins/Metamod/mysql_dump.sql
===================================================================
--- slashjp/trunk/plugins/Metamod/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: mysql_dump.sql,v 1.1 2006/09/03 15:46:00 jamiemccarthy Exp $
+# $Id$
 #
 
 INSERT INTO vars (name, value, description) VALUES ('m2', '0', 'Allows use of the metamoderation system');

Modified: slashjp/trunk/plugins/Metamod/mysql_schema.sql
===================================================================
--- slashjp/trunk/plugins/Metamod/mysql_schema.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/mysql_schema.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: mysql_schema.sql,v 1.2 2006/10/23 16:40:41 jamiemccarthy Exp $
+# $Id$
 #
 
 ALTER TABLE users_info ADD COLUMN m2info varchar(64) DEFAULT '' NOT NULL AFTER lastgranted, ADD COLUMN lastm2 datetime DEFAULT '1970-01-01 00:00' NOT NULL AFTER totalcomments, ADD COLUMN m2_mods_saved varchar(120) DEFAULT '' NOT NULL AFTER lastm2;

Modified: slashjp/trunk/plugins/Metamod/process_metamod.pl
===================================================================
--- slashjp/trunk/plugins/Metamod/process_metamod.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/process_metamod.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: process_metamod.pl,v 1.5 2006/10/26 17:33:04 jamiemccarthy Exp $
+# $Id$
 
 use strict;
 use Slash::Utility;
@@ -22,6 +22,10 @@
 		slashdLog("$me - metamoderation inactive") if verbosity() >= 2;
 		return ;
 	}
+	if ($constants->{tagbox}{Metamod}) {
+		slashdLog("$me - superceded by Metamod tagbox");
+		return ;
+	}
 
 	reconcile_m2();
 	update_modlog_ids();

Modified: slashjp/trunk/plugins/Metamod/templates/data;metamod;default
===================================================================
--- slashjp/trunk/plugins/Metamod/templates/data;metamod;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/templates/data;metamod;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -50,4 +50,4 @@
 __seclev__
 1000
 __version__
-$Id: data;metamod;default,v 1.2 2006/10/26 17:33:04 jamiemccarthy Exp $
+$Id$

Modified: slashjp/trunk/plugins/Metamod/templates/dispTheComments;metamod;default
===================================================================
--- slashjp/trunk/plugins/Metamod/templates/dispTheComments;metamod;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/templates/dispTheComments;metamod;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -52,7 +52,7 @@
 
 <form action="[% gSkin.rootdir %]/metamod.pl" method="post">
 [% IF comments.size %]
-<ul id="commentlisting">
+<ul id="commentlisting" class="[% Slash.discussion2() ? 'd2' : 'd1' %]">
 [% END %]
 [% FOR C = comments %]
 [%
@@ -86,4 +86,4 @@
 __seclev__
 1000
 __version__
-$Id: dispTheComments;metamod;default,v 1.1 2006/09/03 15:46:00 jamiemccarthy Exp $
+$Id$

Modified: slashjp/trunk/plugins/Metamod/templates/isEligible;metamod;default
===================================================================
--- slashjp/trunk/plugins/Metamod/templates/isEligible;metamod;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Metamod/templates/isEligible;metamod;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -36,4 +36,4 @@
 __seclev__
 1000
 __version__
-$Id: isEligible;metamod;default,v 1.1 2006/09/03 15:46:00 jamiemccarthy Exp $
+$Id$

Modified: slashjp/trunk/plugins/Moderation/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Moderation/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Moderation/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::Moderation',
-    'VERSION_FROM' => 'Moderation.pm', # finds $VERSION
     'PM'        => {
 	'Moderation.pm' => '$(INST_LIBDIR)/Moderation.pm',
     },

Modified: slashjp/trunk/plugins/Moderation/Moderation.pm
===================================================================
--- slashjp/trunk/plugins/Moderation/Moderation.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Moderation/Moderation.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: Moderation.pm,v 1.3 2006/12/01 04:25:32 jamiemccarthy Exp $
 
 package Slash::Moderation;
 
@@ -12,22 +11,24 @@
 use Slash::DB::Utility;
 use Slash::Display;
 
-use vars qw($VERSION);
 use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision: 1.3 $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;
 	my $self = {};
 
+	(my $modname = $class) =~ s/^Slash:://;
+
 	my $plugin = getCurrentStatic('plugin');
-	return unless $plugin->{Moderation};
+	return unless $plugin->{$modname};
 
 	my $constants = getCurrentStatic();
-	return undef unless $constants->{m1} && $constants->{m1_pluginname} eq 'Moderation';
+	return undef unless $constants->{m1}
+		&& $constants->{m1_pluginname} eq $modname;
 
 	bless($self, $class);
 	$self->{virtual_user} = $user;
@@ -68,7 +69,7 @@
 
 sub ajaxModerateCid {
 	my($slashdb, $constants, $user, $form, $options) = @_;
-	my $self = getObject('Slash::Moderation');
+	my $self = getObject('Slash::' . $constants->{m1_pluginname});
 	my $cid = $form->{cid} or return;
 	my $sid = $form->{sid} or return;
 	my $reason = $form->{reason} or return;
@@ -112,9 +113,7 @@
 		} elsif (!$ret_val) {
 			$html->{$select} = "Error: No moderation performed.";
 
-		} elsif ($ret_val == -1) {
-
-		} elsif ($ret_val == -2) {
+		} elsif ($ret_val == -1 || $ret_val == -2) {
 			$html->{$select} = "Error: $user->{points} moderation points left.";
 		}
 	}
@@ -155,40 +154,13 @@
 		|| ( $constants->{authors_unlimited}
 			&& $user->{seclev} >= $constants->{authors_unlimited} );
 
-	if ($user->{points} < 1 && !$superAuthor) {
+	# this check is done already, but we want to return a specific error
+	if (1 > $user->{points} && !$user->{acl}{modpoints_always} && !$superAuthor) {
 		return -1;
 	}
 
-	my $comment = $self->getComment($cid);
+	my $comment = $options->{comment} || $self->getComment($cid);
 
-	$comment->{time_unixepoch} = timeCalc($comment->{date}, "%s", 0);
-
-	# The user should not have been been presented with the menu
-	# to moderate if any of the following tests trigger, but,
-	# an unscrupulous user could have faked their submission with
-	# or without us presenting them the menu options.  So do the
-	# tests again.  XXX  These tests are basically copy-and-pasted
-	# from Slash.pm _can_mod, which should be rectified. -Jamie
-	# use reskeys instead ... -Pudge
-	# One or more reskey checks will need to invoke can_mod or some
-	# subset of it. -Jamie
-	unless ($superAuthor) {
-		# Do not allow moderation of any comments with the same UID as the
-		# current user (duh!).
-		return 0 if $user->{uid} == $comment->{uid};
-		# Do not allow moderation of any comments (anonymous or otherwise)
-		# with the same IP as the current user.
-		return 0 if $user->{ipid} eq $comment->{ipid};
-		# If the var forbids it, do not allow moderation of any comments
-		# with the same *subnet* as the current user.
-		return 0 if $constants->{mod_same_subnet_forbid}
-			and $user->{subnetid} eq $comment->{subnetid};
-		# Do not allow moderation of comments that are too old.
-		return 0 unless $comment->{time_unixepoch} >= time() - 3600*
-			($constants->{comments_moddable_hours}
-				|| 24*$constants->{archive_delay});
-	}
-
 	# Start putting together the data we'll need to display to
 	# the user.
 	my $reasons = $self->getReasons();
@@ -242,7 +214,7 @@
 
 	# If more than 1 mod point needed, we might not have enough,
 	# so this might still fail.
-	if ($pointsneeded > $user->{points} && !$superAuthor) {
+	if ($pointsneeded > $user->{points} && !$user->{acl}{modpoints_always} && !$superAuthor) {
 		return -2;
 	}
 
@@ -1001,6 +973,9 @@
 			"cid=$cid AND uid=$uid"
 		);
 
+		# Remove any tags on that comment by this user, as well.
+		$self->removeModTags($uid, $cid);
+
 		# Restore modded user's karma, again within the proper boundaries.
 		my $adjust = -$val;
 		$adjust =~ s/^([^+-])/+$1/;
@@ -1198,6 +1173,9 @@
 		my $mod_id = $self->getLastInsertId();
 		$metamod_db->adjustForNewMod($uid, $cid, $reason, $active, $mod_id);
 	}
+
+	$self->createModTag($uid, $cid, $reason);
+
 	return $ret_val;
 }
 
@@ -1366,23 +1344,13 @@
 	# update all at once on just one table and since we're using
 	# + and - instead of using absolute values. - Jamie 2002/08/08
 
-	for my $uid (@$uids) {
-		next unless $uid;
-		if ($self->checkAL2({ uid => $uid }, 'nom1')) {
-			my $rows = $self->setUser($uid, {
-				-tokens	=> 0,
-				-points => 0,
-			});
-			next;
-		}
-		my $rows = $self->setUser($uid, {
-			-lastgranted    => 'NOW()',
-			-tokens         => "GREATEST(0, tokens - $tokentrade)",
-			-points         => "LEAST(points + $pointtrade, $maxpoints)",
-		});
-		$granted{$uid} = 1 if $rows;
-	}
+	$self->setModPoints($uids, \%granted, {
+		pointtrade => $pointtrade,
+		maxpoints  => $maxpoints,
+		tokentrade => $tokentrade
+	});
 
+
 	# We used to do some fancy footwork with a cursor and locking
 	# tables.  The only difference between that code and this is that
 	# it only limited points to maxpoints for users with karma >= 0
@@ -1863,5 +1831,31 @@
 	}
 }
 
+# placeholders, used only in TagModeration
+sub removeModTags {}
+sub createModTag  {}
+
+sub setModPoints {
+	my($self, $uids, $granted, $opts) = @_;
+
+	for my $uid (@$uids) {
+		next unless $uid;
+
+		if ($self->checkAL2({ uid => $uid }, 'nom1')) {
+			my $rows = $self->setUser($uid, {
+				-tokens => 0,
+				-points => 0,
+			});
+			next;
+		}
+		my $rows = $self->setUser($uid, {
+			-lastgranted    => 'NOW()',
+			-tokens         => "GREATEST(0, tokens - $opts->{tokentrade})",
+			-points         => "LEAST(points + $opts->{pointtrade}, $opts->{maxpoints})",
+		});
+		$granted->{$uid} = 1 if $rows;
+	}
+}
+
 1;
 

Modified: slashjp/trunk/plugins/Moderation/PLUGIN
===================================================================
--- slashjp/trunk/plugins/Moderation/PLUGIN	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Moderation/PLUGIN	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: PLUGIN,v 1.2 2006/10/26 17:28:44 jamiemccarthy Exp $
+# $Id$
 name=Moderation
 description="Moderation (Classic)"
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/plugins/Moderation/moderate.pl
===================================================================
--- slashjp/trunk/plugins/Moderation/moderate.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Moderation/moderate.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: moderate.pl,v 1.2 2006/10/26 17:28:44 jamiemccarthy Exp $
+# $Id$
 
 # This script is not all that useful since moderation is largely
 # done by ajax now.  Users with browsers that don't support it

Modified: slashjp/trunk/plugins/Moderation/mysql_dump.sql
===================================================================
--- slashjp/trunk/plugins/Moderation/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Moderation/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: mysql_dump.sql,v 1.2 2006/10/26 17:28:44 jamiemccarthy Exp $
+# $Id$
 #
 
 REPLACE INTO ajax_ops VALUES (NULL, 'comments_moderate_cid', 'Slash::Moderation', 'ajaxModerateCid', 'comments-moderation-ajax', 'use');

Modified: slashjp/trunk/plugins/Moderation/mysql_schema.sql
===================================================================
--- slashjp/trunk/plugins/Moderation/mysql_schema.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Moderation/mysql_schema.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: mysql_schema.sql,v 1.2 2006/10/31 19:12:44 jamiemccarthy Exp $
+# $Id$
 #
 
 CREATE TABLE IF NOT EXISTS moderatorlog (

Modified: slashjp/trunk/plugins/Moderation/process_moderation.pl
===================================================================
--- slashjp/trunk/plugins/Moderation/process_moderation.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Moderation/process_moderation.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: process_moderation.pl,v 1.3 2006/11/06 17:04:43 jamiemccarthy Exp $
+# $Id$
 
 use strict;
 use Slash::Utility;
@@ -108,7 +108,7 @@
 	my $constants = getCurrentStatic();
 	my $moddb = getObject('Slash::Moderation');
 	my $mod_reader = getObject('Slash::Moderation', { db_type => 'reader' });
-	my $log_reader = getObject('Slash::DB', { db_type => 'log_slave' });
+	my $log_reader = getObject('Slash::Moderation', { db_type => 'log_slave' });
 	my $statsSave = getObject('Slash::Stats::Writer', '');
 
 	my $needed = 0;

Modified: slashjp/trunk/plugins/NewsVac/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/NewsVac/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/NewsVac/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::NewsVac',
-    'VERSION_FROM' => 'NewsVac.pm', # finds $VERSION
     'PM'	=> {
     	'NewsVac.pm'				=> '$(INST_LIBDIR)/NewsVac.pm',
     },


Property changes on: slashjp/trunk/plugins/NewsVac/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/NewsVac/NewsVac.pm
===================================================================
--- slashjp/trunk/plugins/NewsVac/NewsVac.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/NewsVac/NewsVac.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::NewsVac;
 
@@ -53,7 +52,6 @@
 
 
 use strict;
-use vars qw($VERSION @EXPORT);
 
 use Slash 2.003;	# require Slash 2.3
 use 5.006;		# requires some 5.6-specific stuff, like our()
@@ -79,9 +77,9 @@
 use Slash::Display;
 use Slash::Utility;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
-use vars qw($VERSION $callback_ref);
+use vars qw($callback_ref);
 
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
@@ -6278,7 +6276,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/plugins/NewsVac/newsvac.pod
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/OAI/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/OAI/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/OAI/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::XML::OAI',
-    'VERSION_FROM' => 'OAI.pm', # finds $VERSION
     'PM'	=> { 'OAI.pm' => '$(INST_LIBDIR)/OAI.pm' },
 );

Modified: slashjp/trunk/plugins/OAI/OAI.pm
===================================================================
--- slashjp/trunk/plugins/OAI/OAI.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/OAI/OAI.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::XML::OAI;
 
@@ -30,9 +29,8 @@
 use Slash::Utility;
 use XML::RSS;
 use base 'Slash::XML';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 our %Verbs = (
 	GetRecord		=> \&GetRecord,
@@ -470,7 +468,7 @@
 	if ($data->{type} eq 'article') {
 		my $record = $reader->getStory($data->{id});
 		if ($record) {
-			($data->{datestamp} = $record->{'last_update'}) =~
+			($data->{datestamp} = $record->{'archive_last_update'}) =~
 				s{^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})}
 				 {$1-$2-$3T$4:$5:$6Z}x;
 
@@ -594,7 +592,7 @@
 	my $type = $options->{type} || 'article';
 	my($records, @return);
 
-	my $timecol = 'last_update';
+	my $timecol = 'archive_last_update';
 
 	my $start = $options->{nextStart} || 1;
 
@@ -669,7 +667,3 @@
 =head1 SEE ALSO
 
 Slash(3), Slash::XML(3), L<http://www.openarchives.org/OAI/openarchivesprotocol.html>.
-
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/plugins/Page/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Page/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Page/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Page',
-    'VERSION_FROM' => 'Page.pm', # finds $VERSION
     'PM'	=> { 'Page.pm' => '$(INST_LIBDIR)/Page.pm' },
 );


Property changes on: slashjp/trunk/plugins/Page/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Page/Page.pm
===================================================================
--- slashjp/trunk/plugins/Page/Page.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Page/Page.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Page;
 
@@ -11,12 +10,10 @@
 use Slash::Utility;
 use Data::Dumper;
 
-use vars qw($VERSION @EXPORT);
-use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 #################################################################
 # Ok, so we want a nice module to do the front page and utilise 


Property changes on: slashjp/trunk/plugins/Page/Page.pm
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/PollBooth/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/PollBooth/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/PollBooth/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::PollBooth',
-    'VERSION_FROM' => 'PollBooth.pm', # finds $VERSION
     'PM'	=> {
 	'PollBooth.pm' => '$(INST_LIBDIR)/PollBooth.pm',
 	'ResKey.pm'    => '$(INST_LIBDIR)/PollBooth/ResKey.pm',

Modified: slashjp/trunk/plugins/PollBooth/PollBooth.pm
===================================================================
--- slashjp/trunk/plugins/PollBooth/PollBooth.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/PollBooth/PollBooth.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::PollBooth;
 
@@ -12,11 +11,10 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION @EXPORT);
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;
@@ -393,6 +391,12 @@
 	return $answer;
 }
 
+sub getPollDaysOld {
+	my($self) = @_;
+	return $self->sqlSelect('to_days(now()) - to_days(max(date))','pollquestions');
+	
+}
+
 sub DESTROY {
 	my($self) = @_;
 	$self->{_dbh}->disconnect if !$ENV{GATEWAY_INTERFACE} && $self->{_dbh};

Modified: slashjp/trunk/plugins/PollBooth/ResKey.pm
===================================================================
--- slashjp/trunk/plugins/PollBooth/ResKey.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/PollBooth/ResKey.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::PollBooth::ResKey;
 
@@ -13,7 +12,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/PollBooth/templates/pollplug;misc;default
===================================================================
--- slashjp/trunk/plugins/PollBooth/templates/pollplug;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/PollBooth/templates/pollplug;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -53,4 +53,4 @@
 __seclev__
 10000
 __version__
-$Id: pollplug;misc;default,v 1.3 2007/12/14 22:05:31 tvroom Exp $
+$Id$

Modified: slashjp/trunk/plugins/Rating/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Rating/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Rating/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Rating',
-    'VERSION_FROM' => 'Rating.pm', # finds $VERSION
     'PM'	=> { 'Rating.pm' => '$(INST_LIBDIR)/Rating.pm' },
 );

Modified: slashjp/trunk/plugins/Rating/Rating.pm
===================================================================
--- slashjp/trunk/plugins/Rating/Rating.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Rating/Rating.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Rating;
 
@@ -12,11 +11,10 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION @EXPORT);
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 #Right, this is not needed at the moment but will be in the near future
 sub new {

Modified: slashjp/trunk/plugins/Relocate/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Relocate/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Relocate/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Relocate',
-    'VERSION_FROM' => 'Relocate.pm', # finds $VERSION
     'PM'	=> { 'Relocate.pm' => '$(INST_LIBDIR)/Relocate.pm' },
 );

Modified: slashjp/trunk/plugins/Relocate/Relocate.pm
===================================================================
--- slashjp/trunk/plugins/Relocate/Relocate.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Relocate/Relocate.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Relocate;
 
@@ -12,10 +11,9 @@
 use HTML::TokeParser ();
 use Digest::MD5 'md5_hex';
 
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;

Modified: slashjp/trunk/plugins/Remarks/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Remarks/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Remarks/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Remarks',
-    'VERSION_FROM' => 'Remarks.pm', # finds $VERSION
     'PM'	=> { 'Remarks.pm' => '$(INST_LIBDIR)/Remarks.pm' },
 );

Modified: slashjp/trunk/plugins/Remarks/Remarks.pm
===================================================================
--- slashjp/trunk/plugins/Remarks/Remarks.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Remarks/Remarks.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Remarks;
 
@@ -32,9 +31,8 @@
 
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 ########################################################
 sub new {
@@ -191,7 +189,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$


Property changes on: slashjp/trunk/plugins/Remarks/templates/data;remarks;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Remarks/templates/display;remarks;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/ResKey/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/ResKey/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/ResKey/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 
 WriteMakefile(
     'NAME'	=> 'Slash::ResKey',
-    'VERSION_FROM' => 'ResKey.pm', # finds $VERSION
 #    'PM'	=> {
 #    	'ResKey.pm' => '$(INST_LIBDIR)/ResKey.pm',
 #    	'ResKey/Checks/User.pm' => '$(INST_LIBDIR)/ResKey/Checks/User.pm',


Property changes on: slashjp/trunk/plugins/ResKey/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/ResKey/PLUGIN
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/ACL.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/ACL.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/ACL.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::ACL;
 
@@ -13,7 +12,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/AnonNoPost.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/AnonNoPost.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/AnonNoPost.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::AL2::AnonNoPost;
 
@@ -14,7 +13,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoPost.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoPost.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoPost.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::AL2::NoPost;
 
@@ -14,7 +13,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoPostAnon.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoPostAnon.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoPostAnon.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::AL2::NoPostAnon;
 
@@ -14,7 +13,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoSubmit.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoSubmit.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/NoSubmit.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::AL2::NoSubmit;
 
@@ -14,7 +13,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/Spammer.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/Spammer.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2/Spammer.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 package Slash::ResKey::Checks::AL2::Spammer;
 
@@ -14,7 +13,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/AL2.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::AL2;
 
@@ -13,7 +12,7 @@
 use Slash::Utility;
 use Slash::Constants ':reskey';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 our @ISA    = qw(Exporter);
 our @EXPORT = qw(AL2Check);
 

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/Duration.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/Duration.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/Duration.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::Duration;
 
@@ -13,7 +12,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 
 sub doCheckCreate {
@@ -80,13 +79,17 @@
 	# as not to increase the chance of giving users a rather spurious error
 
 	@return = minDurationBetweenUses($self, $reskey_obj);
-	setMaxDuration($self) if @return;
-	return @return if @return;
+	if (@return) {
+		setMaxDuration($self);
+		return @return;
+	}
 
 	if ($self->origtype ne 'createuse') {
 		@return = minDurationBetweenCreateAndUse($self, $reskey_obj);
-		setMaxDuration($self) if @return;
-		return @return if @return;
+		if (@return) {
+			setMaxDuration($self);
+			return @return;
+		}
 	}
 
 	return RESKEY_SUCCESS;
@@ -286,15 +289,18 @@
 	my($self) = @_;
 	my $check_vars = $self->getCheckVars;
 
-	if ($check_vars->{max_duration}) {
-		my @durations;
-		push @durations, (duration($self, 'minDurationBetweenUses', 1))[0];
-		push @durations, (duration($self, 'minDurationBetweenCreateAndUse', 1))[0];
+	(my $caller = lc((caller(1))[3])) =~ s/^.*:docheck(\w+)$/$1/;
+	$caller ||= '';
+	return unless ($check_vars->{max_duration} ||
+		($caller && $check_vars->{"max_duration_$caller"})
+	);
 
-		my($max_duration) = sort { $b <=> $a } @durations;
-		$self->max_duration($max_duration);
-	}
+	my @durations;
+	push @durations, (duration($self, 'minDurationBetweenUses', 1))[0];
+	push @durations, (duration($self, 'minDurationBetweenCreateAndUse', 1))[0];
 
+	my($max_duration) = sort { $b <=> $a } @durations;
+	$self->max_duration($max_duration);
 }
 
 1;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/HumanConf.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/HumanConf.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/HumanConf.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: HumanConf.pm,v 1.3 2008/04/02 15:15:45 pudge Exp $
 
 package Slash::ResKey::Checks::HumanConf;
 
@@ -13,7 +12,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision: 1.3 $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub updateResKey {
 	my($self) = @_;
@@ -30,7 +29,6 @@
 
 sub doCheckCreate {
 	my($self) = @_;
-
 	return RESKEY_SUCCESS unless useHumanConf($self);
 
 	my $hc = getObject('Slash::HumanConf');
@@ -89,14 +87,20 @@
 			   $constants->{hc_sw_comments} == 0
 				# ...or it's turned off for logged-in users
 				# and this user is logged-in...
-			|| $constants->{hc_sw_comments} == 1
-			   && !$user->{is_anon}
+			|| ($constants->{hc_sw_comments} == 1
+			   && !$user->{is_anon})
 				# ...or it's turned off for logged-in users
 				# with high enough karma, and this user
 				# qualifies.
-			|| $constants->{hc_sw_comments} == 2
+			|| ($constants->{hc_sw_comments} == 2
 			   && !$user->{is_anon}
-		   	&&  $user->{karma} > $constants->{hc_maxkarma};
+		   	   &&  $user->{karma} > $constants->{hc_maxkarma});
+
+	# default
+	} else {
+		return 0 if $user->{is_admin}
+			 || (!$user->{is_anon}
+		   	 &&  $user->{karma} > $constants->{hc_maxkarma});
 	}
 
 	return 1;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/Moderate.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/Moderate.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/Moderate.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: Moderate.pm,v 1.4 2006/10/26 17:33:04 jamiemccarthy Exp $
 
 # XXX right now we have checks for moderation in many places.
 # we must consolidate as much as possible. -- pudge
@@ -25,7 +24,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision: 1.4 $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/Post.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/Post.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/Post.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::Post;
 
@@ -13,7 +12,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/ProxyScan.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/ProxyScan.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/ProxyScan.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::ProxyScan;
 
@@ -13,7 +12,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;
@@ -30,7 +29,7 @@
 		return RESKEY_SUCCESS;
 	}
 
-	if (!$reader->getAL2($user->{srcids}, 'trusted')) {
+	unless ($reader->checkAL2($user->{srcids}, 'trusted')) {
 		my $is_proxy = $reader->checkForOpenProxy($user->{srcids}{ip});
 		if ($is_proxy) {
 			return(RESKEY_DEATH, ['open proxy', {

Modified: slashjp/trunk/plugins/ResKey/ResKey/Checks/User.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Checks/User.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Checks/User.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Checks::User;
 
@@ -13,7 +12,7 @@
 
 use base 'Slash::ResKey::Key';
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub doCheck {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/ResKey/ResKey/Key.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey/Key.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey/Key.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey::Key;
 
@@ -118,7 +117,7 @@
 use Slash::Utility;
 
 our($AUTOLOAD);
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 #========================================================================
 sub new {
@@ -1012,7 +1011,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/plugins/ResKey/ResKey.pm
===================================================================
--- slashjp/trunk/plugins/ResKey/ResKey.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/ResKey.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ResKey;
 
@@ -48,7 +47,7 @@
 use base 'Slash::DB::MySQL';
 
 our($AUTOLOAD);
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 our $DEBUG = 0;
 
@@ -168,11 +167,7 @@
 
 Slash(3).
 
-=head1 VERSION
 
-$Id$
-
-
 =head1 TODO
 
 =head2 Check Classes

Modified: slashjp/trunk/plugins/ResKey/mysql_dump.sql
===================================================================
--- slashjp/trunk/plugins/ResKey/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ResKey/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -73,7 +73,7 @@
 INSERT INTO reskey_vars VALUES (1, 'duration_uses-anon-trolla', 3600, 'duration_uses for anon + trolla AL2');
 INSERT INTO reskey_vars VALUES (1, 'duration_uses-trolla',       300, 'duration_uses for tolla AL2');
 INSERT INTO reskey_vars VALUES (1, 'duration_uses-anon-mult',    1.5, 'multiply by this amount for each comment previously posted in the past 24 hours');
-INSERT INTO reskey_vars VALUES (1, 'max_duration', 1, 'boolean for whether to store max duration in reskey object on creation');
+INSERT INTO reskey_vars VALUES (1, 'max_duration_touch', 1, 'boolean for whether to store max duration in reskey object on touch');
 
 
 
@@ -191,6 +191,8 @@
 INSERT INTO reskey_resource_checks VALUES (NULL, 6, 'all', 'Slash::ResKey::Checks::AL2::Spammer',        531);
 INSERT INTO reskey_resource_checks VALUES (NULL, 6, 'all', 'Slash::ResKey::Checks::AL2::NoSubmit',       551);
 INSERT INTO reskey_resource_checks VALUES (NULL, 6, 'all', 'Slash::ResKey::Checks::Duration',            601);
+INSERT INTO reskey_resource_checks VALUES (NULL, 6, 'all', 'Slash::ResKey::Checks::HumanConf',           701);
+INSERT INTO reskey_resource_checks VALUES (NULL, 6, 'all', 'Slash::ResKey::Checks::ProxyScan',           801);
 
 ### vars
 INSERT INTO reskey_vars VALUES (6, 'adminbypass', 1, 'If admin, bypass checks for duration, proxy, and user');


Property changes on: slashjp/trunk/plugins/ResKey/templates/data;reskey;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/SOAP/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/SOAP/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SOAP/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::SOAP',
-    'VERSION_FROM' => 'SOAP.pm', # finds $VERSION
     'PM'	=> { 'SOAP.pm' => '$(INST_LIBDIR)/SOAP.pm',
     		     'Test.pm' => '$(INST_LIBDIR)/SOAP/Test.pm' },
 );

Modified: slashjp/trunk/plugins/SOAP/SOAP.pm
===================================================================
--- slashjp/trunk/plugins/SOAP/SOAP.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SOAP/SOAP.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::SOAP;
 
@@ -9,12 +8,12 @@
 use Slash;
 use Slash::Utility;
 
-use vars qw( $VERSION $ERROR );
+use vars qw( $ERROR );
 use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 =head1 NAME
 
@@ -170,7 +169,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/plugins/ScheduleShifts/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/ScheduleShifts/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ScheduleShifts/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::ScheduleShifts',
-    'VERSION_FROM' => 'ScheduleShifts.pm', # finds $VERSION
     'PM'	=> { 'ScheduleShifts.pm' => '$(INST_LIBDIR)/ScheduleShifts.pm' },
 );


Property changes on: slashjp/trunk/plugins/ScheduleShifts/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/ScheduleShifts/ScheduleShifts.pm
===================================================================
--- slashjp/trunk/plugins/ScheduleShifts/ScheduleShifts.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/ScheduleShifts/ScheduleShifts.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::ScheduleShifts;
 
@@ -19,7 +18,7 @@
 use constant SHIFT_DEFAULT		=> -2;
 use constant SHIFT_NOTSET		=> -1;
 
-our($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 our @DOW = qw(sun mon tue wed thu fri sat);
 our %DOW;


Property changes on: slashjp/trunk/plugins/ScheduleShifts/ScheduleShifts.pm
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Search/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Search/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Search/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Search',
-    'VERSION_FROM' => 'Search.pm', # finds $VERSION
     'PM'	=> { 'Search.pm' => '$(INST_LIBDIR)/Search.pm' },
 );

Modified: slashjp/trunk/plugins/Search/SOAP/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Search/SOAP/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Search/SOAP/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Search::SOAP',
-    'VERSION_FROM' => 'SOAP.pm', # finds $VERSION
     'PM'	=> { 'SOAP.pm' => '$(INST_LIBDIR)/SOAP.pm' },
 );

Modified: slashjp/trunk/plugins/Search/SOAP/SOAP.pm
===================================================================
--- slashjp/trunk/plugins/Search/SOAP/SOAP.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Search/SOAP/SOAP.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,17 +1,15 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Search::SOAP;
 
 use strict;
 use Slash::Utility;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # As a note I will be adding support for sort later.
 # I want to make it easy for people just to pass in a string

Modified: slashjp/trunk/plugins/Search/Search.pm
===================================================================
--- slashjp/trunk/plugins/Search/Search.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Search/Search.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,17 +1,15 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Search;
 
 use strict;
 use Slash::Utility;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: And where would a giant nerd be? THE LIBRARY!
 


Property changes on: slashjp/trunk/plugins/Search/templates/pagination;search;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/SearchToo/MANIFEST
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/SearchToo/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/SearchToo/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SearchToo/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,7 +3,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::SearchToo',
-    'VERSION_FROM' => 'SearchToo.pm', # finds $VERSION
     'PM'	=> {
     	'SearchToo.pm'				=> '$(INST_LIBDIR)/SearchToo.pm',
     },


Property changes on: slashjp/trunk/plugins/SearchToo/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/SearchToo/PLUGIN
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/SearchToo/SearchToo/Classic.pm
===================================================================
--- slashjp/trunk/plugins/SearchToo/SearchToo/Classic.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SearchToo/SearchToo/Classic.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,11 +3,10 @@
 use strict;
 use Slash::Utility;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 use base 'Slash::SearchToo';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: I did it!  And it's all thanks to the books at my local library.
 

Modified: slashjp/trunk/plugins/SearchToo/SearchToo/Indexer.pm
===================================================================
--- slashjp/trunk/plugins/SearchToo/SearchToo/Indexer.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SearchToo/SearchToo/Indexer.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -7,11 +7,10 @@
 use File::Spec::Functions;
 use Slash::Utility;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 use base 'Slash::SearchToo';
 require Slash::SearchToo::Classic;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: I did it!  And it's all thanks to the books at my local library.
 
@@ -83,8 +82,8 @@
 	# let Classic handle for now
 	return Slash::SearchToo::Classic::findRecords(@_) unless $self->handled($type);
 
-slashProfInit();
-slashProf('findRecords setup');
+# slashProfInit();
+# slashProf('findRecords setup');
 
 	my $constants = getCurrentStatic();
 
@@ -131,9 +130,9 @@
 		%$terms = (%$terms, %$query);
 	}
 
-slashProf('_findRecords', 'findRecords setup');
+# slashProf('_findRecords', 'findRecords setup');
 	$self->_findRecords($results, $records, $sopts, $terms, $opts);
-slashProf('getRecords', '_findRecords');
+# slashProf('getRecords', '_findRecords');
 	$self->getRecords($type => $records, {
 		alldata		=> 1,
 		sort		=> $sopts->{sort},
@@ -142,11 +141,11 @@
 		offset		=> $sopts->{start},
 		carryover	=> $opts->{carryover}
 	});
-slashProf('prepResults', 'getRecords');
+# slashProf('prepResults', 'getRecords');
 	$self->prepResults($results, $records, $sopts);
-slashProf('', 'getRecords');
+# slashProf('', 'getRecords');
 
-slashProfEnd();
+# slashProfEnd();
 
 	return $results;
 
@@ -517,8 +516,16 @@
 			while (my $f = readdir($dh)) {
 				next if $f =~ /^\./;
 				my $file = catfile($back, 'invindex', $f);
-				if (-f $file && -s _ == 0 && -M _ > 1) {
-					unlink $file;
+
+				lstat $file;
+				# file is empty ...
+				if (-f _ && -s _ == 0) {
+					# ... and more than an hour old
+					# current time - (time script started -
+					# file modify time since script started)
+					my $time = time - ($^T - ((-M _) * 86400));
+					# convert $time to days
+					unlink $file if (($time/86400) > 1/24);
 				}
 			}
 		} else {

Modified: slashjp/trunk/plugins/SearchToo/SearchToo/Kinosearch.pm
===================================================================
--- slashjp/trunk/plugins/SearchToo/SearchToo/Kinosearch.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SearchToo/SearchToo/Kinosearch.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -5,7 +5,6 @@
 use File::Spec::Functions;
 use Slash::Utility;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 use base 'Slash::SearchToo::Indexer';
 
 use KinoSearch::Analysis::PolyAnalyzer;
@@ -15,7 +14,7 @@
 use KinoSearch::Search::QueryFilter;
 use KinoSearch::Searcher;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: I did it!  And it's all thanks to the books at my local library.
 


Property changes on: slashjp/trunk/plugins/SearchToo/SearchToo/Makefile.PL
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/SearchToo/SearchToo/Plucene.pm
===================================================================
--- slashjp/trunk/plugins/SearchToo/SearchToo/Plucene.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SearchToo/SearchToo/Plucene.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -7,7 +7,6 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 use Slash::SearchToo::Classic;
-use vars qw($VERSION);
 use base 'Slash::SearchToo::Indexer';
 
 use Plucene::Document;
@@ -18,7 +17,7 @@
 use Plucene::Search::IndexSearcher;
 use Plucene::Search::TermQuery;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: I did it!  And it's all thanks to the books at my local library.
 

Modified: slashjp/trunk/plugins/SearchToo/SearchToo.pm
===================================================================
--- slashjp/trunk/plugins/SearchToo/SearchToo.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SearchToo/SearchToo.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,10 +3,9 @@
 use strict;
 use Slash::Utility;
 use Slash::DB::Utility;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: Prepare to be thought at!
 


Property changes on: slashjp/trunk/plugins/SearchToo/dump
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/SearchToo/schema.sql
===================================================================
--- slashjp/trunk/plugins/SearchToo/schema.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SearchToo/schema.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: schema.sql,v 1.1 2006/09/28 21:42:35 pudge Exp $
+# $Id$
 #
 
 DROP TABLE IF EXISTS search_index_dump;

Modified: slashjp/trunk/plugins/SearchToo/search_index.pl
===================================================================
--- slashjp/trunk/plugins/SearchToo/search_index.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/SearchToo/search_index.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: search_index.pl,v 1.9 2007/09/14 21:52:28 pudge Exp $
+# $Id$
 
 use strict;
 
@@ -104,13 +104,13 @@
 		} else {
 			$searchtoo->deleteStoredRecords(\@iids_d);
 		}
+
+		$searchtoo->finish;
 	}
 
 	$searchtoo->backup(0);
 	$searchtoo->moveLive;
 
-	$searchtoo->finish;
-
 	slashdLog("Moved new index live");
 	slashdLog("Finished");
 };


Property changes on: slashjp/trunk/plugins/SearchToo/templates/commentsearch;searchtoo;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/SearchToo/templates/data;searchtoo;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/SearchToo/templates/nosearch;searchtoo;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/SearchToo/templates/pagination;searchtoo;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/SearchToo/templates/searchform;searchtoo;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/SearchToo/templates/searchrss;searchtoo;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/SearchToo/templates/storysearch;searchtoo;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Stats/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Stats/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Stats',
-    'VERSION_FROM' => 'Stats.pm', # finds $VERSION
     'PM'	=> { 'Stats.pm' => '$(INST_LIBDIR)/Stats.pm' },
 );

Modified: slashjp/trunk/plugins/Stats/PLUGIN
===================================================================
--- slashjp/trunk/plugins/Stats/PLUGIN	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/PLUGIN	2008-09-09 13:07:58 UTC (rev 742)
@@ -19,3 +19,4 @@
 template=templates/report;stats;default
 template=templates/stats_days;stats;default
 template=templates/table;stats;default
+template=templates/topic_stats;stats;default

Modified: slashjp/trunk/plugins/Stats/Stats.pm
===================================================================
--- slashjp/trunk/plugins/Stats/Stats.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/Stats.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Stats;
 
@@ -18,11 +17,10 @@
 use Slash::DB::Utility;
 use LWP::UserAgent;
 
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user, $options) = @_;
@@ -119,6 +117,7 @@
 			my $new_sql = $create_sql;
 			$new_sql =~ s/__TABLENAME__/$new_table/;
 			$self->sqlDo($new_sql);
+			$self->sqlDo("ALTER TABLE $new_table DROP INDEX ts");
 		}
 
 		# Create the accesslog_temp table, then add indexes to its data.
@@ -136,26 +135,13 @@
 			"id BETWEEN $minid AND $maxid AND ts $self->{_day_between_clause}
 			 AND status  = 200 AND op != 'rss'",
 			3, 60);
-		# Some of these (notably ts) may be redundant but that's OK,
-		# they will just throw errors we don't care about.  They're here
-		# in case the table on the DB we're operating on has had its ts
-		# index removed.
+		# Some of these may be redundant but that's OK, they will
+		# just throw errors we don't care about.
 		$self->sqlDo("ALTER TABLE accesslog_temp ADD INDEX uid (uid)");
 		$self->sqlDo("ALTER TABLE accesslog_temp ADD INDEX skid_op (skid,op)");
 		$self->sqlDo("ALTER TABLE accesslog_temp ADD INDEX op_uid_skid (op, uid, skid)");
 		$self->sqlDo("ALTER TABLE accesslog_temp ADD INDEX referer (referer(4))");
-		# XXX there should be a way to check whether the source accesslog table
-		# already had this index, and if so, to leave it off.
-		$self->sqlDo("ALTER TABLE accesslog_temp ADD INDEX ts (ts)")
-			unless ($self->{_dbh}->selectrow_hashref("SHOW FIELDS FROM accesslog_temp LIKE 'ts'")->{Key});
-		$self->sqlDo("ALTER TABLE accesslog_temp_errors ADD INDEX ts (ts)")
-			unless ($self->{_dbh}->selectrow_hashref("SHOW FIELDS FROM accesslog_temp_errors LIKE 'ts'")->{Key});
-		$self->sqlDo("ALTER TABLE accesslog_temp_subscriber ADD INDEX ts (ts)")
-			unless ($self->{_dbh}->selectrow_hashref("SHOW FIELDS FROM accesslog_temp_subscriber LIKE 'ts'")->{Key});
-		$self->sqlDo("ALTER TABLE accesslog_temp_other ADD INDEX ts (ts)")
-			unless ($self->{_dbh}->selectrow_hashref("SHOW FIELDS FROM accesslog_temp_other LIKE 'ts'")->{Key});
-		$self->sqlDo("ALTER TABLE accesslog_temp_rss ADD INDEX ts (ts)")
-			unless ($self->{_dbh}->selectrow_hashref("SHOW FIELDS FROM accesslog_temp_rss LIKE 'ts'")->{Key});
+		$self->sqlDo("ALTER TABLE accesslog_temp ADD INDEX ts (ts)");
 
 		# Create the other accesslog_temp_* tables and add their indexes.
 		return undef unless $self->_do_insert_select(
@@ -165,6 +151,7 @@
 			"id BETWEEN $minid AND $maxid AND ts $self->{_day_between_clause}
 			 AND status  = 200 AND op = 'rss'",
 			3, 60);
+		$self->sqlDo("ALTER TABLE accesslog_temp_rss ADD INDEX ts (ts)");
 		return undef unless $self->_do_insert_select(
 			"accesslog_temp_errors",
 			"*",
@@ -172,6 +159,7 @@
 			"id BETWEEN $minid AND $maxid AND ts $self->{_day_between_clause}
 			 AND status != 200",
 			3, 60);
+		$self->sqlDo("ALTER TABLE accesslog_temp_errors ADD INDEX ts (ts)");
 
 		my $stats_reader = getObject('Slash::Stats', { db_type => 'reader' });	
 		my $recent_subscribers = $stats_reader->getRecentSubscribers();
@@ -185,6 +173,7 @@
 				"accesslog_temp",
 				"uid IN ($recent_subscriber_uidlist)",
 				3, 60);
+			$self->sqlDo("ALTER TABLE accesslog_temp_subscriber ADD INDEX ts (ts)");
 		}
 
 		my @pages;
@@ -202,8 +191,9 @@
 			"accesslog_temp",
 			"op NOT IN ($page_list)",
 			3, 60);
+		$self->sqlDo("ALTER TABLE accesslog_temp_other ADD INDEX ts (ts)");
 
-		# Add in the indexes we need for those tables.
+		# Add in the non-ts indexes we need for those tables.
 		$self->sqlDo("ALTER TABLE accesslog_temp_errors ADD INDEX status_op_skid (status, op, skid)");
 		$self->sqlDo("ALTER TABLE accesslog_temp_subscriber ADD INDEX skid (skid)");
 		$self->sqlDo("ALTER TABLE accesslog_temp_other ADD INDEX skid (skid)");
@@ -1018,8 +1008,7 @@
 sub countSubmissionsByCommentIPID {
 	my($self, $ipids, $options) = @_;
 	return unless @$ipids;
-	my $slashdb = getCurrentDB();
-	my $in_list = join(",", map { $slashdb->sqlQuote($_) } @$ipids);
+	my $in_list = join(",", map { $self->sqlQuote($_) } @$ipids);
 
 	my $where = "time $self->{_day_between_clause}
 		AND ipid IN ($in_list)";
@@ -1298,11 +1287,20 @@
 
 ########################################################
 sub countFromRSSStatsBySections {
-	my ($self) = @_;
+	my($self, $options) = @_;
+	my $op_clause = '';
+	if ($options->{no_op}) {
+		my $no_op = $options->{no_op};
+		$no_op = [ $no_op ] if !ref($no_op);
+		if (@$no_op) {
+			my $op_not_in = join(",", map { $self->sqlQuote($_) } @$no_op);
+			$op_clause = " AND op NOT IN ($op_not_in)";
+		}
+	}
 	$self->sqlSelectAllHashref("skid",
 		"skid, count(*) AS cnt, COUNT(DISTINCT uid) AS uids, COUNT(DISTINCT host_addr) AS ipids",
 		"accesslog_temp",
-		"referer='rss'",
+		"referer='rss'$op_clause",
 		"GROUP BY skid");
 }
 
@@ -1342,20 +1340,29 @@
 
 
 ########################################################
-sub countDailyStoriesAccess {
+sub countDailyStoriesAccessArticle {
 	my($self) = @_;
-	my $qlid = $self->_querylog_start('SELECT', 'accesslog_temp');
-	my $c = $self->sqlSelectMany("dat, COUNT(*), op", "accesslog_temp",
-		"op='article'",
-		"GROUP BY dat");
+	return $self->sqlSelectAllKeyValue('dat, COUNT(*)',
+		'accesslog_temp', "op='article'", 'GROUP BY dat');
+}
 
-	my %articles; 
-	while (my($sid, $cnt) = $c->fetchrow) {
-		$articles{$sid} = $cnt;
+########################################################
+sub countDailyStoriesAccessRSS {
+	my($self) = @_;
+	my $qs_hr = $self->sqlSelectAllKeyValue(
+		'query_string, COUNT(*)',
+		'accesslog_temp',
+		"op='slashdot-it' AND query_string LIKE '%from=rssbadge'",
+		'GROUP BY query_string');
+	my $sid_hr = { };
+	my $regex_sid = regexSid(1);
+	for my $qs (keys %$qs_hr) {
+		my($sid) = $qs =~ m{sid=\b([\d/]+)\b};
+		next unless $sid =~ $regex_sid;
+		$sid_hr->{$sid} ||= 0;
+		$sid_hr->{$sid} += $qs_hr->{$qs};
 	}
-	$c->finish;
-	$self->_querylog_finish($qlid);
-	return \%articles;
+	return $sid_hr;
 }
 
 ########################################################
@@ -1745,11 +1752,14 @@
 	my $constants = getCurrentStatic();
 	return [ ] unless $constants->{basedomain} eq 'slashdot.org';
 
+	# If Slash::XML::RSS::rssstory()'s text for its <img src>
+	# badge changes, the query_string check here may also
+	# have to change.
 	my $count = $options->{count} || 10;
 	my $top_ar = $self->sqlSelectAll(
 		"query_string AS qs, COUNT(*) AS c",
 		"accesslog_temp",
-		"op='slashdot-it' AND query_string NOT LIKE '%from=rssbadge'",
+		"op='slashdot-it' AND query_string NOT LIKE 'from=rss%'",
 		"GROUP BY qs ORDER BY c DESC, qs LIMIT $count"
 	);
 	for my $duple (@$top_ar) {
@@ -2142,6 +2152,7 @@
 			sleep $sleep_time;
 		} else {
 			print STDERR scalar(localtime) . " INSERT-SELECT $to_table still failed, giving up\n";
+			$self->insertErrnoteLog("adminmail", "Failed creating table '$to_table'", "Checked replication $try_num times without success, giving up");
 			return undef;
 		}
 
@@ -2205,6 +2216,64 @@
 
 }
 
+sub getTopicStats {
+	my ($self, $days, $order) = @_;
+	$days = 30 if $days !~/^\d+$/;
+	my $order_clause = $order eq "name" ? "1 ASC" : "4 DESC";
+
+	return $self->sqlSelectAllHashrefArray(
+		"topics.textname, story_topics_rendered.tid, count(*) AS cnt, sum(hits) AS sum_hits, sum(commentcount) AS sum_cc, avg(hits) AS avg_hits, avg(commentcount) AS avg_cc, image", 
+		"stories, story_topics_rendered, topics",
+		"time > date_sub(now(), interval $days day) and stories.stoid = story_topics_rendered.stoid and story_topics_rendered.tid = topics.tid group by story_topics_rendered.tid",
+		"order by $order_clause"
+	);
+
+}
+
+sub tallyBinspam {
+	my($self) = @_;
+	my $constants = getCurrentStatic();
+	return (undef, undef, undef)
+		unless $constants->{plugin}{Tags} && $constants->{plugin}{FireHose};
+
+	# Count all globjs which got 'binspam' tags applied by admins
+	# during the previous day, but only globjs which did _not_ get
+	# any admin 'binspam' tags in days previous (we already counted
+	# those).
+	my $tagsdb = getObject('Slash::Tags');
+	my $binspam_tagnameid = $tagsdb->getTagnameidCreate('binspam');
+	my $admins = $self->getAdmins();
+	my $admin_uid_str = join(',', sort { $a <=> $b } keys %$admins);
+	my $binspammed_globj = $self->sqlSelect(
+		'COUNT(DISTINCT t1.globjid)',
+		"tags AS t1 LEFT JOIN tags AS t2
+			ON (    t1.globjid=t2.globjid
+			    AND t2.tagnameid=$binspam_tagnameid
+			    AND t2.uid IN ($admin_uid_str)
+			    AND t2.created_at < '$self->{_day} 00:00:00'
+			    AND t2.inactivated IS NULL )",
+		"t1.uid IN ($admin_uid_str)
+		 AND t1.created_at $self->{_day_between_clause}
+		 AND t1.inactivated IS NULL
+		 AND t1.tagnameid=$binspam_tagnameid
+		 AND t2.tagid IS NULL");
+
+	# Get the total is_spam count in the hose.
+	my $old_count = $constants->{stats_firehose_spamcount} || 0;
+	my $is_spam_count = $self->sqlCount('firehose', "is_spam='yes'") || 0;
+	$is_spam_count = $old_count if $is_spam_count < $old_count;
+	my $is_spam_new = $is_spam_count - $old_count;
+	$self->setVar('stats_firehose_spamcount', $is_spam_count);
+
+	# And get the count of is_spams added automatically by tagboxes/Despam.
+	my $statsSave = getObject('Slash::Stats::Writer', { day => $self->{_day} });
+	# Create it if it doesn't exist, so stats have an unbroken sequence.
+	$statsSave->createStatDaily('firehose_binspam_despam', 0);
+	my $autodetected = $self->getStatToday('firehose_binspam_despam');
+ 
+	return($binspammed_globj, $is_spam_new, $autodetected);
+}
+
 ########################################################
 sub DESTROY {
 	my($self) = @_;
@@ -2220,7 +2289,3 @@
 =head1 SEE ALSO
 
 Slash(3).
-
-=head1 VERSION
-
-$Id$

Modified: slashjp/trunk/plugins/Stats/Writer/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Stats/Writer/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/Writer/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Stats::Writer',
-    'VERSION_FROM' => 'Writer.pm', # finds $VERSION
     'PM'	=> { 'Writer.pm' => '$(INST_LIBDIR)/Writer.pm' },
 );

Modified: slashjp/trunk/plugins/Stats/Writer/Writer.pm
===================================================================
--- slashjp/trunk/plugins/Stats/Writer/Writer.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/Writer/Writer.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Stats::Writer;
 
@@ -11,11 +10,10 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # On a side note, I am not sure if I liked the way I named the methods either.
 # -Brian

Modified: slashjp/trunk/plugins/Stats/adminmail.pl
===================================================================
--- slashjp/trunk/plugins/Stats/adminmail.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/adminmail.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 use strict;
 use Slash::Constants qw( :messages :slashd );
@@ -106,8 +105,6 @@
 	}
 	slashdLog("Counting Error Pages End");
 
-	my $articles = $logdb->countDailyStoriesAccess();
-
 	my $admin_clearpass_warning = '';
 	if ($constants->{admin_check_clearpass}) {
 		my $clear_admins = $stats->getAdminsClearpass();
@@ -450,7 +447,7 @@
 	# 1 hour
 	slashdLog("Sectional Stats Begin");
 	my $skins =  $slashdb->getDescriptions('skins');
-	my $stats_from_rss = $logdb->countFromRSSStatsBySections();
+	my $stats_from_rss = $logdb->countFromRSSStatsBySections({ no_op => $constants->{op_exclude_from_countdaily} });
 	#XXXSECTIONTOPICS - don't think we need this anymore but just making sure
 	#$sections->{index} = 'index';
 	
@@ -793,31 +790,53 @@
 	$data{day} = $yesterday ;
 	$data{distinct_comment_posters_uids} = sprintf("%8u", $distinct_comment_posters_uids);
 
+	my $stories_article = $logdb->countDailyStoriesAccessArticle();
 	my @top_articles =
-		grep { $articles->{$_} >= 100 }
-		sort { ($articles->{$b} || 0) <=> ($articles->{$a} || 0) }
-		keys %$articles;
+		grep { $stories_article->{$_} >= 100 }
+		sort { ($stories_article->{$b} || 0) <=> ($stories_article->{$a} || 0) }
+		keys %$stories_article;
 	$#top_articles = 24 if $#top_articles > 24; # only list top 25 stories
-	my @lazy = ( );
+	my @lazy_article = ( );
 	my %nick = ( );
 	for my $sid (@top_articles) {
-		my $hitcount = $articles->{$sid};
+		my $hitcount = $stories_article->{$sid};
  		my $story = $reader->getStory($sid, [qw( title uid )]);
 		next unless $story->{title} && $story->{uid};
 		$nick{$story->{uid}} ||= $reader->getUser($story->{uid}, 'nickname')
 			|| $story->{uid};
 
-		push @lazy, sprintf( "%6d %-16s %-10s %-30s",
+		push @lazy_article, sprintf( "%6d %-16s %-10s %-30s",
 			$hitcount, $sid, $nick{$story->{uid}},
 			substr($story->{title}, 0, 30),
 		);
 	}
+	$data{lazy_article} = \@lazy_article; 
 
+	my $stories_rss = $logdb->countDailyStoriesAccessRSS;
+	my @top_rsses =
+		grep { $stories_rss->{$_} >= 100 }
+		sort { ($stories_rss->{$b} || 0) <=> ($stories_rss->{$a} || 0) }
+		keys %$stories_rss;
+	$#top_rsses = 24 if $#top_rsses > 24; # only list top 25 stories
+	my @lazy_rss = ( );
+	for my $sid (@top_rsses) {
+		my $hitcount = $stories_rss->{$sid};
+ 		my $story = $reader->getStory($sid, [qw( title uid )]);
+		next unless $story->{title} && $story->{uid};
+		$nick{$story->{uid}} ||= $reader->getUser($story->{uid}, 'nickname')
+			|| $story->{uid};
+
+		push @lazy_rss, sprintf( "%6d %-16s %-10s %-30s",
+			$hitcount, $sid, $nick{$story->{uid}},
+			substr($story->{title}, 0, 30),
+		);
+	}
+	$data{lazy_rss} = \@lazy_rss; 
+
 	$mod_data{data} = \%mod_data;
 	$mod_data{admin_mods_text} = $admin_mods_text;
 	
 	$data{data} = \%data;
-	$data{lazy} = \@lazy; 
 	$data{admin_clearpass_warning} = $admin_clearpass_warning;
 	$data{tailslash} = $logdb->getTailslash();
 
@@ -922,6 +941,17 @@
 		$data{firehose_report} = $fh_report;
 	}
 
+	if ($firehose && $tags) {
+		my($binspam_globj_count, $is_spam_new_count, $autodetected_count)
+			= $stats->tallyBinspam();
+		$data{binspam_globj_count} = $binspam_globj_count;
+		$statsSave->createStatDaily('binspam_globj_count', $binspam_globj_count);
+		$data{is_spam_new_count} = $is_spam_new_count;
+		$statsSave->createStatDaily('is_spam_new_count', $is_spam_new_count);
+		$data{is_spam_autodetected_count} = $autodetected_count;
+		$statsSave->createStatDaily('is_spam_autodetected_count', $autodetected_count);
+	}
+
 	if ($tags) {
 		my $tags_report = '';
 		my $tags_users = $stats->getTagCountForDay($yesterday, [], 1);

Modified: slashjp/trunk/plugins/Stats/mysql_dump
===================================================================
--- slashjp/trunk/plugins/Stats/mysql_dump	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/mysql_dump	2008-09-09 13:07:58 UTC (rev 742)
@@ -9,6 +9,7 @@
 INSERT INTO vars (name, value, description) VALUES ('mod_stats_reports','admin****@examp*****','Who to send daily moderation stats reports to');
 INSERT INTO vars (name, value, description) VALUES ('op_exclude_from_countdaily','rss','Ops to omit from daily counts in adminmail');
 INSERT INTO vars (name, value, description) VALUES ('stats_admin_seclev','100','seclev required to look at stats in stats.pl');
+INSERT INTO vars (name, value, description) VALUES ('stats_firehose_spamcount', '0', 'Number of firehose items marked as is_spam');
 INSERT INTO vars (name, value, description) VALUES ('adminmail_last_run','2003-02-20','day adminmail last ran');
 
 INSERT INTO menus (menu, label, sel_label, value, seclev, menuorder) VALUES ('info','Stats','Stats','[% gSkin.rootdir %]/stats.pl',1,2);

Modified: slashjp/trunk/plugins/Stats/stats.pl
===================================================================
--- slashjp/trunk/plugins/Stats/stats.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/stats.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -37,6 +37,7 @@
 		table	=> [ $admin,		\&table		],
 		csv	=> [ $admin,		\&csv		],
 		list	=> [ $admin_post,	\&list		],
+		topics	=> [ $admin,		\&topics	],
 
 		default	=> [ $admin,		\&list		]
 	);
@@ -262,6 +263,15 @@
 	return \%skins;
 }
 
+sub topics {
+	my($slashdb, $constants, $user, $form, $stats) = @_;
+	my $days = $form->{days} ||= 30;
+	my $sort = $form->{sort} eq "name" ? "name" : "hits";
+	my $topic_stats = $stats->getTopicStats($days, $sort);
+	slashDisplay("topic_stats", { topic_stats => $topic_stats });
+
+}
+
 createEnvironment();
 main();
 


Property changes on: slashjp/trunk/plugins/Stats/templates/csv;stats;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Stats/templates/display;adminmail;default
===================================================================
--- slashjp/trunk/plugins/Stats/templates/display;adminmail;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Stats/templates/display;adminmail;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -151,10 +151,18 @@
 
 -----------------------
 
-[% FOREACH item = lazy -%]
+Top stories viewed by article.pl:
+[% FOREACH item = lazy_article -%]
 [% item %]
 [% END %]
 
+[% IF lazy_rss.size %]
+Top stories viewed in RSS:
+[% FOREACH item = lazy_rss -%]
+[% item %]
+[% END %]
+
+[% END %]
 [% IF top_referers.size %]
 -----------------------      
 
@@ -221,6 +229,12 @@
 [% firehose_report %]
 [% END %]
 
+[% IF is_spam_new_count.defined %]
+Yesterday's admin binspammed globjs: [% binspam_globj_count %]
+Yesterday's hose item is_spams: [% is_spam_new_count %]
+Yesterday's Despam autodetects: [% is_spam_autodetected_count %]
+[% END %]
+
 [% IF tags_report %]
 Tags Report
 ------------------------------------


Property changes on: slashjp/trunk/plugins/Stats/templates/graphs;stats;default
___________________________________________________________________
Name: svn:executable
   - *

Copied: slashjp/trunk/plugins/Stats/templates/topic_stats;stats;default (from rev 741, slashjp/branches/upstream/2.5.0.218/plugins/Stats/templates/topic_stats;stats;default)
===================================================================
--- slashjp/trunk/plugins/Stats/templates/topic_stats;stats;default	                        (rev 0)
+++ slashjp/trunk/plugins/Stats/templates/topic_stats;stats;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,44 @@
+__section__
+default
+__description__
+You should describe stuff here.
+__title__
+Useless title to template
+__page__
+stats
+__lang__
+en_US
+__name__
+topic_stats
+__seclev__
+10000
+__template__
+<p>
+<form action="[% constants.rootdir %]/stats.pl" method="get">
+<input type="hidden" name="op" value="topics">
+Days: [% Slash.createSelect('days', [30, 60, 90, 180, 365], form.days, 1, 1) %]
+Sort By [% Slash.createSelect('sort', ["hits", "name"], form.sort, 1) %]
+<input type="submit">
+</form>
+<p>
+
+<table border="1" cellpadding="5" cellspacing="5">
+<tr>
+	<td>Topic</td>
+	<td>Total Stories</td>
+	<td>Total Hits</td>
+	<td>Total Comments</td>
+	<td>Avg Hits</td>
+	<td>Avg Comments</td>
+</tr>
+[% FOREACH topic = topic_stats %]
+<tr>
+	<td>[% topic.textname %]<br><img src="[% constants.imagedir %]/topics/[% topic.image %]" alt="[% topic.textname %]"></td>
+	<td>[% topic.cnt %]</td>
+	<td>[% topic.sum_hits %]</td>
+	<td>[% topic.sum_cc %]</td>
+	<td>[% topic.avg_hits %]</td>
+	<td>[% topic.avg_cc %]</td>
+</tr>
+[% END %]
+</table>

Modified: slashjp/trunk/plugins/Submit/mysql_schema.sql
===================================================================
--- slashjp/trunk/plugins/Submit/mysql_schema.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Submit/mysql_schema.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-
+# $Id$
 #
 
 DROP TABLE IF EXISTS submissions_notes;

Modified: slashjp/trunk/plugins/Submit/submit.pl
===================================================================
--- slashjp/trunk/plugins/Submit/submit.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Submit/submit.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -691,6 +691,54 @@
 	yourPendingSubmissions($constants, $slashdb, $user, $form, { skip_submit_body => 1 });
 	print getData("submit_body_close");
 
+        if (!$user->{is_anon}) {
+                my $events = $slashdb->sqlSelectAllHashref(
+                        'eid', 'eid, date', 'user_events', "uid = $uid and code = 3");
+
+                # Delete the oldest event for this user if they already have 5 events.
+                if ((scalar keys %$events) == 5) {
+                        my $eid = [sort keys %$events]->[0];
+                        $slashdb->sqlDelete('user_events', "uid = $uid and code = 3 and eid = $eid");
+                }
+
+                my $submission_id =
+                        $slashdb->sqlSelect("id", "firehose", "uid = $uid and srcid = " . $messagesub->{subid} . " and type = 'submission'");
+
+                # Insert event
+                $slashdb->sqlInsert('user_events', {
+                        code  => 3,
+                        uid   => $uid,
+                        event => $submission_id,
+                        -date  => 'NOW()',
+                });
+
+                # Create/update event block
+                my $event_blocks = $slashdb->sqlSelectAllHashref(
+                        'uid', 'bid, uid, block', 'user_event_blocks', "uid = $uid and code = 3");
+
+                # New block
+                if (!%$event_blocks) {
+                        $slashdb->sqlInsert('user_event_blocks', {
+                                code  => 3,
+                                uid   => $uid,
+                                block => $submission_id,
+                         });
+                } else {
+                        my @blocks = split(/,/, $event_blocks->{$uid}->{block});
+
+                        # Remove oldest event from this block
+                        if (scalar @blocks == 5) {
+                                @blocks = @blocks[1 .. 4];
+                        }
+
+                        # Append new event
+                        $blocks[$#blocks + 1] = $submission_id;
+                        my $new_blocks = join(",", @blocks);
+
+                        $slashdb->sqlUpdate('user_event_blocks', { block => $new_blocks }, "uid = $uid and code = 3");
+                }
+        }
+
 	return(1);
 }
 
@@ -734,7 +782,6 @@
 	# leave if - has nonwhitespace on either side, otherwise, convert
 	unless (getCurrentStatic('submit_keep_dashes')) {
 		$str =~ s/(\s+-+\s+)/ &mdash; /g;
-		$str =~ s/(\s*--+\s*)/ &mdash; /g;
 	}
 
 	$str = balanceTags($str, { deep_nesting => 1 });

Modified: slashjp/trunk/plugins/Submit/templates/displayForm;submit;default
===================================================================
--- slashjp/trunk/plugins/Submit/templates/displayForm;submit;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Submit/templates/displayForm;submit;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -11,6 +11,7 @@
 * topic = submission topic hashref
 * width = passed to titlebar
 * title = passed to titlebar
+* pending = html of pending submissions
 __title__
 
 __page__
@@ -20,7 +21,8 @@
 __name__
 displayForm
 __template__
-
+<div class="generalbody">
+[% pending %]
 [% # set the variable 'subtext'
    submission.storyonly = 0;
    submission.email = fakeemail;
@@ -51,26 +53,30 @@
 	</div>
 	[% END %]
 [% END %]
+
 	<p>
 	Here is where you can submit a story for the [% constants.sitename %] Editors to peer at it, poke it with a stick, and perhaps post it for all to share and enjoy.  It is <strong>very</strong> important that you write a clear simple subject, and include relevant links in your story.  If you wish to be anonymous, feel free to leave the identifying fields blank.  Anonymity has no effect on whether we will accept or reject the story.
 	</p>
+
+[%# username is the only of from, email, subj that needs to be filtered in %]
+
 	<form action="[% env.script_name %]" method="post">
-        [% IF savestory %]
-                <fieldset>
-                        <legend>
-                                Preview Submission
-                        </legend>
+	[% IF savestory %]
+		<fieldset>
+			<legend>
+				Preview Submission
+			</legend>
 			<div class="article">
-                        	[% PROCESS titlebar width => "100%", title => form.subj %]
+				[% PROCESS titlebar width => "100%", title => form.subj %]
 				<div class="body">
-                        		<div class="topic">
-                                		<img src="[% constants.imagedir %]/topics/[% topic.image %]" alt="[% topic.textname %]" width="[% topic.width %]" height="[% topic.height %]">
-                        		</div>
-                       			[% subtext %]
+					<div class="topic">
+						<img src="[% constants.imagedir %]/topics/[% topic.image %]" alt="[% topic.textname %]" width="[% topic.width %]" height="[% topic.height %]">
+					</div>
+					[% subtext %]
 				</div>
 			</div>
-                </fieldset>
-        [% END %]
+		</fieldset>
+	[% END %]
 		<fieldset>
 			<legend>
 				Story Submission Form
@@ -86,15 +92,18 @@
 			[% 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"> Url type [% Slash.createSelect('mediiatype', Slash.db.getDescriptions('mediatypes'), { default => form.mediatype || "none" , return => 1 }) %]
+				<input type="text" name="url" value="[% form.url | strip_attribute %]" size="50"> Url type:
+				[% Slash.createSelect('mediatype', 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"  %]
 			<input type="text" name="subj" value="[% form.subj %]" size="50" maxlength="50">
-			[% PROCESS formNote note => "Be descriptive and concise! For best results, put the most important words first."%]
-			[% PROCESS formNote note => "Bad subjects=&#39;Check This Out!&#39; or &#39;An Article&#39;.  We get many submissions each day, and if yours isn't clear, it will be deleted." %]
+			[% PROCESS formNote note => "Be descriptive and concise!" %]
+			[% PROCESS formNote note => "(Nondescriptive subjects like 'Check this out!' usually just get deleted, because we get many every day. For best results, put the important words early.)" %]
+
 	[% FOR extra = extras %]
-			[% PROCESS formLabel value => extra.0  %]
+		[% PROCESS formLabel value => extra.0, comment => "" %]
 		[% IF extra.2 == 'text' %]
 			<input type="text" name="[% extra.1 %]" value="[% form.${extra.1} | strip_attribute %]" size="50">
 		[% ELSIF extra.2 == 'textarea' %]
@@ -104,6 +113,7 @@
 			[% Slash.createSelect(extra.1, Slash.db.getDescriptions('genericstring',extra.1), form.${extra.1}, 1, 1) %]	
 		[% END %]
 	[% END %]
+
 			[% hide_section_select = 0; hide_topic_select = 0 %]
 			[% primaryskid_val = form.primaryskid.defined ? form.primaryskid : constants.submission_default_skid;
 			IF constants.submission_force_default || (form.primaryskid && form.hss);
@@ -134,16 +144,23 @@
 			[% Slash.createSelect('tid', topic_values, form.tid, 1, 0, 1)%]	
 		[% END %]
 			[% submitToLabel = skins.${constants.mainpage_skid}.title || "the main section" %]
-			[% PROCESS formNote note =>"In general, submit to $submitToLabel" %]
+			[% PROCESS formNote note => "In general, submit to $submitToLabel" %]
+
 			[% PROCESS formLabel value => "The Scoop" %]
 			<textarea wrap="virtual" rows="[% user.textarea_rows || constants.textarea_rows %]" cols="[% user.textarea_cols || constants.textarea_cols %]" name="story">[% form.story | strip_literal %]</textarea><br>
 			[% PROCESS formNote note => "Are you sure you included a URL?  Did you test them for typos?" %]
 			[% PROCESS formNote note => "HTML is fine, but double check those URLs and HTML tags!" %]
-			[% PROCESS formLabel value => "Submission format" %]
+			[% PROCESS formLabel value => "Submission format", comment => "" %]
 			[% def_type = form.sub_type || 'html'; sub_types = { "html" => "HTML Formatted", "plain" => "Plain Old Text" }; Slash.createSelect('sub_type', sub_types, def_type, 1) %]
 			[% IF form.url_id %]
 				<input type="hidden" name="url_id" value="[% form.url_id | strip_attribute %]">
 			[% END %]
+
+			[% IF user.state.hc && !user.state.hcinvalid %]
+			<p>[% user.state.hcquestion; user.state.hchtml %]
+			<input type="text" name="hcanswer" value="[% form.hcanswer | strip_attribute %]" size="8" maxlength="8"></p>
+			[% END %]
+
 			<input type="submit" name="op" value="PreviewStory" class="button">
 		[% IF savestory %]
 			<input type="submit" name="op" value="SubmitStory" class="button">
@@ -152,6 +169,7 @@
 		[% END %]
 		</fieldset>
 	</form>
+</div>
 __seclev__
 10000
 __version__


Property changes on: slashjp/trunk/plugins/Submit/templates/formatSub;submit;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Submit/templates/mergeSub;submit;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/Subscribe/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Subscribe/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Subscribe/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::Subscribe',
-    'VERSION_FROM' => 'Subscribe.pm', # finds $VERSION
     'PM'        => { 'Subscribe.pm' => '$(INST_LIBDIR)/Subscribe.pm' },
 );

Modified: slashjp/trunk/plugins/Subscribe/Static/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Subscribe/Static/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Subscribe/Static/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,5 +2,4 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::Subscribe::Static',
-    'VERSION_FROM' => 'Static.pm', # finds $VERSION
 );

Modified: slashjp/trunk/plugins/Subscribe/Static/Static.pm
===================================================================
--- slashjp/trunk/plugins/Subscribe/Static/Static.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Subscribe/Static/Static.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Subscribe::Static;
 
@@ -10,13 +9,11 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION);
-
 use base 'Exporter';
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $vuser) = @_;

Modified: slashjp/trunk/plugins/Subscribe/Subscribe.pm
===================================================================
--- slashjp/trunk/plugins/Subscribe/Subscribe.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Subscribe/Subscribe.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Subscribe;
 
@@ -10,12 +9,10 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION);
-
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class) = @_;

Modified: slashjp/trunk/plugins/TagDataView/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/TagDataView/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagDataView/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::TagDataView',
-    'VERSION_FROM' => 'TagDataView.pm', # finds $VERSION
     'PM'	=> { 'TagDataView.pm' => '$(INST_LIBDIR)/TagDataView.pm' },
 );

Modified: slashjp/trunk/plugins/TagDataView/PLUGIN
===================================================================
--- slashjp/trunk/plugins/TagDataView/PLUGIN	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagDataView/PLUGIN	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=TagDataView
 description="Tag-related stats data for admins"
 htdoc=tagdataview.pl

Modified: slashjp/trunk/plugins/TagDataView/TagDataView.pm
===================================================================
--- slashjp/trunk/plugins/TagDataView/TagDataView.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagDataView/TagDataView.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 package Slash::TagDataView;
 
@@ -31,9 +30,8 @@
 
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
-use vars qw($VERSION);
 
-($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub getGlobjidsMissingHistory {
 	my($self, $max_mins, $max_min_incrs, $max_globjids) = @_;
@@ -131,7 +129,3 @@
 
 Slash(3).
 
-=head1 VERSION
-
-$Id: $
-

Modified: slashjp/trunk/plugins/TagDataView/mysql_schema.sql
===================================================================
--- slashjp/trunk/plugins/TagDataView/mysql_schema.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagDataView/mysql_schema.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: $
+# $Id$
 #
 
 DROP TABLE IF EXISTS firehose_history;

Modified: slashjp/trunk/plugins/TagDataView/tagdataview.pl
===================================================================
--- slashjp/trunk/plugins/TagDataView/tagdataview.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagDataView/tagdataview.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
+# $Id$
 
 use strict;
 use warnings;
@@ -15,7 +15,7 @@
 use GD::Graph::lines;
 use vars qw($VERSION);
 
-($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
 
 
 sub main {

Modified: slashjp/trunk/plugins/TagDataView/templates/display;tagdataview;default
===================================================================
--- slashjp/trunk/plugins/TagDataView/templates/display;tagdataview;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagDataView/templates/display;tagdataview;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -70,4 +70,4 @@
 __seclev__
 10000
 __version__
-$Id: $
+$Id$

Modified: slashjp/trunk/plugins/TagModeration/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/TagModeration/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagModeration/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,7 +4,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::TagModeration',
-    'VERSION_FROM' => 'TagModeration.pm', # finds $VERSION
     'PM'        => {
 	'TagModeration.pm' => '$(INST_LIBDIR)/TagModeration.pm',
     },

Modified: slashjp/trunk/plugins/TagModeration/PLUGIN
===================================================================
--- slashjp/trunk/plugins/TagModeration/PLUGIN	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagModeration/PLUGIN	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=TagModeration
 description="Moderation (Tags)"
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/plugins/TagModeration/TagModeration.pm
===================================================================
--- slashjp/trunk/plugins/TagModeration/TagModeration.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagModeration/TagModeration.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,1383 +1,57 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 package Slash::TagModeration;
 
 use strict;
-use Date::Format qw(time2str);
+
 use Slash;
 use Slash::Utility;
 use Slash::DB::Utility;
 use Slash::Display;
 
-use vars qw($VERSION);
-use base 'Exporter';
-use base 'Slash::DB::Utility';
-use base 'Slash::DB::MySQL';
+our $VERSION = $Slash::Constants::VERSION;
 
-($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+# most of the guts are now in Slash::Moderation, and we inherit it all ...
+use base 'Slash::Moderation';
 
-sub new {
-	my($class, $user) = @_;
-	my $self = {};
+# ... except for this function, which is manually imported ...
+*ajaxModerateCid = \&Slash::Moderation::ajaxModerateCid;
 
-	my $plugin = getCurrentStatic('plugin');
-	return unless $plugin->{TagModeration};
+# ... and these three methods.
+sub removeModTags {
+	my($self, $uid, $cid) = @_;
 
-	my $constants = getCurrentStatic();
-	return undef unless $constants->{m1} && $constants->{m1_pluginname} eq 'TagModeration';
-
-	bless($self, $class);
-	$self->{virtual_user} = $user;
-	$self->sqlConnect();
-
-	return $self;
-}
-
-########################################################
-
-sub getReasons {
-	my($self) = @_;
-	my $table_cache = "_reasons_cache";
-	$self->{$table_cache} ||= $self->sqlSelectAllHashref(
-		"id", "*", "modreasons"
-	);
-	return {( %{$self->{$table_cache}} )};
-}
-
-########################################################
-
-# to-do:
-#
-# db down
-# allow moderation
-# archived (done)
-# -1 == no points
-# -2 == not enough points
-# already posted
-# $slashdb->setStory($discussion->{sid}, { writestatus => 'dirty' });
-
-sub ajaxModerateCid {
-	my($slashdb, $constants, $user, $form, $options) = @_;
-	my $self = getObject('Slash::TagModeration');
-	my $cid = $form->{cid} or return;
-	my $sid = $form->{sid} or return;
-	my $reason = $form->{reason} or return;
-
-	my $score  = "comment_score_$cid";
-	my $select = "reasondiv_$cid";
-
-	my $html = {};
-	my $error;
-
-	my $discussion = $self->getDiscussion($sid);
-	my $moderate_check = $self->moderateCheck($form, $user, $constants, $discussion);
-
-	if ($moderate_check->{msg}) {
-		$html->{$select} = $moderate_check->{msg};
-	} elsif ($moderate_check->{count}) {
-		$html->{$select} = $moderate_check->{msg};
-	} else {
-		# XXX this should be in templates -- pudge
-		my $ret_val = $self->moderateComment($sid, $cid, $reason, { no_display => 1 });
-		if ($ret_val > 0) {
-			my $comment = $self->getComment($cid) or return;
-			my $reasons = $self->getReasons or return;
-			my $points = getPoints(
-				$comment, $user,
-				$constants->{comment_minscore}, $constants->{comment_maxscore},
-				$self->countUsers({ max => 1 }), $self->getReasons
-			);
-
-			$html->{$score}  = "Score:$points";
-			$html->{$score} = qq[<a href="#" onclick="getModalPrefs('modcommentlog', 'Moderation Comment Log', $cid); return false">$html->{$score}</a>]
-				if $constants->{modal_prefs_active} && !$user->{is_anon};
-			$html->{$score} .= ", $reasons->{$comment->{reason}}{name}"
-				if $comment->{reason} && $reasons->{$comment->{reason}};
-			$html->{$score} = "($html->{$score})";
-
-			my $ptstr = $user->{points} == 1 ? 'point' : 'points';
-			$html->{$select} = "Moderated '$reasons->{$reason}{name}.'  $user->{points} $ptstr left.";
-			$self->setStory($sid, { writestatus => 'dirty' });
-
-		} elsif (!$ret_val) {
-			$html->{$select} = "Error: No moderation performed.";
-
-		} elsif ($ret_val == -1) {
-
-		} elsif ($ret_val == -2) {
-			$html->{$select} = "Error: $user->{points} moderation points left.";
-		}
+	my $comment_globjid = $self->getGlobjidFromTargetIfExists('comments', $cid);
+	if ($comment_globjid) {
+		my $tagsdb = getObject('Slash::Tags');
+		$tagsdb->deactivateTag({ globjid => $comment_globjid, uid => $uid });
 	}
 
-	$options->{content_type} = 'application/json';
-	return Data::JavaScript::Anon->anon_dump({
-		html    => $html,
-		error   => $error,
-	});
 }
 
-##################################################################
-# moderateComment
-#
-# Handles moderation
-# Moderates a specific comment.
-# Returns 0 or 1 for whether the comment changed
-# Returns a negative value when an error was encountered. The
-# warning the user sees is handled within the .pl file.
-#
-# Currently defined error types:
-# -1 - No points
-# -2 - Not enough points
-#
-##################################################################
+sub createModTag {
+	my($self, $uid, $cid, $reason) = @_;
 
-sub moderateComment {
-	my($self, $sid, $cid, $reason, $options) = @_;
-	return 0 unless dbAvailable("write_comments");
-	return 0 unless $reason;
-	$options ||= {};
-
-	my $constants = getCurrentStatic();
-	my $user = getCurrentUser();
-
-	my $comment_changed = 0;
-	my $superAuthor = $options->{is_superauthor}
-		|| ( $constants->{authors_unlimited}
-			&& $user->{seclev} >= $constants->{authors_unlimited} );
-
-	if ($user->{points} < 1 && !$superAuthor) {
-		return -1;
-	}
-
-	my $comment = $self->getComment($cid);
-
-	$comment->{time_unixepoch} = timeCalc($comment->{date}, "%s", 0);
-
-	# The user should not have been been presented with the menu
-	# to moderate if any of the following tests trigger, but,
-	# an unscrupulous user could have faked their submission with
-	# or without us presenting them the menu options.  So do the
-	# tests again.  XXX  These tests are basically copy-and-pasted
-	# from Slash.pm _can_mod, which should be rectified. -Jamie
-	# use reskeys instead ... -Pudge
-	# One or more reskey checks will need to invoke can_mod or some
-	# subset of it. -Jamie
-	unless ($superAuthor) {
-		# Do not allow moderation of any comments with the same UID as the
-		# current user (duh!).
-		return 0 if $user->{uid} == $comment->{uid};
-		# Do not allow moderation of any comments (anonymous or otherwise)
-		# with the same IP as the current user.
-		return 0 if $user->{ipid} eq $comment->{ipid};
-		# If the var forbids it, do not allow moderation of any comments
-		# with the same *subnet* as the current user.
-		return 0 if $constants->{mod_same_subnet_forbid}
-			and $user->{subnetid} eq $comment->{subnetid};
-		# Do not allow moderation of comments that are too old.
-		return 0 unless $comment->{time_unixepoch} >= time() - 3600*
-			($constants->{comments_moddable_hours}
-				|| 24*$constants->{archive_delay});
-	}
-
-	# Start putting together the data we'll need to display to
-	# the user.
-	my $reasons = $self->getReasons();
-	my $dispArgs = {
-		cid     => $cid,
-		sid     => $sid,
-		subject => $comment->{subject},
-		reason  => $reason,
-		points  => $user->{points},
-		reasons => $reasons,
-	};
-
-	unless ($superAuthor) {
-		my $mid = $self->getModeratorLogID($cid, $user->{uid});
-		if ($mid) {
-			$dispArgs->{type} = 'already moderated';
-			Slash::slashDisplay('moderation', $dispArgs)
-				unless $options->{no_display};
-			return 0;
-		}
-	}
-
-	# Add moderation value to display arguments.
-	my $val = $reasons->{$reason}{val};
-	my $raw_val = $val;
-	$val = "+1" if $val == 1;
-	$dispArgs->{val} = $val;
-
-	my $scorecheck = $comment->{points} + $val;
-	my $active = 1;
-	# If the resulting score is out of comment score range, no further
-	# actions need be performed.
-	# Should we return here and go no further?
-	if (    $scorecheck < $constants->{comment_minscore} ||
-		($scorecheck > $constants->{comment_maxscore} && $val + $comment->{tweak} > 0 ))
-	{
-		# We should still log the attempt for M2, but marked as
-		# 'inactive' so we don't mistakenly undo it. Mods get modded
-		# even if the action didn't "really" happen.
-		#
-		$active = 0;
-		$dispArgs->{type} = 'score limit';
-	}
-
-	# Find out how many mod points this will really cost us.  As of
-	# Oct. 2002, it might be more than 1.
-	my $pointsneeded = $self->getModPointsNeeded(
-		$comment->{points},
-		$scorecheck,
-		$reason);
-
-	# If more than 1 mod point needed, we might not have enough,
-	# so this might still fail.
-	if ($pointsneeded > $user->{points} && !$superAuthor) {
-		return -2;
-	}
-
-	# Write the proper records to the moderatorlog.
-	$self->createModeratorLog($comment, $user, $val, $reason, $active,
-		$pointsneeded);
-
-	if ($active) {
-
-		# If we are here, then the user either has mod points, or
-		# is an admin (and 'author_unlimited' is set).  So point
-		# checks should be unnecessary here.
-
-		# First, update values for the moderator.
-		my $changes = { };
-		$changes->{-points} = "GREATEST(points-$pointsneeded, 0)";
-		my $tcost = $constants->{mod_unm2able_token_cost} || 0;
-		$tcost = 0 if $reasons->{$reason}{m2able};
-		$changes->{-tokens} = "tokens - $tcost" if $tcost;
-		$changes->{-totalmods} = "totalmods + 1";
-		$self->setUser($user->{uid}, $changes);
-		$user->{points} -= $pointsneeded;
-		$user->{points} = 0 if $user->{points} < 0;
-
-		# Update stats.
-		if ($tcost and my $statsSave = getObject('Slash::Stats::Writer')) {
-			$statsSave->addStatDaily("mod_tokens_lost_unm2able", $tcost);
-		}
-
-		# Apply our changes to the comment.
-		my $comment_change_hr =
-			$self->setCommentForMod($cid, $val, $reason,
-				$comment->{reason});
-		if (!defined($comment_change_hr)) {
-			# This shouldn't happen;  the only way we believe it
-			# could is if $val is 0, the comment is already at
-			# min or max score, the user's already modded this
-			# comment, or some other reason making this mod invalid.
-			# This is really just here as a safety check.
-			$dispArgs->{type} = 'logic error';
-			Slash::slashDisplay('moderation', $dispArgs)
-				unless $options->{no_display};
-			return 0;
-		}
-
-		# Finally, adjust the appropriate values for the user who
-		# posted the comment.
-		my $poster_was_anon = isAnon($comment->{uid});
-		my $karma_change = $reasons->{$reason}{karma};
-		$karma_change = 0 if $poster_was_anon;
-		my $token_change = 0;
-		if ($karma_change) {
-			# If this was a downmod, it may cost the poster
-			# something other than exactly 1 karma.
-			if ($karma_change < 0) {
-				($karma_change, $token_change) =
-					$self->_calc_karma_token_loss(
-						$karma_change, $comment_change_hr)
-			}
-		}
-		if ($karma_change) {
-			my $cu_changes = { };
-			if ($val < 0) {
-				$cu_changes->{-downmods} = "downmods + 1";
-			} elsif ($val > 0) {
-				$cu_changes->{-upmods} = "upmods + 1";
-			}
-			if ($karma_change < 0) {
-				$cu_changes->{-karma} = "GREATEST("
-					. "$constants->{minkarma}, karma + $karma_change)";
-				$cu_changes->{-tokens} = "tokens + $token_change";
-			} elsif ($karma_change > 0) {
-				$cu_changes->{-karma} = "LEAST("
-					. "$constants->{maxkarma}, karma + $karma_change)";
-			}
-
-			# Make the changes to the poster user.
-			$self->setUser($comment->{uid}, $cu_changes);
-
-			# Update stats.
-			if ($karma_change < 0 and my $statsSave = getObject('Slash::Stats::Writer')) {
-				$statsSave->addStatDaily("mod_tokens_lost_downmod",
-					$token_change);
-			}
-
-		}
-
-		# We know things actually changed, so update points for
-		# display and send a message if appropriate.
-		$dispArgs->{points} = $user->{points};
-		$dispArgs->{type} = 'moderated';
-		if (($comment->{points} + $comment->{tweak} + $raw_val) >= $constants->{comment_minscore} &&
-		    ($comment->{points} + $comment->{tweak}) >= $constants->{comment_minscore}) {
-
-			my $messages = getObject("Slash::Messages");
-			$messages->send_mod_msg({
-				type    => 'mod_msg',
-				sid     => $sid,
-				cid     => $cid,
-				val     => $val,
-				reason  => $reason,
-				comment => $comment
-			}) unless $options->{no_message};
-		}
-	}
-
-	# Now display the template with the moderation results.
-	Slash::slashDisplay('moderation', $dispArgs)
-		unless $options->{no_display};
-
-	return 1;
-}
-
-# setCommentForMod returns either undef (if the comment did not change)
-# or (if it did) a hashref about the changed comment score.  It's
-# currently called only by moderateComment.
-
-sub setCommentForMod {
-	my($self, $cid, $val, $newreason, $oldreason) = @_;
-	my $raw_val = $val;
-	$val += 0;
-	return undef if !$val;
-	$val = "+$val" if $val > 0;
-
-	my $user = getCurrentUser();
-	my $constants = getCurrentStatic();
-	my $clear_ctp = 0;
-
-	my $allreasons_hr = $self->sqlSelectAllHashref(
-		"reason",
-		"reason, COUNT(*) AS c",
-		"moderatorlog",
-		"cid=$cid AND active=1",
-		"GROUP BY reason"
-	);
-	my $averagereason = $self->getCommentMostCommonReason($cid,
-		$allreasons_hr,
-		$newreason, $oldreason);
-
-	# Changes we're going to make to this comment.  Note
-	# that the pointsmax GREATEST() gets called after
-	# points is assigned, thanks to assn_order.
-	my $update = {
-		-points =>      "points$val",
-		-pointsmax =>   "GREATEST(pointsmax, points)",
-		reason =>       $averagereason,
-		lastmod =>      $user->{uid},
-	};
-
-	# If more than n downmods, a comment loses its karma bonus.
 	my $reasons = $self->getReasons;
-	my $num_downmods = 0;
-	for my $reason (keys %$allreasons_hr) {
-		$num_downmods += $allreasons_hr->{$reason}{c}
-			if $reasons->{$reason}{val} < 0;
-	}
-	if ($num_downmods > $constants->{mod_karma_bonus_max_downmods}) {
-		$update->{karma_bonus} = "no";
-		# If we remove a karma_bonus, we must invalidate the
-		# comment_text (because the noFollow changes).  Sadly
-		# at this point we don't know (due to performance
-		# requirements and atomicity) whether we are actually
-		# changing the value of this column, but we have to
-		# invalidate the cache anyway.
-		$clear_ctp = 1;
-	}
-
-	# Make sure we apply this change to the right comment :)
-	my $where = "cid=$cid ";
-	my $points_extra_where = "";
-	if ($val < 0) {
-		$points_extra_where .= " AND points > $constants->{comment_minscore}";
-	} else {
-		$points_extra_where .= " AND points < $constants->{comment_maxscore}";
-	}
-	$where .= " AND lastmod <> $user->{uid}"
-		unless $constants->{authors_unlimited}
-			&& $user->{seclev} >= $constants->{authors_unlimited};
-
-	# We do a two-query transaction here:  one select to get
-	# the old points value, then the update as part of the
-	# same transaction;  that way, we know, based on whether
-	# the update succeeded, what the final points value is.
-	# If this weren't a transaction, another moderation
-	# could happen between the two queries and give us the
-	# wrong answer.  On the other hand, if the caller didn't
-	# want the point change, we don't need to get any of
-	# that data.
-	# We have to select cid here because LOCK IN SHARE MODE
-	# only works when an indexed column is returned.
-	# Of course, this isn't actually going to work at all
-	# (unless you keep your main DB all-InnoDB and put the
-	# MyISAM FULLTEXT indexes onto a slave search-only DB)
-	# since the comments table is MyISAM.  Eventually, though,
-	# we'll pull the indexed blobs out and into comments_text
-	# and make the comments table InnoDB and this will work.
-	# Oh well.  Meanwhile, the worst thing that will happen is
-	# a few wrong points logged here and there.
-	# XXX Hey, comments table is InnoDB now.  That comment
-	# above needs to be revised, and it might be time to look
-	# over the code too.
-
-#       $self->{_dbh}{AutoCommit} = 0;
-	$self->sqlDo("SET AUTOCOMMIT=0");
-
-	my $hr = { };
-	($hr->{cid}, $hr->{points_before}, $hr->{points_orig}, $hr->{points_max}, $hr->{karma}) =
-		$self->sqlSelect("cid, points, pointsorig, pointsmax, karma",
-			"comments", "cid=$cid", "LOCK IN SHARE MODE");
-	$hr->{points_change} = $val;
-	$hr->{points_after} = $hr->{points_before} + $val;
-
-	my $karma_val;
-	my $karma_change = $reasons->{$newreason}{karma};
-	if (!$constants->{mod_down_karmacoststyle}) {
-		$karma_val = $karma_change;
-	} elsif ($val < 0) {
-		$karma_val = ($hr->{points_before} + $karma_change) - $hr->{points_max};
-	} else {
-		$karma_val = $karma_change;
-	}
-
-	if ($karma_val < 0
-		&& defined($constants->{comment_karma_limit})
-		&& $constants->{comment_karma_limit} ne "") {
-		my $future_karma = $hr->{karma} + $karma_val;
-		if ($future_karma < $constants->{comment_karma_limit}) {
-			$karma_val = $constants->{comment_karma_limit} - $hr->{karma};
-		}
-		$karma_val = 0 if $karma_val > 0; # just to make sure
-	}
-
-	if ($karma_val) {
-		my $karma_abs_val = abs($karma_val);
-		$update->{-karma}     = sprintf("karma%+d", $karma_val);
-		$update->{-karma_abs} = sprintf("karma_abs%+d", $karma_abs_val);
-	}
-
-	my $changed = $self->sqlUpdate("comments", $update, $where.$points_extra_where, {
-		assn_order => [ "-points", "-pointsmax" ]
+	my $reason_name = lc $reasons->{$reason}{name};
+	my $tagsdb = getObject('Slash::Tags');
+	my $created = $tagsdb->createTag({
+		table   => 'comments',
+		id      => $cid,
+		uid     => $uid,
+		name    => $reason_name,
+		private => 1,
 	});
-	$changed += 0;
-	if (!$changed && $raw_val > 0) {
-		$update->{-points} = "points";
-		$update->{-tweak}  = "tweak$val";
-		my $tweak_extra = " AND tweak$val <= 0";
-		$changed = $self->sqlUpdate("comments", $update, $where.$tweak_extra, {
-			assn_order => [ "-points", "-pointsmax" ]
-		});
-	}
-	$changed += 0;
-	if (!$changed) {
-		# If the row in the comments table didn't change, then
-		# the karma_bonus didn't change, so we know there is
-		# no need to clear the comment text cache.
-		$clear_ctp = 0;
-	}
 
-#       $self->{_dbh}->commit;
-#       $self->{_dbh}{AutoCommit} = 1;
-	$self->sqlDo("COMMIT");
-	$self->sqlDo("SET AUTOCOMMIT=1");
-
-	if ($clear_ctp and my $mcd = $self->getMCD()) {
-		my $mcdkey = "$self->{_mcd_keyprefix}:ctp:";
-		$mcd->delete("$mcdkey$cid", 3);
-	}
-
-	return $changed ? $hr : undef;
-}
-
-# This gets the mathematical mode, in other words the most common,
-# of the moderations done to a comment.  If no mods, return undef.
-# If a comment's net moderation is down, choose only one of the
-# negative mods, and the opposite for up.  Tiebreakers break ties,
-# first tiebreaker found wins.  "cid" is a key in moderatorlog
-# so this is not a table scan.  It's currently called only by
-# setCommentForMod and undoModeration.
-sub getCommentMostCommonReason {
-	my($self, $cid, $allreasons_hr, $new_reason, @tiebreaker_reasons) = @_;
-	$new_reason = 0 if !$new_reason;
-	unshift @tiebreaker_reasons, $new_reason if $new_reason;
-
-	my $reasons = $self->getReasons();
-	my $listable_reasons = join(",",
-		sort grep { $reasons->{$_}{listable} }
-		keys %$reasons);
-	return undef if !$listable_reasons;
-
-	# Build the hashref of reason counts for this comment, for all
-	# listable reasons.  If allreasoncounts_hr was passed in, this
-	# is easy (just grep out the nonlistable ones).  If not, we have
-	# to do a DB query.
-	my $hr = { };
-	if ($allreasons_hr) {
-		for my $reason (%$allreasons_hr) {
-			$hr->{$reason} = $allreasons_hr->{$reason}
-				if $reasons->{$reason}{listable};
-		}
-	} else {
-		$hr = $self->sqlSelectAllHashref(
-			"reason",
-			"reason, COUNT(*) AS c",
-			"moderatorlog",
-			"cid=$cid AND active=1
-			 AND reason IN ($listable_reasons)",
-			"GROUP BY reason"
-		);
-	}
-
-	# If no mods that are listable, return undef.
-	return undef if !keys %$hr;
-
-	# We need to know if the comment has been moderated net up,
-	# net down, or to a net tie, and if not a tie, restrict
-	# ourselves to choosing only reasons from that direction.
-	# Note this isn't atomic with the actual application of, or
-	# undoing of, the moderation in question.  Oh well!  If two
-	# mods are applied at almost exactly the same time, there's
-	# a one in a billion chance the comment will end up with a
-	# wrong (but still plausible) reason field.  I'm not going
-	# to worry too much about it.
-	# Also, I'm doing this here, with a separate for loop to
-	# screen out unacceptable reasons, instead of putting this
-	# "if" into the same for loop above, because it may save a
-	# query (if a comment is modded entirely with Under/Over).
-	my($points, $pointsorig) = $self->sqlSelect(
-		"points, pointsorig", "comments", "cid=$cid");
-	if ($new_reason) {
-		# This mod hasn't been taken into account in the
-		# DB yet, but it's about to be applied.
-		$points += $reasons->{$new_reason}{val};
-	}
-	my $needval = $points - $pointsorig;
-	if ($needval) {
-		   if ($needval >  1) { $needval =  1 }
-		elsif ($needval < -1) { $needval = -1 }
-		my $new_hr = { };
-		for my $reason (keys %$hr) {
-			$new_hr->{$reason} = $hr->{$reason}
-				if $reasons->{$hr->{$reason}{reason}}{val} == $needval;
-		}
-		$hr = $new_hr;
-	}
-
-	# If no mods that are listable, return undef.
-	return undef if !keys %$hr;
-
-	# Sort first by popularity and secondarily by reason.
-	# "reason" is a numeric field, so we sort $a<=>$b numerically.
-	my @sorted_keys = sort {
-		$hr->{$a}{c} <=> $hr->{$b}{c}
-		||
-		$a <=> $b
-	} keys %$hr;
-	my $top_count = $hr->{$sorted_keys[-1]}{c};
-	@sorted_keys = grep { $hr->{$_}{c} == $top_count } @sorted_keys;
-	# Now sorted_keys are only the top values, one or more of them,
-	# any of which could be the winning reason.
-	if (scalar(@sorted_keys) == 1) {
-		# A clear winner.  Return it.
-		return $sorted_keys[0];
-	}
-	# No clear winner. Are any of our tiebreakers contenders?
-	my %sorted_hash = ( map { $_ => 1 } @sorted_keys );
-	for my $reason (@tiebreaker_reasons) {
-		# Yes, return the first tiebreaker we find.
-		return $reason if $sorted_hash{$reason};
-	}
-	# Nope, we don't have a good way to resolve the tie. Pick whatever
-	# comes first in the reason list (reasons are all numeric and
-	# sorted_keys is already sorted, making this easy).
-	return $sorted_keys[0];
-}
-
-##################################################################
-
-=head2 dispModCommentLog(TYPE, ID)
-
-Returns the HTML for a table detailing the history of moderation of a
-particular comment and/or the reasons why a comment is scored like it is.
-The "mod" in this method's title is intended to reflect that the info
-it returns includes both moderations and comment-score-modifiers.
-
-=over 4
-
-=item Parameters
-
-=over 4
-
-=item TYPE
-
-String describing type of the ID data:  cid, uid, cuid, ipid, subnetid,
-bipid or bsubnetid.
-
-=item ID
-
-Cid or IPID.
-
-=back
-
-=item Return value
-
-The HTML.
-
-=item Dependencies
-
-The 'modCommentLog' template.
-
-=back
-
-=cut
-
-sub dispModCommentLog {
-	my($self, $type, $value, $options) = @_;
-	$options ||= {};
-	my $title = $options->{title};
-	my $constants = getCurrentStatic();
-	my $user = getCurrentUser();
-
-	# If the user doesn't want even to see the numeric score of
-	# a comment, they certainly don't want to see all this detail.
-	return "" if $user->{noscores};
-
-	my $seclev = $user->{seclev};
-	my $mod_admin = $seclev >= $constants->{modviewseclev} ? 1 : 0;
-
-	my $asc_desc = $type eq 'cid' ? 'ASC' : 'DESC';
-	my $limit = $type eq 'cid' ? 0 : 100;
-	my $both_mods = (($type =~ /ipid/) || ($type =~ /subnetid/) || ($type =~ /global/)) ? 1 : 0;
-	my $skip_ip_disp = 0;
-	if ($type =~ /^b(ip|subnet)id$/) {
-		$skip_ip_disp = 1;
-	} elsif ($type =~ /^(ip|subnet)id$/) {
-		$skip_ip_disp = 2;
-	}
-	my $gmcl_opts = {};
-	$gmcl_opts->{hours_back} = $options->{hours_back} if $options->{hours_back};
-	$gmcl_opts->{order_col} = "reason" if $type eq "cid";
-
-	my $mods = $self->getModeratorCommentLog($asc_desc, $limit,
-		$type, $value, $gmcl_opts);
-
-	my $timestamp_hr = exists $options->{hr_hours_back}
-		? $self->getTime({ add_secs => -3600 * $options->{hr_hours_back} })
-		: "";
-
-	if (!$mod_admin) {
-		# Eliminate inactive moderations from the list.
-		$mods = [ grep { $_->{active} } @$mods ];
-	}
-
-	my($reasons, @return, @reasonHist);
-	my $reasonTotal = 0;
-	$reasons = $self->getReasons();
-
-	# Note: Before 2001/01/27 or so, the only things being displayed
-	# in this template were moderations, and if there were none,
-	# we could short-circuit here if @$mods was empty.  But now,
-	# the template handles that decision.
-	my $seen_mods = {};
-	for my $mod (@$mods) {
-		$seen_mods->{$mod->{id}}++;
-		vislenify($mod); # add $mod->{ipid_vis}
-		#$mod->{ts} = substr($mod->{ts}, 5, -3);
-	       $mod->{nickname2} = $self->getUser($mod->{uid2},
-			'nickname') if $both_mods; # need to get 2nd nick
-		next unless $mod->{active};
-		$reasonHist[$mod->{reason}]++;
-		$reasonTotal++;
-	}
-
-	my $listed_reason = 0;
-	if ($type eq 'cid') {
-		my $val_q = $self->sqlQuote($value);
-		$listed_reason = $self->sqlSelect("reason", "comments", "cid=$val_q");
-	}
-	my @reasonsTop = $self->getTopModReasons($reasonTotal, $listed_reason, \@reasonHist);
-
-	my $show_cid    = ($type eq 'cid') ? 0 : 1;
-	my $show_modder = $mod_admin ? 1 : 0;
-	my $mod_to_from = ($type eq 'uid') ? 'to' : 'from';
-
-	my $modifier_hr = { };
-	my $reason = 0;
-	if ($type eq 'cid') {
-		my $cid_q = $self->sqlQuote($value);
-		my($min, $max) = ($constants->{comment_minscore},
-				  $constants->{comment_maxscore});
-		# XXXMULTIPLEMASTERS
-		my $max_uid = $self->countUsers({ max => 1 });
-
-		my $select = "cid, uid, karma_bonus, reason, points, pointsorig, tweak, tweak_orig";
-		if ($constants->{plugin}{Subscribe} && $constants->{subscribe}) {
-			$select .= ", subscriber_bonus";
-		}
-		my $comment = $self->sqlSelectHashref(
-			$select,
-			"comments",
-			"cid=$cid_q");
-		$comment->{comment} = $self->sqlSelect(
-			"comment",
-			"comment_text",
-			"cid=$cid_q");
-		$reason = $comment->{reason};
-
-		my $user = getCurrentUser();
-		my $points;
-		($points, $modifier_hr) = getPoints($comment, $user, $min, $max, $max_uid, $reasons);
-	}
-
-	my $this_user;
-	$this_user = $self->getUser($value) if $type eq "uid";
-	my $cur_uid;
-	$cur_uid = $value if $type eq "uid" || $type eq "cuid";
-
-	my $mods_to_m2s;
-	if ($constants->{m2}) {
-		my $mod_ids = [keys %$seen_mods];
-		if ($constants->{show_m2s_with_mods} && $options->{show_m2s}) {
-			my $metamod_db = getObject('Slash::Metamod');
-			$mods_to_m2s = $metamod_db->getMetamodsForMods($mod_ids, $constants->{m2_limit_with_mods});
-		}
-	}
-
-	# Do the work to determine which moderations share the same m2s
-	if (       $constants->{m2}
-		&& $type eq 'cid'
-		&& $constants->{show_m2s_with_mods}
-		&& $constants->{m2_multicount}
-		&& $options->{show_m2s}
-	){
-		foreach my $m (@$mods){
-			my $key = '';
-			foreach my $m2 (@{$mods_to_m2s->{$m->{id}}}) {
-				$key .= "$m2->{uid} $m2->{val},";
-			}
-			$m->{m2_identity} = $key;
-		}
-		@$mods = sort {
-			$a->{reason} <=> $b->{reason}
-				||
-			$b->{active} <=> $a->{active}
-				||
-			$a->{m2_identity} cmp $b->{m2_identity}
-		} @$mods;
-	}
-	my $data = {
-		type            => $type,
-		mod_admin       => $mod_admin,
-		mods            => $mods,
-		reasonTotal     => $reasonTotal,
-		reasonHist      => \@reasonHist,
-		reasonsTop      => \@reasonsTop,
-		reasons         => $reasons,
-		reason          => $reason,
-		modifier_hr     => $modifier_hr,
-		show_cid        => $show_cid,
-		show_modder     => $show_modder,
-		mod_to_from     => $mod_to_from,
-		both_mods       => $both_mods,
-		timestamp_hr    => $timestamp_hr,
-		skip_ip_disp    => $skip_ip_disp,
-		this_user       => $this_user,
-		title           => $title,
-		cur_uid         => $cur_uid,
-		value           => $value,
-	};
-	if ($constants->{m2}) {
-		$data->{mods_to_m2s} = $mods_to_m2s;
-		$data->{show_m2s} = $options->{show_m2s};
-		$data->{need_m2_form} = $options->{need_m2_form};
-		$data->{need_m2_button} = $options->{need_m2_button};
-		$data->{meta_mod_only} = $options->{meta_mod_only};
-	}
-	return slashDisplay('modCommentLog', $data,
-		{ Return => 1, Nocomm => 1 });
-}
-
-# This method is currently used only by dispModCommentLog.
-#
-# Takes a reason histogram, a list of counts of each reason mod.
-# So $reasonHist[1] is the number of Offtopic moderations (at
-# least if Offtopic is still reason 1).  Returns a list of hashrefs,
-# the top 3 mods performed and their percentages, rounded to the
-# nearest 10%, sorted largest to smallest.
-
-sub getTopModReasons{
-	my($self, $reasonTotal, $listed_reason, $reasonHist_ar) = @_;
-	return ( ) unless $reasonTotal;
-	my $top_needed = 3;
-	my @reasonsTop = ( );
-
-	# Algorithm by MJD in Perl Quiz of the Week #7
-	# http://perl.plover.com/qotw/r/solution/007
-	my @p = map { $_*10/$reasonTotal } @$reasonHist_ar;
-	my @r = map { int($_+0.5) } @p;
-	my @e = map { $p[$_] - $r[$_] } (0..$#r);
-	my $total_error = 0;
-	for (@e) { $total_error += $_ }
-	# Round total_error to int, to avoid float rounding error
-	my $sign = $total_error < 0 ? -1 : 1;
-	$total_error *= $sign;
-	$total_error = int($total_error+0.5);
-	if ($total_error) {
-		for (0..$#r) {
-			next unless $e[$_] * $sign > 0;
-			$r[$_] += $sign;
-			$total_error--;
-			last if $total_error <= 0;
-		}
-	}
-
-	# This part I added, so if it breaks, don't blame MJD :) JRM
-	my %reasonRound = map { ($_, $r[$_]*10) } (0..$#r);
-	my @rr_keys = sort { $a <=> $b } keys %reasonRound;
-	my $min = (sort { $b <=> $a } values %reasonRound)[$top_needed-1];
-	for my $key (0..$#r) {
-		$reasonRound{$key} = 0 if $reasonRound{$key} < $min;
-	}
-	my $have = 0;
-	for my $key (0..$#r) {
-		++$have if $reasonRound{$key} > $min;
-	}
-	for my $key (0..$#r) {
-		if ($reasonRound{$key} == $min) {
-			if ($have >= $top_needed) {
-				$reasonRound{$key} = 0;
-			} else {
-				++$have;
-			}
-		}
-	}
-	for my $reason (1..$#r) {
-		next unless $reasonRound{$reason};
-		push @reasonsTop, {
-			reason => $reason,
-			percent => $reasonRound{$reason},
-		};
-	}
-	@reasonsTop = sort {
-		($b->{reason} == $listed_reason) <=> ($a->{reason} == $listed_reason)
-		||
-		$b->{percent} <=> $a->{percent}
-		||
-		$a->{reason} <=> $b->{reason}
-	} @reasonsTop;
-
-	return @reasonsTop;
-}
-
-sub moderateCheck {
-	my($self, $form, $user, $constants, $discussion) = @_;
-
-	# all of these can be removed in favor of reskeys, later
-	if (!dbAvailable('write_comments')) {
-		return { msg => Slash::Utility::Comments::getError('comment_db_down') };
-	}
-
-	if (!$constants->{m1}) {
-		return { msg => Slash::Utility::Comments::getError('no_moderation') };
-	}
-
-	if ($discussion->{type} eq 'archived' &&
-	   !$constants->{comments_moddable_archived} &&
-	   !$form->{meta_mod_only}) {
-		return { msg => Slash::Utility::Comments::getError('archive_error') };
-	}
-
-	my $return = {};
-	$return->{count} = $self->countCommentsBySidUID($form->{sid}, $user->{uid})
-		unless (   $constants->{authors_unlimited}
-			&& $user->{seclev} >= $constants->{authors_unlimited}
-		)       || $user->{acl}{modpoints_always};
-	if ($return->{count}) {
-		$return->{msg} = Slash::Utility::Comments::getError('already posted');
-	}
-
-	return $return;
-}
-
-sub checkDiscussionForUndoModeration {
-	my($self, $sid) = @_;
-	my $constants = getCurrentStatic();
-	my $user = getCurrentUser();
-
-	# We abandon this operation, thus allowing mods to remain while
-	# the post goes forward, if:
-	#       1) Moderation is off
-	#       2) The user is anonymous (posting anon is the only way
-	#          to contribute to a discussion after you moderate)
-	#       3) The user has the "always modpoints" ACL
-	#       4) The user has a sufficient seclev
-	return if !$constants->{m1}
-		|| $user->{is_anon}
-		|| $user->{acl}{modpoints_always}
-		|| $constants->{authors_unlimited} && $user->{seclev} >= $constants->{authors_unlimited};
-
-	if ($sid !~ /^\d+$/) {
-		$sid = $self->getDiscussionBySid($sid, 'header');
-	}
-	my $removed = $self->undoModeration($user->{uid}, $sid);
-
-	if ($removed && @$removed) {
-		my $messages = getObject('Slash::Messages');
-		if ($messages) {
-			for my $mod (@$removed) {
-				$mod->{val} =~ s/^(\d)/+$1/;  # put "+" in front if necessary
-				$messages->send_mod_msg({
-					type    => 'unmod_msg',
-					sid     => $sid,
-					cid     => $mod->{cid},
-					val     => $mod->{val},
-					reason  => $mod->{reason}
-				});
-			}
-		}
-	}
-
-	my $removed_text = slashDisplay('undo_mod', { removed => $removed }, { Return => 1, Page => 'comments' });
-	return $removed_text;
-}
-
-sub undoModeration {
-	my($self, $uid, $sid) = @_;
-	my $constants = getCurrentStatic();
-
-	return [] unless dbAvailable("write_comments");
-
-	# querylog isn't going to work for this sqlSelectMany, since
-	# we do multiple other queries while the cursor runs over the
-	# rows it returns.  So don't bother doing the _querylog_start.
-
-	# sid here really refers to discussions.id, NOT stories.sid
-	my $cursor = $self->sqlSelectMany("cid,val,active,cuid,reason",
-		"moderatorlog",
-		"moderatorlog.uid=$uid AND moderatorlog.sid=$sid"
-	);
-
-	my $min_score = $constants->{comment_minscore};
-	my $max_score = $constants->{comment_maxscore};
-	my $min_karma = $constants->{minkarma};
-	my $max_karma = $constants->{maxkarma};
-
-	my @removed;
-	while (my($cid, $val, $active, $cuid, $reason) = $cursor->fetchrow){
-
-		# If moderation wasn't actually performed, we skip ahead one.
-		next if ! $active;
-
-		# We undo moderation even for inactive records (but silently for
-		# inactive ones...).  Leave them in the table but inactive, so
-		# they are still eligible to be metamodded.
-		$self->sqlUpdate("moderatorlog",
-			{ active => 0 },
-			"cid=$cid AND uid=$uid"
-		);
-		# Remove any tags on that comment by this user, as well.
-		my $comment_globjid = $self->getGlobjidFromTargetIfExists('comments', $cid);
-		if ($comment_globjid) {
-			my $tagsdb = getObject('Slash::Tags');
-			$tagsdb->deactivateTag({ globjid => $comment_globjid, uid => $uid });
-		}
-
-		# Restore modded user's karma, again within the proper boundaries.
-		my $adjust = -$val;
-		$adjust =~ s/^([^+-])/+$1/;
-		my $adjust_abs = abs($adjust);
-		$self->sqlUpdate(
-			"users_info",
-			{ -karma =>	$adjust > 0
-					? "LEAST($max_karma, karma $adjust)"
-					: "GREATEST($min_karma, karma $adjust)" },
-			"uid=$cuid"
-		) unless isAnon($cuid);
-
-		# Adjust the comment score up or down, but don't push it
-		# beyond the maximum or minimum.  Also recalculate its reason.
-		# Its pointsmax logically can't change.
-		my $points = $adjust > 0
-			? "LEAST($max_score, points $adjust)"
-			: "GREATEST($min_score, points $adjust)";
-		my $new_reason = $self->getCommentMostCommonReason($cid)
-			|| 0; # no active moderations? reset reason to empty
-		my $comm_update = {
-			-points =>      $points,
-			reason =>       $new_reason,
-		};
-		$self->sqlUpdate("comments", $comm_update, "cid=$cid");
-
-		push @removed, {
-			cid     => $cid,
-			reason  => $reason,
-			val     => $val,
-		};
-	}
-
-	return \@removed;
-}
-
-sub getModeratorLogID {
-	my($self, $cid, $uid) = @_;
-	my($mid) = $self->sqlSelect("id", "moderatorlog",
-		"uid=$uid AND cid=$cid");
-	return $mid;
-}
-
-sub getMaxModeratorlogId {
-	my($self) = @_;
-	return $self->sqlSelect("MAX(id)", "moderatorlog");
-}
-
-sub getModeratorLog {
-	my $answer = Slash::DB::MySQL::_genericGet({
-		table           => 'moderatorlog',
-		arguments       => \@_,
-	});
-	return $answer;
-}
-
-sub countUserModsInDiscussion {
-	my($self, $uid, $disc_id) = @_;
-	my $uid_q = $self->sqlQuote($uid);
-	my $disc_id_q = $self->sqlQuote($disc_id);
-	return $self->sqlCount(
-		"moderatorlog",
-		"uid=$uid_q AND active=1 AND sid=$disc_id_q");
-}
-
-sub getModeratorCommentLog {
-	my($self, $asc_desc, $limit, $t, $value, $options) = @_;
-	my $constants = getCurrentStatic();
-	# $t tells us what type of data $value is, and what type of
-	# information we're looking to retrieve
-	$options ||= {};
-	$asc_desc ||= 'ASC';        $asc_desc = uc $asc_desc;
-	$asc_desc = 'ASC' if $asc_desc ne 'DESC';
-	my $order_col = $options->{order_col} || "ts";
-
-	if ($limit and $limit =~ /^(\d+)$/) {
-		$limit = "LIMIT $1";
-	} else {
-		$limit = "";
-	}
-
-	my $cidlist;
-	if ($t eq "cidin") {
-		if (ref $value eq "ARRAY" and @$value) {
-			$cidlist = join(',', @$value);
-		} elsif (!ref $value and $value) {
-			$cidlist = $value;
-		} else {
-			return [];
-		}
-	}
-
-	my $select_extra = (($t =~ /ipid/) || ($t =~ /subnetid/) || ($t =~ /global/))
-		? ", comments.uid AS uid2, comments.ipid AS ipid2"
-		: "";
-	if ($constants->{m2}) {
-		$select_extra .= ', moderatorlog.m2status AS m2status';
-	}
-
-	my $vq = $self->sqlQuote($value);
-	my $where_clause = "";
-	my $ipid_table = "moderatorlog";
-	   if ($t eq 'uid')       { $where_clause = "comments.uid=users.uid AND     moderatorlog.uid=$vq";
-				    $ipid_table = "comments"                                                        }
-	elsif ($t eq 'cid')       { $where_clause = "moderatorlog.uid=users.uid AND moderatorlog.cid=$vq"           }
-	elsif ($t eq 'cuid')      { $where_clause = "moderatorlog.uid=users.uid AND moderatorlog.cuid=$vq"          }
-	elsif ($t eq 'cidin')     { $where_clause = "moderatorlog.uid=users.uid AND moderatorlog.cid IN ($cidlist)" }
-	elsif ($t eq 'subnetid')  { $where_clause = "moderatorlog.uid=users.uid AND comments.subnetid=$vq"          }
-	elsif ($t eq 'ipid')      { $where_clause = "moderatorlog.uid=users.uid AND comments.ipid=$vq"              }
-	elsif ($t eq 'bsubnetid') { $where_clause = "moderatorlog.uid=users.uid AND moderatorlog.subnetid=$vq"      }
-	elsif ($t eq 'bipid')     { $where_clause = "moderatorlog.uid=users.uid AND moderatorlog.ipid=$vq"          }
-	elsif ($t eq 'global')    { $where_clause = "moderatorlog.uid=users.uid"                                    }
-	return [ ] unless $where_clause;
-
-	my $time_clause = "";
-	$time_clause = " AND ts > DATE_SUB(NOW(), INTERVAL $options->{hours_back} HOUR)" if $options->{hours_back};
-
-	my $qlid = $self->_querylog_start("SELECT", "moderatorlog, users, comments");
-	my $sth = $self->sqlSelectMany(
-		"comments.sid AS sid,
-		 comments.cid AS cid,
-		 comments.pid AS pid,
-		 comments.points AS score,
-		 comments.karma AS karma,
-		 comments.tweak AS tweak,
-		 comments.tweak_orig AS tweak_orig,
-		 users.uid AS uid,
-		 users.nickname AS nickname,
-		 $ipid_table.ipid AS ipid,
-		 moderatorlog.val AS val,
-		 moderatorlog.reason AS reason,
-		 moderatorlog.ts AS ts,
-		 moderatorlog.active AS active,
-		 moderatorlog.id AS id,
-		 moderatorlog.points_orig AS points_orig
-		 $select_extra",
-		"moderatorlog, users, comments",
-		"$where_clause
-		 AND moderatorlog.cid=comments.cid
-		 $time_clause",
-		"ORDER BY $order_col $asc_desc $limit"
-	);
-	my(@comments, $comment, @ml_ids);
-	# XXX can simplify this now, don't need to do fetchrow_hashref, can use utility method
-	while ($comment = $sth->fetchrow_hashref) {
-		push @comments, $comment;
-	}
-	$self->_querylog_finish($qlid);
-	if ($constants->{m2}) {
-		my $metamod_db = getObject('Slash::Metamod');
-		$metamod_db->addFairUnfairCounts(\@comments, 'id');
-	}
-	return \@comments;
-}
-
-# At the time of creating a moderation, the caller can influence
-# whether this moderation needs more or fewer M2 votes to reach
-# consensus.  Passing in 0 for the 'm2needed' option means to use
-# the default.  Passing in a positive or negative value means to
-# add that to the default.  Fractional values are fine; the result
-# will always be rounded to an odd number.
-sub createModeratorLog {
-	my($self, $comment, $user, $val, $reason, $active, $points_spent,
-		$options) = @_;
-	my $constants = getCurrentStatic();
-	$active = 1 unless defined $active;
-	$points_spent = 1 unless defined $points_spent;
-	my $uid = $user->{uid};
-	my $cid = $comment->{cid};
-
-	my $metamod_db;
-	$metamod_db = getObject('Slash::Metamod') if $constants->{m2};
-
-	my $mod_hr = {
-		uid     => $uid,
-		ipid    => $user->{ipid} || '',
-		subnetid => $user->{subnetid} || '',
-		val     => $val,
-		sid     => $comment->{sid},
-		cid     => $cid,
-		cuid    => $comment->{uid},
-		reason  => $reason,
-		-ts     => 'NOW()',
-		active  => $active,
-		spent   => $points_spent,
-		points_orig => $comment->{points},
-	};
-	if ($active && $constants->{m2}) {
-		$mod_hr->{m2needed} = $metamod_db->getM2Needed($uid, $cid, $reason,
-			$options->{m2needed} || 0);
-	}
-
-	my $ret_val = $self->sqlInsert('moderatorlog', $mod_hr);
-	if ($constants->{m2}) {
-		my $mod_id = $self->getLastInsertId();
-		$metamod_db->adjustForNewMod($uid, $cid, $reason, $active, $mod_id);
-	}
-	if ($ret_val) {
-		my $reasons = $self->getReasons();
-		my $reason_name = lc $reasons->{$reason}{name};
-		my $tagsdb = getObject('Slash::Tags');
-		my $created = $tagsdb->createTag({
-			table =>	'comments',
-			id =>		$cid,
-			uid =>		$uid,
-			name =>		$reason_name,
-			private =>	1,
-		});
 #print STDERR "TagModeration::createModeratorLog ret_val=$ret_val reason_name='$reason_name' created='$created'\n";
-	}
-	return $ret_val;
 }
 
-sub deleteModeratorlog {
-	my($self, $opts) = @_;
-	my $where;
-
-	if ($opts->{cid}) {
-		$where = 'cid=' . $self->sqlQuote($opts->{cid});
-	} elsif ($opts->{sid}) {
-		$where = 'sid=' . $self->sqlQuote($opts->{sid});
-	} else {
-		return;
-	}
-
-	my $mmids = $self->sqlSelectColArrayref(
-		'id', 'moderatorlog', $where
-	);
-	return unless @$mmids;
-
-	my $mmid_in = join ',', @$mmids;
-	# Delete from metamodlog first since (if built correctly) that
-	# table has a FOREIGN KEY constraint pointing to moderatorlog.
-	my $plugins = getCurrentStatic('plugin');
-	if ($plugins->{Metamod}) {
-		$self->sqlDelete('metamodlog', "mmid IN ($mmid_in)");
-	}
-	$self->sqlDelete('moderatorlog', $where);
-}
-
-########################################################
-
-# these are technically static-only
-
-sub getModderCommenterIPIDSummary {
-	my ($self, $options) = @_;
-	my $ac_uid = getCurrentStatic('anonymous_coward_uid');
-	$options ||= {};
-
-	my @where = ( "moderatorlog.cid=comments.cid" );
-	push @where, "ts > date_sub(NOW(),INTERVAL $options->{days_back} DAY)" if $options->{days_back};
-	push @where, "cuid != $ac_uid" if $options->{no_anon_comments};
-	push @where, "cuid = $ac_uid" if $options->{only_anon_comments};
-	push @where, "id >= $options->{start_at_id}" if $options->{start_at_id};
-	push @where, "id <= $options->{end_at_id}" if $options->{end_at_id};
-	push @where, "comments.ipid IS NOT NULL AND comments.ipid!=''" if $options->{need_ipid};
-
-	my $where = join(" AND ", @where);
-
-	my $mods = $self->sqlSelectAllHashref(
-			[qw(uid ipid)],
-			"moderatorlog.uid AS uid, comments.ipid AS ipid, COUNT(*) AS count",
-			"moderatorlog, comments",
-			$where,
-			"GROUP BY uid, comments.ipid");
-
-	return $mods;
-}
-
-sub getModderModdeeSummary {
-	my ($self, $options) = @_;
-	my $ac_uid = getCurrentStatic('anonymous_coward_uid');
-	$options ||= {};
-
-	my @where = ( );
-	push @where, "ts > DATE_SUB(NOW(), INTERVAL $options->{days_back} DAY)" if $options->{days_back};
-	push @where, "cuid != $ac_uid" if $options->{no_anon_comments};
-	push @where, "id >= $options->{start_at_id}" if $options->{start_at_id};
-	push @where, "id <= $options->{end_at_id}" if $options->{end_at_id};
-	push @where, "ipid IS NOT NULL AND ipid != ''" if $options->{need_ipid};
-
-	my $where = join(" AND ", @where);
-
-	my $mods = $self->sqlSelectAllHashref(
-			[qw(uid cuid)],
-			"uid, cuid, COUNT(*) AS count",
-			"moderatorlog",
-			$where,
-			"GROUP BY uid, cuid");
-
-	return $mods;
-}
-
-########################################################
-# For process_moderatord.pl
-# Pass in option "sleep_between" of a few seconds, maybe up to a
-# minute, if for some reason the deletion still makes slave
-# replication lag... (but it shouldn't, anymore) - 2005/01/06
-sub deleteOldModRows {
-	my($self, $options) = @_;
-
-	my $reader = getObject('Slash::DB', { db_type => "reader" });
+sub setModPoints {
+	my($self, $uids, $granted, $opts) = @_;
 	my $constants = getCurrentStatic();
-	my $max_rows = $constants->{mod_delete_maxrows} || 1000;
-	my $archive_delay_mod =
-		   $constants->{archive_delay_mod}
-		|| $constants->{archive_delay}
-		|| 14;
-	my $sleep_between = $options->{sleep_between} || 0;
 
-	# Find the minimum ID in these tables that should remain, then
-	# delete everything before it.  We do it this way to keep the
-	# slave DBs tied up on the replication of the deletion query as
-	# little as possible.  Turning off foreign key checking here is
-	# just pretty lame, I know...
-
-	$self->sqlDo("SET FOREIGN_KEY_CHECKS=0");
-
-	# First delete from the bottom up for the moderatorlog.
-
-	my $junk_bottom = $reader->sqlSelect('MIN(id)', 'moderatorlog');
-	my $need_bottom = $reader->sqlSelectNumericKeyAssumingMonotonic(
-		'moderatorlog', 'min', 'id',
-		"ts >= DATE_SUB(NOW(), INTERVAL $archive_delay_mod DAY)");
-	while ($need_bottom && $junk_bottom < $need_bottom) {
-		$junk_bottom += $max_rows;
-		$junk_bottom = $need_bottom if $need_bottom < $junk_bottom;
-		$self->sqlDelete('moderatorlog', "id < $junk_bottom");
-		sleep $sleep_between
-			if $sleep_between;
-	}
-
-	$self->sqlDo("SET FOREIGN_KEY_CHECKS=1");
-	return 0;
-}
-
-########################################################
-# For process_moderatord.pl
-# Slightly new logic.  Now users can accumulate tokens beyond the
-# "trade-in" limit and the token_retention var is obviated.
-# Any user with more than $tokentrade tokens is forced to cash
-# them in for points, but they get to keep any excess tokens.
-# And on 2002/10/23, even newer logic:  the number of desired
-# conversions is passed in and the top that-many token holders
-# get points.
-sub convert_tokens_to_points {
-	my($self, $n_wanted) = @_;
-
-	my $reader = getObject("Slash::DB", { db_type => 'reader' });
-
-	my $constants = getCurrentStatic();
-	my %granted = ( );
-
-	return unless $n_wanted;
-
-	# Sanity check.
-	my $n_users = $reader->countUsers();
-	$n_wanted = int($n_users/10) if $n_wanted > int($n_users)/10;
-
-	my $maxtokens = $constants->{maxtokens} || 60;
-	my $tokperpt = $constants->{tokensperpoint} || 8;
-	my $maxpoints = $constants->{maxpoints} || 5;
-	my $pointtrade = $maxpoints;
-	my $tokentrade = $pointtrade * $tokperpt;
-	$tokentrade = $maxtokens if $tokentrade > $maxtokens; # sanity check
-	my $half_tokentrade = int($tokentrade/2); # another sanity check
-
-	my $uids = $reader->sqlSelectColArrayref(
-		"uid",
-		"users_info",
-		"tokens >= $half_tokentrade",
-		"ORDER BY tokens DESC, RAND() LIMIT $n_wanted",
-	);
-
-	# Locking tables is no longer required since we're doing the
-	# update all at once on just one table and since we're using
-	# + and - instead of using absolute values. - Jamie 2002/08/08
-
 	my($num_high, $sum_high, @high_uids) = (0, 0);
 	for my $uid (@$uids) {
 		next unless $uid;
@@ -1390,496 +64,18 @@
 			$sum_high += $high_clout_count;
 			push @high_uids, $uid;
 		}
-		my $this_pointgain = $pointtrade * (1 + $high_clout_count);
-		my $this_maxpoints = $maxpoints  * (1 + $high_clout_count);
+		my $this_pointgain = $opts->{pointtrade} * (1 + $high_clout_count);
+		my $this_maxpoints = $opts->{maxpoints}  * (1 + $high_clout_count);
 		my $rows = $self->setUser($uid, {
 			-lastgranted    => 'NOW()',
-			-tokens         => "GREATEST(0, tokens - $tokentrade)",
+			-tokens         => "GREATEST(0, tokens - $opts->{tokentrade})",
 			-points         => "LEAST(points + $this_pointgain, $this_maxpoints)",
 		});
-		$granted{$uid} = 1 if $rows;
+		$granted->{$uid} = 1 if $rows;
 	}
 	main::slashdLog("convert_tokens_to_points num_high=$num_high sum_high=$sum_high high_uids='@high_uids'");
-
-	# We used to do some fancy footwork with a cursor and locking
-	# tables.  The only difference between that code and this is that
-	# it only limited points to maxpoints for users with karma >= 0
-	# and seclev < 100.  These aren't meaningful limitations, so these
-	# updates should work as well.  - Jamie 2002/08/08
-	# Actually I don't think these are needed at all. - Jamie 2003/09/09
-	#
-	# 2006/02/09:  I still don't think they're needed, and they are
-	# causing lags in replication...
-	#   Searching rows for update:
-	#   The thread is doing a first phase to find all matching
-	#   rows before updating them. This has to be done if the UPDATE
-	#   is changing the index that is used to find the involved rows.
-	# ...so I'm removing these.  I believe wherever the existing code
-	# increases points or tokens, it updates the oldvalue to
-	# LEAST(newvalue, maxvalue), so these adjustments should never
-	# change anything.
-	# 2006/02/12:  The lag is due to a MySQL bug in 4.1.16 that is
-	# fixed in 4.1.18.  <http://bugs.mysql.com/bug.php?id=15935>
-	# Still, we shouldn't need these.
-#       $self->sqlUpdate(
-#               "users_comments",
-#               { points => $maxpoints },
-#               "points > $maxpoints"
-#       );
-#       $self->sqlUpdate(
-#               "users_info",
-#               { tokens => $maxtokens },
-#               "tokens > $maxtokens"
-#       );
-
-	return \%granted;
 }
 
-########################################################
-# For process_moderatord
-sub stirPool {
-	my($self) = @_;
 
-	# Old var "stir" still works, its value is in days.
-	# But "mod_stir_hours" is preferred.
-	my $constants = getCurrentStatic();
-	my $stir_hours = $constants->{mod_stir_hours}
-		|| $constants->{stir} * 24
-		|| 96;
-	my $tokens_per_pt = $constants->{mod_stir_token_cost} || 0;
-	
-	# This isn't atomic.  But it doesn't need to be.  We could lock the
-	# tables during this operation, but all that happens if we don't
-	# is that a user might use up a mod point that we were about to stir,
-	# and it gets counted twice, later, in stats.  No big whup.
-	
-	my $stir_ar = $self->sqlSelectAllHashrefArray(
-		"users_info.uid AS uid, points",
-		"users_info, users_comments",
-		"users_info.uid = users_comments.uid
-		 AND points > 0
-		 AND DATE_SUB(NOW(), INTERVAL $stir_hours HOUR) > lastgranted"
-	);
-	
-	my $n_stirred = 0;
-	for my $user_hr (@$stir_ar) {
-		my $uid = $user_hr->{uid}; 
-		my $pts = $user_hr->{points};
-		my $tokens_pt_chg = $tokens_per_pt * $pts;
-
-		my $change = { };
-		$change->{points} = 0; 
-		$change->{-lastgranted} = "NOW()";
-		$change->{-stirred} = "stirred + $pts";
-		# In taking tokens away, this subtraction itself will not
-		# cause the value to go negative.
-		$change->{-tokens} = "LEAST(tokens, GREATEST(tokens - $tokens_pt_chg, 0))"
-			if $tokens_pt_chg;
-		$self->setUser($uid, $change);
-
-		$n_stirred += $pts;
-	}
-
-	return $n_stirred;
-} 
-
-########################################################
-# For process_moderatord.pl
-# 
-# New as of 2002/09/05:  returns ordered first by hitcount, and
-# second randomly, so when give_out_tokens() chops off the list
-# halfway through the minimum number of clicks, the survivors
-# are determined at random and not by (probably) uid order.
-# 
-# New as of 2002/09/11:  limit look-back distance to 48 hours,
-# to make the effects of click-grouping more predictable, and
-# not being erased all at once with accesslog expiration.
-# 
-# New as of 2003/01/30:  fetchEligibleModerators() has been
-# split into fetchEligibleModerators_accesslog and
-# fetchEligibleModerators_users.  The first pulls down the data
-# we need from accesslog, which may be a different DBIx virtual
-# user (different database).  The second uses that data to pull
-# down the rest of the data we need from the users tables.
-# Also, the var mod_elig_hoursback is no longer needed.
-# Note that fetchEligibleModerators_accesslog can return a
-# *very* large hashref.
-# 
-# New as of 2004/02/04:  fetchEligibleModerators_accesslog has
-# been split into ~_insertnew, ~_deleteold, and ~_read.  They
-# all are methods for the logslavedb, which may or may not be
-# the same as the main slashdb.
-
-sub fetchEligibleModerators_accesslog_insertnew {
-	my($self, $lastmaxid, $newmaxid, $youngest_uid) = @_;
-	return if $lastmaxid > $newmaxid;
-	my $ac_uid = getCurrentStatic('anonymous_coward_uid');
-	$self->sqlDo("INSERT INTO accesslog_artcom (uid, ts, c)"
-		. " SELECT uid, FROM_UNIXTIME(FLOOR(AVG(UNIX_TIMESTAMP(ts)))) AS ts, COUNT(*) AS c"
-		. " FROM accesslog"
-		. " WHERE id BETWEEN $lastmaxid AND $newmaxid"
-			. " AND (op='article' OR op='comments')"
-		. " AND uid != $ac_uid AND uid <= $youngest_uid"
-		. " GROUP BY uid");
-}
-
-sub fetchEligibleModerators_accesslog_deleteold {
-	my($self) = @_; 
-	my $constants = getCurrentStatic();
-	my $hoursback = $constants->{accesslog_hoursback} || 60;
-	$self->sqlDelete("accesslog_artcom",
-		"ts < DATE_SUB(NOW(), INTERVAL $hoursback HOUR)");
-}
-
-sub fetchEligibleModerators_accesslog_read {
-	my($self) = @_; 
-	my $constants = getCurrentStatic();
-	my $hitcount = defined($constants->{m1_eligible_hitcount})
-		? $constants->{m1_eligible_hitcount} : 3;
-	return $self->sqlSelectAllHashref(
-		"uid",
-		"uid, SUM(c) AS c",
-		"accesslog_artcom",
-		"",
-		"GROUP BY uid HAVING c >= $hitcount");
-}
-
-# This is a method for the main slashdb, which may or may not be
-# the same as the logslavedb.
-
-sub fetchEligibleModerators_users {
-	my($self, $count_hr) = @_;
-	my $constants = getCurrentStatic();
-	my $youngest_uid = $self->getYoungestEligibleModerator();
-	my $minkarma = $constants->{mod_elig_minkarma} || 0;
-	
-	my @uids =
-		sort { $a <=> $b } # don't know if this helps MySQL but it can't hurt... much
-		grep { $_ <= $youngest_uid }
-		keys %$count_hr;
-	my @uids_start = @uids;
-	
-	# What is a good splice_count?  Well I was seeing entries show
-	# up in the *.slow log for a size of 5000, so smaller is good.
-	my $splice_count = 2000;
-	while (@uids) {
-		my @uid_chunk = splice @uids, 0, $splice_count;
-		my $uid_list = join(",", @uid_chunk);
-		my $uids_disallowed = $self->sqlSelectColArrayref(
-			"users_info.uid AS uid",
-			"users_info, users_prefs",
-			"(karma < $minkarma OR willing != 1)
-			 AND users_info.uid = users_prefs.uid
-			 AND users_info.uid IN ($uid_list)"
-		);
-		for my $uid (@$uids_disallowed) {
-			delete $count_hr->{$uid};
-		}
-		# If there is more to do, sleep for a moment so we don't
-		# hit the DB too hard.
-		sleep 1 if @uids;
-	}
-
-	my $return_ar = [
-		map { [ $count_hr->{$_}{uid}, $count_hr->{$_}{c} ] }
-		sort { $count_hr->{$a}{c} <=> $count_hr->{$b}{c}
-			|| int(rand(3))-1 }
-		grep { defined $count_hr->{$_} }
-		@uids_start
-	];
-	return $return_ar;
-}
-
-########################################################
-# For process_moderatord.pl
-# Quick overview:  This method takes a list of uids who are eligible
-# to be moderators and returns that same list, with the "worst"
-# users made statistically less likely to be on it, and the "best"
-# users more likely to remain on the list and appear more than once.
-# Longer explanation:
-# This method takes a list of uids who are eligible to be moderators
-# (i.e., eligible to receive tokens which may end up giving them mod
-# points).  It also takes several numeric values, positive numbers
-# that are almost certainly slightly greater than 1 (e.g. 1.3 or so).
-# For each uid, several values are calculated:  the total number of
-# times the user has been M2'd "fair," the ratio of fair-to-unfair M2s,
-# and the ratio of spent-to-stirred modpoints.  Multiple lists of
-# the uids are made, from "worst" to "best," the "worst" user in each
-# case having the probability of being eligible for tokens (remaining
-# on the list) reduced and the "best" with that probability increased
-# (appearing two or more times on the list).
-# The list of which factors to use and the numeric values of those
-# factors is in $wtf_hr ("what to factor");  its currently-defined
-# keys are factor_ratio, factor_total and factor_stirred.
-sub factorEligibleModerators {
-	my($self, $orig_uids, $wtf, $info_hr) = @_;
-	return $orig_uids if !$orig_uids || !@$orig_uids || scalar(@$orig_uids) < 10;
-	
-	$wtf->{upfairratio} ||= 0;      $wtf->{upfairratio} = 0         if $wtf->{upfairratio} == 1;
-	$wtf->{downfairratio} ||= 0;    $wtf->{downfairratio} = 0       if $wtf->{downfairratio} == 1;
-	$wtf->{fairtotal} ||= 0;        $wtf->{fairtotal} = 0           if $wtf->{fairtotal} == 1;
-	$wtf->{stirratio} ||= 0;        $wtf->{stirratio} = 0           if $wtf->{stirratio} == 1;
-	
-	return $orig_uids if !$wtf->{fairratio} || !$wtf->{fairtotal} || !$wtf->{stirratio};
-	
-	my $start_time = Time::HiRes::time;
-	
-	my @return_uids = ( );
-	
-	my $uids_in = join(",", @$orig_uids);
-	my $u_hr = $self->sqlSelectAllHashref(
-		"uid",
-		"uid, up_fair, down_fair, up_unfair, down_unfair, totalmods, stirred",
-		"users_info",
-		"uid IN ($uids_in)",
-	);
-	
-	# Assign ratio values that will be used in the sorts in a moment.
-	# We precalculate these because they're used in several places.
-	# Note that we only calculate the *ratio* if there are a decent
-	# number of votes, otherwise we leave it undef.
-	for my $uid (keys %$u_hr) {
-		# Upmod fairness ratio.
-		my $ratio = undef;
-		my $denom = $u_hr->{$uid}{up_fair} + $u_hr->{$uid}{up_unfair};
-		if ($denom >= 5) {
-			$ratio = $u_hr->{$uid}{up_fair} / $denom;
-		}
-		$u_hr->{$uid}{upfairratio} = $ratio;
-		# Downmod fairness ratio.
-		$ratio = undef;
-		$denom = $u_hr->{$uid}{down_fair} + $u_hr->{$uid}{down_unfair};
-		if ($denom >= 5) {
-			$ratio = $u_hr->{$uid}{down_fair} / $denom;
-		}
-		$u_hr->{$uid}{downfairratio} = $ratio;
-		# Spent-to-stirred ratio.
-		$ratio = undef;
-		$denom = $u_hr->{$uid}{totalmods} + $u_hr->{$uid}{stirred};
-		if ($denom >= 10) {
-			$ratio = $u_hr->{$uid}{totalmods} / $denom;
-		}               
-		$u_hr->{$uid}{stirredratio} = $ratio;
-	}
-	
-	# Get some stats into the $u_hr hashref that will make some
-	# code later on easier.  Sum the total number of fair votes,
-	# so up_fair+down_fair = total_fair.  And sum the fair
-	# ratios too, to give a very general idea of total fairness.
-	for my $uid (%$u_hr) {
-		$u_hr->{$uid}{total_fair} =
-			  ($u_hr->{$uid}{up_fair} || 0)
-			+ ($u_hr->{$uid}{down_fair} || 0);
-		$u_hr->{$uid}{totalfairratio} = $u_hr->{$uid}{upfairratio}
-			if defined($u_hr->{$uid}{upfairratio});
-		if (defined($u_hr->{$uid}{downfairratio})) {
-			$u_hr->{$uid}{totalfairratio} =
-				($u_hr->{$uid}{totalfairratio} || 0)
-				+ $u_hr->{$uid}{downfairratio};
-		}
-	}
-
-	if ($wtf->{fairtotal}) {
-		# Assign a token likeliness factor based on the absolute
-		# number of "fair" M2s assigned to each user's moderations.
-		# Sort by total m2fair first (that's the point of this
-		# code).  If there's a tie in that, the secondary sort is
-		# by ratio, and tertiary is random.
-		my @new_uids = sort {
-				$u_hr->{$a}{total_fair} <=> $u_hr->{$b}{total_fair}
-				||
-				( defined($u_hr->{$a}{totalfairratio})
-					&& defined($u_hr->{$b}{totalfairratio})
-				  ? $u_hr->{$a}{totalfairratio} <=> $u_hr->{$b}{totalfairratio}
-				  : 0 )
-				||
-				int(rand(1)*2)*2-1
-			} @$orig_uids;
-		# Assign the factors in the hashref according to this
-		# sort order.  Those that sort first get the lowest value,
-		# the approximate middle gets 1, the last get highest.
-		_set_factor($u_hr, $wtf->{fairtotal}, 'factor_m2total',
-			\@new_uids);
-	}
-
-		# Assign a token likeliness factor based on the ratio of
-		# "fair" to "unfair" M2s assigned to each user's
-		# moderations.  In order not to be "prejudiced" against
-		# users with no M2 history, those users get no change in
-		# their factor (i.e. 1) by simply being left out of the
-		# list.  Sort by ratio first (that's the point of this
-		# code);  if there's a tie in ratio, the secondary sort
-		# order is total m2fair, and tertiary is random.
-		# Do this separately by first up fairness ratio, then
-		# down fairness ratio.
-
-	if ($wtf->{upfairratio}) {
-		my @new_uids = sort {
-				$u_hr->{$a}{upfairratio} <=> $u_hr->{$b}{upfairratio}
-				||
-				$u_hr->{$a}{total_fair} <=> $u_hr->{$b}{total_fair}
-				||
-				int(rand(1)*2)*2-1
-			} grep { defined($u_hr->{$_}{upfairratio}) }
-			@$orig_uids;
-		# Assign the factors in the hashref according to this
-		# sort order.  Those that sort first get the lowest value,
-		# the approximate middle gets 1, the last get highest.
-		_set_factor($u_hr, $wtf->{upfairratio}, 'factor_upfairratio',
-			\@new_uids);
-	}       
-		
-	if ($wtf->{downfairratio}) {
-		my @new_uids = sort {
-				$u_hr->{$a}{downfairratio} <=> $u_hr->{$b}{downfairratio}
-				||
-				$u_hr->{$a}{total_fair} <=> $u_hr->{$b}{total_fair}
-				||      
-				int(rand(1)*2)*2-1
-			} grep { defined($u_hr->{$_}{downfairratio}) }
-			@$orig_uids;
-		# Assign the factors in the hashref according to this
-		# sort order.  Those that sort first get the lowest value,
-		# the approximate middle gets 1, the last get highest.
-		_set_factor($u_hr, $wtf->{downfairratio}, 'factor_downfairratio',
-			\@new_uids);
-	}       
-			
-	if ($wtf->{stirratio}) {
-		# Assign a token likeliness factor based on the ratio of
-		# stirred to spent mod points.  In order not to be
-		# "prejudiced" against users with little or no mod history,
-		# those users get no change in their factor (i.e. 1) by
-		# simply being left out of the list.  Sort by ratio first
-		# (that's the point of this code); if there's a tie in
-		# ratio, the secondary sort order is total spent, and
-		# tertiary is random.
-		my @new_uids = sort {
-				$u_hr->{$a}{stirredratio} <=> $u_hr->{$b}{stirredratio}
-				||
-				$u_hr->{$a}{totalmods} <=> $u_hr->{$b}{totalmods}
-				||
-				int(rand(1)*2)*2-1
-			} grep { defined($u_hr->{$_}{stirredratio}) }
-			@$orig_uids;
-		# Assign the factors in the hashref according to this
-		# sort order.  Those that sort first get the lowest value,
-		# the approximate middle gets 1, the last get highest.
-		_set_factor($u_hr, $wtf->{stirratio}, 'factor_stirredratio',
-			\@new_uids);
-	}
-
-	# If the caller wanted to keep stats, prep some stats.
-	if ($info_hr) {
-		$info_hr->{factor_lowest} = 1;
-		$info_hr->{factor_highest} = 1;
-	}
-
-	# Now modify the list of uids.  Each uid in the list has the product
-	# of its factors calculated.  If the product is exactly 1, that uid
-	# is left alone.  If less than 1, there is a chance the uid will be
-	# deleted from the list.  If more than 1, there is a chance it will
-	# be doubled up in the list (or more than doubled for large factors).
-	for my $uid (@$orig_uids) {
-		my $factor = 1;
-		for my $field (qw(
-			factor_m2total
-			factor_upfairratio factor_downfairratio
-			factor_stirredratio
-		)) {
-			$factor *= $u_hr->{$uid}{$field}
-				if defined($u_hr->{$uid}{$field});
-		}
-		# If the caller wanted to keep stats, send some stats.
-		$info_hr->{factor_lowest} = $factor
-			if $info_hr && $info_hr->{factor_lowest}
-				&& $factor < $info_hr->{factor_lowest};
-		$info_hr->{factor_highest} = $factor
-			if $info_hr && $info_hr->{factor_highest}
-				&& $factor > $info_hr->{factor_highest};
-		# If the factor is, say, 1.3, then the count of this uid is
-		# at least 1, and there is a 0.3 chance that it goes to 2.
-		my $count = roundrand($factor);
-		push @return_uids, ($uid) x $count;
-	}
-
-	return \@return_uids;
-}
-
-# This specialized utility function takes a list of uids and assigns
-# values into the hashrefs that are their values in %$u_hr.  The
-# @$uidlist determines the order that the values will be assigned.
-# The first uid gets the value 1/$factor (and since $factor should
-# be >1, this value will be <1).  The middle uid in @$uidlist will
-# get the value approximately 1, and the last uid will get the value
-# $factor.  After these assignments are made, any uid keys in %$u_hr
-# *not* in @$uidlist will be given the value 1.  The 2nd-level hash
-# key that these values are assigned to is $u_hr->{$uid}{$field}.
-sub _set_factor {
-	my($u_hr, $factor, $field, $uidlist) = @_;
-	my $halfway = int($#$uidlist/2);
-	return if $halfway <= 1;
-
-	if ($factor != 1) {
-		for my $i (0 .. $halfway) {
-	
-			# We'll use this first as a numerator, then as 
-			# a denominator.
-			my $between_1_and_factor = 1 + ($factor-1)*($i/$halfway);
-		
-			# Set the lower uid, which ranges from 1/$factor to
-			# $factor/$factor.
-			my $uid = $uidlist->[$i];
-			$u_hr->{$uid}{$field} = $between_1_and_factor/$factor;
-		
-			# Set its counterpart the higher uid, which ranges from
-			# $factor/$factor to $factor/1 (but we build this list
-			# backwards, from $#uidlist down to $halfway-ish, so we
-			# start at $factor/1 and come down to $factor/$factor).
-			my $j = $#$uidlist-$i;
-			$uid = $uidlist->[$j];
-			$u_hr->{$uid}{$field} = $factor/$between_1_and_factor;
-		
-		}       
-	}                       
-		
-	# uids which didn't get a value assigned just get "1".
-	for my $uid (keys %$u_hr) {
-		$u_hr->{$uid}{$field} = 1 if !defined($u_hr->{$uid}{$field});
-	}
-}
-
-########################################################
-# For run_moderatord.pl
-sub updateTokens {
-	my($self, $uid_hr, $options) = @_;
-	my $constants = getCurrentStatic();
-	my $maxtokens = $constants->{maxtokens} || 60;
-	my $splice_count = $options->{splice_count} || 200;
-	my $sleep_time = defined($options->{sleep_time}) ? $options->{sleep_time} : 0.5;
-
-	my %adds = ( map { ($_, 1) } grep /^\d+$/, values %$uid_hr );
-	for my $add (sort { $a <=> $b } keys %adds) {
-		my @uids = sort { $a <=> $b }
-			grep { $uid_hr->{$_} == $add }
-			keys %$uid_hr;
-		# At this points, @uids is the list of uids that need
-		# to have $add tokens added.  Group them into slices
-		# and bulk-add.  This is much more efficient than
-		# calling setUser individually.
-		while (@uids) {
-			my @uid_chunk = splice @uids, 0, $splice_count;
-			my $uids_in = join(",", @uid_chunk);
-			$self->sqlUpdate("users_info",
-				{ -tokens => "LEAST(tokens+$add, $maxtokens)" },
-				"uid IN ($uids_in)");
-			$self->setUser_delete_memcached(\@uid_chunk);
-			# If there is more to do, sleep for a moment so we don't
-			# hit the DB too hard.
-			Time::HiRes::sleep($sleep_time) if @uids && $sleep_time;
-		}
-	}
-}
-
 1;
 

Modified: slashjp/trunk/plugins/TagModeration/mysql_dump.sql
===================================================================
--- slashjp/trunk/plugins/TagModeration/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagModeration/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: $
+# $Id$
 #
 
 REPLACE INTO ajax_ops VALUES (NULL, 'comments_moderate_cid', 'Slash::TagModeration', 'ajaxModerateCid', 'comments-moderation-ajax', 'use');

Modified: slashjp/trunk/plugins/TagModeration/mysql_schema.sql
===================================================================
--- slashjp/trunk/plugins/TagModeration/mysql_schema.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagModeration/mysql_schema.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #
-# $Id: $
+# $Id$
 #
 
 CREATE TABLE IF NOT EXISTS moderatorlog (

Modified: slashjp/trunk/plugins/TagModeration/process_tagmoderation.pl
===================================================================
--- slashjp/trunk/plugins/TagModeration/process_tagmoderation.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/TagModeration/process_tagmoderation.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
+# $Id$
 
 use strict;
 use Slash::Utility;

Modified: slashjp/trunk/plugins/Tags/Clout/Describe.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout/Describe.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/Clout/Describe.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -6,10 +6,8 @@
 use Slash::Utility;
 use base 'Slash::Clout';
 
-use vars qw($VERSION);
+our $VERSION = $Slash::Constants::VERSION;
 
-($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
-
 sub init {
 	my($self) = @_;
 	$self->SUPER::init(@_);
@@ -18,7 +16,7 @@
 	# 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->{cumfrac} = 0.6;
 	my $constants = getCurrentStatic();
 	$self->{debug_uids} = { map { ($_, 1) } split / /,
 		($constants->{tags_updateclouts_debuguids} || '')
@@ -45,8 +43,13 @@
 		$clout = 0;
 	}
 	$clout += 5 if $user_stub->{seclev} > 1;
-	$clout *= $user_stub->{tag_clout};
 
+	my $clout_mult = 1;
+	if (defined($user_stub->{tag_clout})) {
+		$clout_mult = $user_stub->{tag_clout};
+	}
+	$clout *= $clout_mult;
+
 	# An account created within the past 3 days has low clout.
 	# Once an account reaches 30 days old, it gets full clout.
 	my $created_at_ut;
@@ -82,15 +85,16 @@
 			UNIX_TIMESTAMP(newtag.inactivated)-UNIX_TIMESTAMP(newtag.created_at))
 			AS duration,
 		 newtag.uid AS newtag_uid,
-		 users_info.tag_clout AS clout,
-		 UNIX_TIMESTAMP(users_info.created_at) AS created_at_ut,
-		 karma, tokens,
+		 seclev,
+		 users_info.tag_clout,
+		 karma, tokens, UNIX_TIMESTAMP(users_info.created_at) AS created_at_ut,
 		 sourcetag.tagnameid,
 		 sourcetag.globjid,
 		 gtid",
 		"tags AS sourcetag,
 		 tagname_params AS tagparam,
-		 globjs, tags_peerclout AS sourcetpc, users_info,
+		 globjs, tags_peerclout AS sourcetpc,
+		 users, users_info,
 		 tags AS newtag LEFT JOIN tags_peerclout AS newtpc USING (uid)",
 		"sourcetag.inactivated IS NULL
 		 AND sourcetag.globjid=globjs.globjid
@@ -102,6 +106,7 @@
 			AND tagparam.name='descriptive'
 		 AND sourcetag.tagid != newtag.tagid
 		 AND newtag.created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)
+		 AND newtag.uid=users.uid
 		 AND newtag.uid=users_info.uid
 		 AND newtpc.uid IS NULL
 		 AND sourcetpc.gen=$g",
@@ -114,34 +119,48 @@
 	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 $start_time = Time::HiRes::time;
 		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});
+		my($tag_clout, $created_at, $karma, $tokens) =
+			($match0->{tag_clout}, $match0->{created_at_ut}, $match0->{karma}, $match0->{tokens});
 		if ($self->{debug_uids}{$newtag_uid}) {
-			print STDERR ref($self) . sprintf(" starting uid=%d\n", $newtag_uid);
+			print STDERR sprintf("%s tags_updateclouts %s process_nextgen starting uid=%d\n",
+				scalar(gmtime), ref($self), $newtag_uid);
 			++$self->{debug};
 		}
 		my $uid_mults = $self->get_mults(\@match);
-		my $weight = $self->get_total_weight($tags_peerclout, $uid_mults, $clout, $created_at, $karma, $tokens);
+
+		my $peer_weight = $self->get_total_weight($tags_peerclout, $uid_mults, $tag_clout, $created_at, $karma, $tokens);
+
+		my $base_weight = $self->getUserClout($match0);
+
+		my $total_weight = $peer_weight + $base_weight;
+
 		push @$insert_ar, {
 			uid =>		$newtag_uid,
-			clout =>	$weight,
+			clout =>	$total_weight,
 		};
+		my $elapsed = Time::HiRes::time - $start_time;
+
 		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";
+			print STDERR sprintf("%s tags_updateclouts %s process_nextgen uid=%d peer_weight=%.6f base_=%.6f total_weight=%.6f in %.6f secs, mults: %s\n",
+				scalar(gmtime), ref($self), $newtag_uid,
+				$peer_weight, $base_weight, $total_weight,
+				$elapsed, $umd);
 		}
 		++$i;
-		if ($i % 100 == 0) {
-			print STDERR ref($self) . " process_nextgen processed $i (uid $newtag_uid, matched " . scalar(@match) . ")\n";
+		if ($i % 100 == 0 || $self->{debug}) {
+			print STDERR sprintf("%s tags_updateclouts %s process_nextgen processed %d uid=%d matched=%d in %.6f secs\n",
+				scalar(gmtime), ref($self), $i, $newtag_uid, scalar(@match), $elapsed);
 		}
 		if ($self->{debug_uids}{$newtag_uid}) {
-			print STDERR ref($self) . sprintf(" done uid=%d\n", $newtag_uid);
+			print STDERR sprintf("%s tags_updateclouts %s process_nextgen done uid=%d\n",
+				scalar(gmtime), ref($self), $newtag_uid);
 			--$self->{debug};
 		}
 		Time::HiRes::sleep(0.01);
@@ -237,7 +256,11 @@
 		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";
+			print STDERR sprintf("%s tags_updateclouts %s get_total_weight uid=%d (%d) count=%d pushed %.6f\n",
+				scalar(gmtime), ref($self),
+				$uid, $tags_peerclout->{$uid},
+				scalar(@{$uid_mults->{$uid}}),
+				$total_mults[-1]);
 		}       
 	}       
 			
@@ -246,7 +269,8 @@
 	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";
+		print STDERR sprintf("%s tags_updateclouts %s get_total_weight initial total=%d\n",
+			scalar(gmtime), ref($self), $total);
 	}               
 			
 	# If this user was created recently, less weight for them.
@@ -279,6 +303,10 @@
 	
 	# If the user has low clout, less weight for them.
 	$total *= $clout;
+	if ($self->{debug}) {   
+		print STDERR sprintf("%s tags_updateclouts %s get_total_weight final total=%d\n",
+			scalar(gmtime), ref($self), $total);
+	}
 	
 	# If the result is _very_ low, just count it as 0 (this may allow
 	# optimizations later).
@@ -311,8 +339,8 @@
 	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;
-		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));
+		print STDERR sprintf("%s tags_updateclouts %s balance_weight_vectors pos=%.5g neg=%.5g from '%s' to '%s'\n",
+			scalar(gmtime), ref($self), $w_pos_mag, $w_neg_mag, join(' ', @w2), join(' ', @r2));
 	}
 	return @ret;
 }
@@ -327,11 +355,12 @@
 		$cur_magnitude *= $self->{cumfrac};
 		$weight += $cur_magnitude * $w;
 	}
-	$weight = 0 if $weight < 0;
+	my $weight_floored = $weight < 0 ? 0 : $weight;
 	if ($self->{debug}) {
-		print STDERR ref($self) . " sum_weight_vectors weight='$weight' w='@w'\n";
+		print STDERR sprintf("%s tags_updateclouts %s sum_weight_vectors weight=%.6f wf=%.6f w: '%s'\n",
+			scalar(gmtime), ref($self), $weight, $weight_floored, join(' ', @w));
 	}
-	return $weight;
+	return $weight_floored;
 }
 
 sub copy_peerclout_sql {

Modified: slashjp/trunk/plugins/Tags/Clout/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Tags/Clout/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/Clout/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'      => 'Slash::Clout',
-    'VERSION_FROM' => '../Clout.pm', # finds $VERSION
     'PM'        =>
         {
                 'Describe.pm' => '$(INST_LIBDIR)/Clout/Describe.pm',

Modified: slashjp/trunk/plugins/Tags/Clout/Moderate.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout/Moderate.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/Clout/Moderate.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -5,10 +5,8 @@
 use Slash::Utility;
 use base 'Slash::Clout';
 
-use vars qw($VERSION);
+our $VERSION = $Slash::Constants::VERSION;
 
-($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
-
 sub init {
 	1;
 }

Modified: slashjp/trunk/plugins/Tags/Clout/Vote.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout/Vote.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/Clout/Vote.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -6,10 +6,8 @@
 use Slash::Utility;
 use base 'Slash::Clout';
 
-use vars qw($VERSION);
+our $VERSION = $Slash::Constants::VERSION;
 
-($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
-
 sub init {
         my($self) = @_;
         $self->SUPER::init(@_);
@@ -18,7 +16,7 @@
         # 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->{cumfrac} = 0.6;
 	my $constants = getCurrentStatic();
 	$self->{debug_uids} = { map { ($_, 1) } split / /,
 		($constants->{tags_updateclouts_debuguids} || '')
@@ -46,7 +44,11 @@
 		$clout = 0;
 	}
 
-	$clout *= $user_stub->{tag_clout};
+	my $clout_mult = 1;
+	if (defined($user_stub->{tag_clout})) {
+		$clout_mult = $user_stub->{tag_clout};
+	}
+	$clout *= $clout_mult;
 
 	my $created_at_ut;
 	if (defined($user_stub->{created_at_ut})) {
@@ -99,6 +101,8 @@
 	sleep 10;
 
 	my $reader = getObject('Slash::DB', { db_type => 'reader' });
+	my $mintagid = $reader->sqlSelect('MIN(tagid)', 'tags',
+		"created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)");
 	my $hr_ar = $reader->sqlSelectAllHashrefArray(
 		"sourcetag.uid AS sourcetag_uid,
 		 UNIX_TIMESTAMP(newtag.created_at)-UNIX_TIMESTAMP(sourcetag.created_at)
@@ -111,19 +115,20 @@
 			AS duration,
 		 newtag.uid AS newtag_uid,
 		 simil,
-		 users_info.tag_clout AS clout,
-		 UNIX_TIMESTAMP(users_info.created_at) AS created_at_ut,
+		 users_info.tag_clout,
 		 IF(firehose_ogaspt.pubtime IS NULL,
 			NULL,
 			UNIX_TIMESTAMP(firehose_ogaspt.pubtime)-UNIX_TIMESTAMP(newtag.created_at))
 			AS timebeforepub,
-		 karma, tokens,
+		 seclev,
+		 karma, tokens, UNIX_TIMESTAMP(users_info.created_at) AS created_at_ut,
 		 sourcetag.tagnameid AS sourcetag_tagnameid,
 		 newtag.tagnameid AS newtag_tagnameid,
 		 sourcetag.globjid,
 		 gtid",
 		"tags AS sourcetag LEFT JOIN firehose_ogaspt USING (globjid),
-		 tags_peerclout AS sourcetpc, users_info,
+		 tags_peerclout AS sourcetpc,
+		 users, users_info,
 		 tagnames_similar, globjs,
 		 tags AS newtag LEFT JOIN tags_peerclout AS newtpc USING (uid)",
 		"sourcetag.inactivated IS NULL
@@ -134,8 +139,10 @@
 			 AND sourcetag.tagnameid=tagnames_similar.src_tnid
 			 AND tagnames_similar.dest_tnid=newtag.tagnameid
 		 AND simil != 0
+		 AND sourcetag.tagid >= $mintagid
 		 AND sourcetag.tagid != newtag.tagid
-		 AND newtag.created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)
+		 AND newtag.tagid >= $mintagid
+		 AND newtag.uid=users.uid
 		 AND newtag.uid=users_info.uid
 		 AND newtpc.uid IS NULL
 		 AND sourcetpc.gen=$g
@@ -157,7 +164,7 @@
 	my $insert_ar = [ ];
 	my $i = 0;
 	for my $newtag_uid (@newtag_uid) {
-		++$self->{debug} if $self->{debug_uids}{$newtag_uid};
+		my $start_time = Time::HiRes::time;
 		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) {
@@ -166,40 +173,53 @@
 			$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 ($self->{debug}) {
-			print STDERR ref($self) . sprintf(" starting uid=%d user_nodnixes_mult=%.3f\n",
-				$newtag_uid, $user_nodnixes_mult);
+		if ($self->{debug_uids}{$newtag_uid}) {
+			print STDERR sprintf("%s tags_updateclouts %s process_nextgen starting uid=%d user_nodnixes_count=%d _mult=%.6f\n",
+				scalar(gmtime), ref($self), $newtag_uid, $user_nodnixes_count, $user_nodnixes_mult);
+			++$self->{debug};
 		}
+
+		my $peer_weight = 0;
+		my(@match, $tag_clout, $created_at, $karma, $tokens, $uid_mults);
+		@match = grep { $_->{newtag_uid} == $newtag_uid } @$hr_ar;
+		my $match0 = $match[0];
 		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});
+			($tag_clout, $created_at, $karma, $tokens) =
+				($match0->{tag_clout}, $match0->{created_at_ut}, $match0->{karma}, $match0->{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)
+			$peer_weight = $self->get_total_weight($tags_peerclout, $uid_mults,
+				$tag_clout, $created_at, $karma, $tokens, $newtag_uid)
 				* $user_nodnixes_mult;
 		}
+
+		my $base_weight = $self->getUserClout($match0);
+
+		my $total_weight = $peer_weight + $base_weight;
+
 		push @$insert_ar, {
 			uid =>		$newtag_uid,
-			clout =>	$weight,
+			clout =>	$total_weight,
 		};
+		my $elapsed = Time::HiRes::time - $start_time;
+
 		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,
-				$weight,
-				Dumper($uid_mults));
+			use Data::Dumper; my $umd = Dumper($uid_mults); $umd =~ s/\s+/ /g;
+			print STDERR sprintf("%s tags_updateclouts %s process_nextgen uid=%d peer_weight=%.6f base_=%.6f total_weight=%.6f in %.6f secs, mults: %s\n",
+				scalar(gmtime), ref($self), $newtag_uid,
+                                $peer_weight, $base_weight, $total_weight,
+                                $elapsed, $umd);
 		}
 		++$i;
-		if ($i % 100 == 0) {
-			print STDERR scalar(localtime) . " " . ref($self) . " process_nextgen processed $i (uid $newtag_uid, matched " . scalar(@match) . ")\n";
+		if ($i % 100 == 0 || $self->{debug}) {
+			print STDERR sprintf("%s tags_updateclouts %s process_nextgen processed %d uid=%d matched=%d in %.6f secs\n",
+				scalar(gmtime), ref($self), $i, $newtag_uid, scalar(@match), $elapsed);
 		}
-		--$self->{debug} if $self->{debug_uids}{$newtag_uid};
+		if ($self->{debug_uids}{$newtag_uid}) {
+			print STDERR sprintf("%s tags_updateclouts %s process_nextgen done uid=%d\n",
+				scalar(gmtime), ref($self), $newtag_uid);
+			--$self->{debug};
+		}
 		Time::HiRes::sleep(0.01);
 	}
 
@@ -219,7 +239,7 @@
 	return unless keys %uid_needed;
 	my $reader = getObject('Slash::DB', { db_type => 'reader' });
 	my @uids_needed = sort { $a <=> $b } keys %uid_needed;
-	my $splice_count = 2000;
+	my $splice_count = 20;
 	while (@uids_needed) {
 		my @uid_chunk = splice @uids_needed, 0, $splice_count;
 		my $uid_str = join(",", @uid_chunk);
@@ -235,9 +255,22 @@
 			"tagnameid='$self->{nixid}' AND uid IN ($uid_str)
 			 AND created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)",
 			'GROUP BY uid');
+		if (grep { $self->{debug_uids}{$_} } @uid_chunk) {
+			my $nod_d = Dumper($nod_hr); $nod_d =~ s/\s+/ /g;
+			my $nix_d = Dumper($nix_hr); $nix_d =~ s/\s+/ /g;
+			print STDERR sprintf("%s tags_updateclouts %s count_uid_nodnix splice nod_d=%s nix_d=%s\n",
+				scalar(gmtime), ref($self),
+				$nod_d, $nix_d);
+		}
 		for my $uid (@uid_chunk) {
 			$self->{nodc}{$uid} = $nod_hr->{$uid} || 0;
 			$self->{nixc}{$uid} = $nix_hr->{$uid} || 0;
+			if ($self->{debug_uids}{$uid}) {
+				print STDERR sprintf("%s tags_updateclouts %s count_uid_nodnix uid=%d nod=%s nix=%s nodc=%s nixc=%s\n",
+					scalar(gmtime), ref($self), $uid,
+					$nod_hr->{$uid}, $nix_hr->{$uid},
+					$self->{nodc}{$uid}, $self->{nixc}{$uid});
+			}
 		}
 		sleep 1 if @uids_needed;
 	}
@@ -334,10 +367,15 @@
 		my $sfrac = ($stn == $nodid ? $snix : $snod) / ($snod+$snix+1);
 		my $nfrac = ($ntn == $nodid ? $nnix : $nnod) / ($nnod+$nnix+1);
 		if ($self->{debug}) {
-			print STDERR ref($self) . " get_mult su='$su' nu='$nu' sfrac='$sfrac' nfrac='$nfrac'\n";
+			print STDERR sprintf("%s tags_updateclouts %s get_mult su=%d nu=%d sfrac=%.6f nfrac=%.6f\n",
+				scalar(gmtime), ref($self), $su, $nu, $sfrac, $nfrac);
 		}
 		$mult *= $sfrac * $nfrac;
 	}
+	if ($self->{debug}) {
+		print STDERR sprintf("%s tags_updateclouts %s get_mult returning %.6f\n",
+			scalar(gmtime), ref($self), $mult);
+	}
 
 	return $mult;
 }
@@ -392,17 +430,24 @@
 	# correlations with other users' tags.
 	if ($uid_mults->{'-1'}) {
 		if (@{$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}
+			my $m = $constants->{tags_tagpeerval_postingbonus}
 				* $self->sum_weight_vectors(@balanced);
+			push @total_mults, $m;
 			$any_weight = 1;
+			if ($self->{debug}) {
+				print STDERR sprintf("%s tags_updateclouts %s get_total_weight uid=%d balance_weight_vectors(-1)=%.6f\n",
+					scalar(gmtime), ref($self), $new_uid, $m);
+			}
 		}
 		delete $uid_mults->{'-1'};
 	}
 	
 	# Start by sorting source uids by decreasing weight.
-	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 @nodef = grep { !defined $tags_peerclout->{$_} } keys %$uid_mults; $#nodef = 20 if $#nodef > 20;
+	print STDERR sprintf("%s tags_updateclouts %s get_total_weight for uid=%d nodef: '%s'\n",
+		scalar(gmtime), ref($self), $new_uid, join(' ', @nodef))
+		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.
@@ -412,25 +457,39 @@
 			last;
 		}
 	}
+	if ($self->{debug}) {
+		my $src_count = scalar(@source_uids);
+		my @src_abridged = @source_uids;
+		$#src_abridged = 19 if $#src_abridged >= 19;
+		my $src_min = $uid_mults->{ $src_abridged[-1] };
+		my $src_max = $uid_mults->{ $src_abridged[ 0] };
+		my $abridged_str = join(' ', @src_abridged);
+		print STDERR sprintf("%s tags_updateclouts %s get_total_weight uid=%d any_weight=%d count=%d min=%.6f max=%.6f uids: '%d'\n",
+			scalar(gmtime), ref($self), $new_uid, $any_weight,
+			$src_count, $src_min, $src_max, $abridged_str);
+	}
 	return 0 if !$any_weight;
 
 	# Get the mult for each of those
 	for my $uid (@source_uids) {
-	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);
+		my $m = $tags_peerclout->{$uid} * $self->sum_weight_vectors(@balanced);
+		push @total_mults, $m;
 		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";
+			print STDERR sprintf("%s tags_updateclouts %s get_total_weight uid=%d source_uid=%d (clout %.6f) mult: %.6f for balanced: %s\n",
+				scalar(gmtime), ref($self), $new_uid, $uid, $m,
+				join(' ', map { sprintf("%.6f", $_) } @balanced));
 		}
 	}
 
 	# Then (using the same decreasing-multipliers algorithm) get the
 	# total of all those mults.
-	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 ($self->{debug}) {
+		print STDERR sprintf("%s tags_updateclouts %s get_total_weight uid=%d initial total=%.6f\n",
+			scalar(gmtime), ref($self), $new_uid, $total);
+	}
 	
 	# If this user was created recently, less weight for them.
 	my $daysold = (time - $created_at)/86400;
@@ -462,6 +521,11 @@
 	
 	# If the user has low clout, less weight for them.
 	$total *= $clout;
+
+	if ($self->{debug}) {
+		print STDERR sprintf("%s tags_updateclouts %s get_total_weight uid=%d final total=%.6f\n",
+			scalar(gmtime), ref($self), $new_uid, $total);
+	}
 	
 	# If the result is _very_ low, just count it as 0 (this may allow
 	# optimizations later).
@@ -494,8 +558,10 @@
 	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));
+		print STDERR sprintf("%s tags_updateclouts %s balance_weight_vectors posmag=%0.5g negmag=%0.5g from '%s' to '%s'\n",
+			scalar(gmtime), ref($self), $w_pos_mag, $w_neg_mag,
+			join(' ', map { sprintf("%.6f", $_) } @w2),
+			join(' ', map { sprintf("%.6f", $_) } @r2));
 	}
 	return @ret;
 }
@@ -512,7 +578,8 @@
 	}
 	$weight = 0 if $weight < 0;
 	if ($self->{debug}) {
-		print STDERR ref($self) . " sum_weight_vectors weight='$weight' w='@w'\n";
+		print STDERR sprintf("%s tags_updateclouts %s sum_weight_vectors weight=%.6f w='%s'\n",
+			scalar(gmtime), ref($self), $weight, join(' ', map { sprintf("%.6f", $_) } @w));
 	}
 	return $weight;
 }

Modified: slashjp/trunk/plugins/Tags/Clout.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/Clout.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 package Slash::Clout;
 
@@ -17,14 +16,12 @@
 use base 'Slash::DB::Utility';
 use base 'Slash::DB';
 
-use vars qw($VERSION);
+our $VERSION = $Slash::Constants::VERSION;
 
-($VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
-
 sub init {
 	my($self) = @_;
 
-	$self->{months_back} = 4; # default
+	$self->{months_back} = 2; # default
 	my $slashdb = getCurrentDB();
         my $info = $slashdb->getCloutInfo();
         for my $clid (keys %$info) {
@@ -33,9 +30,9 @@
         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');
+	my $tagsdb = getObject('Slash::Tags');
+	$self->{nodid} = $tagsdb->getTagnameidCreate($constants->{tags_upvote_tagname}   || 'nod');
+	$self->{nixid} = $tagsdb->getTagnameidCreate($constants->{tags_downvote_tagname} || 'nix');
 	1;
 }
 

Modified: slashjp/trunk/plugins/Tags/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Tags/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,7 +3,6 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Tags',
-    'VERSION_FROM' => 'Tags.pm', # finds $VERSION
     'PM'	=>
     	{
 		'Tags.pm' =>   '$(INST_LIBDIR)/Tags.pm',

Modified: slashjp/trunk/plugins/Tags/Tagbox.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Tagbox.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/Tagbox.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Tagbox;
 
@@ -11,13 +10,12 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 use Apache::Cookie;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
 use Data::Dumper;
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: And where would a giant nerd be? THE LIBRARY!
 
@@ -165,7 +163,36 @@
 }
 }
 
+# Cache a list of which gtids map to which tagboxes, so we can quickly
+# return a list of tagboxes that want a "nosy" entry for a given gtid.
+# Input is a hashref with the globj fields (the only one this cares
+# about at the moment is gtid, but that may change in future).  Output
+# is an array of tagbox IDs.
+
 { # closure XXX this won't work with multiple sites, fix
+my $gtid_to_tbids = { };
+sub getTagboxesNosyForGlobj {
+	my($self, $globj_hr) = @_;
+	my $gtid;
+	if (!keys %$gtid_to_tbids) {
+		my $globj_types = $self->getGlobjTypes();
+		for $gtid (grep /^\d+$/, keys %$globj_types) {
+			$gtid_to_tbids->{ $gtid } = [ ];
+		}
+		my $tagboxes = $self->getTagboxes();
+		for my $tb_hr (@$tagboxes) {
+			my @nosy = grep /^\d+$/, split / /, $tb_hr->{nosy_gtids};
+			for $gtid (@nosy) {
+				push @{ $gtid_to_tbids->{$gtid} }, $tb_hr->{tbid};
+			}
+		}
+	}
+	$gtid = $globj_hr->{gtid};
+	return @{ $gtid_to_tbids->{$gtid} };
+}
+}
+
+{ # closure XXX this won't work with multiple sites, fix
 my $userkey_masterregex;
 sub userKeysNeedTagLog {
 	my($self, $keys_ar) = @_;
@@ -220,24 +247,24 @@
 }
 
 sub getMostImportantTagboxAffectedIDs {
-	my($self, $num) = @_;
+	my($self, $num, $min_weightsum) = @_;
 	$num ||= 10;
+	$min_weightsum ||= 1;
 	return $self->sqlSelectAllHashrefArray(
 		'tagboxes.tbid,
 		 affected_id,
-		 MAX(tagid) AS max_tagid,
-		 MAX(tdid)  AS max_tdid,
-		 MAX(tuid)  AS max_tuid,
+		 MAX(tfid) AS max_tfid,
 		 SUM(importance*weight) AS sum_imp_weight',
 		'tagboxes, tagboxlog_feeder',
 		'tagboxes.tbid=tagboxlog_feeder.tbid',
 		"GROUP BY tagboxes.tbid, affected_id
-		 HAVING sum_imp_weight >= 1
+		 HAVING sum_imp_weight >= $min_weightsum
 		 ORDER BY sum_imp_weight DESC LIMIT $num");
 }
 
 sub getTagboxTags {
 	my($self, $tbid, $affected_id, $extra_levels, $options) = @_;
+	warn "no tbid for $self" if !$tbid;
 	$extra_levels ||= 0;
 	my $type = $options->{type} || $self->getTagboxes($tbid, 'affected_type')->{affected_type};
 #print STDERR "getTagboxTags($tbid, $affected_id, $extra_levels), type=$type\n";
@@ -282,8 +309,6 @@
 	my($self, $tbid, $info_hr) = @_;
 	$info_hr->{-created_at} = 'NOW()';
 	$info_hr->{tbid} = $tbid;
-	die "attempt to create tagboxlog_feeder row with no non-NULL ids: " . Dumper($info_hr)
-		if !( $info_hr->{tagid} || $info_hr->{tdid} || $info_hr->{tuid} );
 	return $self->sqlInsert('tagboxlog_feeder', $info_hr);
 }
 
@@ -294,9 +319,9 @@
 		tbid =>		$tbid,
 		affected_id =>	$affected_id,
 		importance =>	9999,
-		tagid =>	0,
-		tdid =>		0,
-		tuid =>		0,
+		tagid =>	undef,
+		tdid =>		undef,
+		tuid =>		undef,
 	};
 	return $self->sqlInsert('tagboxlog_feeder', $info_hr);
 }
@@ -310,13 +335,7 @@
 	my($self, $affected_hr) = @_;
 
 	my $delete_clause = "tbid=$affected_hr->{tbid} AND affected_id=$affected_hr->{affected_id}";
-	my @id_clauses = ( );
-	push @id_clauses, "tagid <= $affected_hr->{max_tagid}" if $affected_hr->{max_tagid};
-	push @id_clauses, "tdid  <= $affected_hr->{max_tdid}"  if $affected_hr->{max_tdid};
-	push @id_clauses, "tuid  <= $affected_hr->{max_tuid}"  if $affected_hr->{max_tuid};
-	@id_clauses = ("tagid=0 AND tdid=0 AND tuid=0") if !@id_clauses;
-	my $id_clause = join(' OR ', @id_clauses);
-	$delete_clause .= " AND ($id_clause)";
+	$delete_clause .= " AND tfid <= $affected_hr->{max_tfid}";
 
 	$self->sqlDelete('tagboxlog_feeder', $delete_clause);
 	$self->sqlUpdate('tagboxes',

Modified: slashjp/trunk/plugins/Tags/Tags.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Tags.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/Tags.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Tags;
 
@@ -13,11 +12,10 @@
 use Slash::DB::Utility;
 #use Slash::Clout;
 use Apache::Cookie;
-use vars qw($VERSION);
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # FRY: And where would a giant nerd be? THE LIBRARY!
 
@@ -243,7 +241,7 @@
 
 sub deactivateTag {
 	my($self, $hr, $options) = @_;
-	my $tag = $self->_setuptag($hr, { tagname_not_required => 1 });
+	my $tag = $self->_setuptag($hr, { tagname_not_required => !$options->{tagname_required} });
 	return 0 if !$tag;
 	my $prior_clause = '';
 	$prior_clause = " AND tagid < $options->{tagid_prior_to}" if $options->{tagid_prior_to};
@@ -551,6 +549,9 @@
 	if ($options->{tagnameid}) {
 		my $tagnameid_q = $self->sqlQuote($options->{tagnameid});
 		$tagnameid_where = " AND tagnameid = $tagnameid_q";
+	} elsif ($options->{limit_to_tagnames}) {
+		my $in_clause = join ',', grep { $_ } map { $self->getTagnameidFromNameIfExists($_) } @{ $options->{limit_to_tagnames} };
+		$tagnameid_where = " AND tagnameid IN ($in_clause)";
 	}
 
 	my $ar = $self->sqlSelectAllHashrefArray(
@@ -1108,16 +1109,24 @@
 	# Create any tag specified but only if it does not already exist.
 	my @create_tagnames	= grep { !$old_tagnames{$_} } sort keys %new_tagnames;
 
-	# Deactivate any tags previously specified that were deleted from
-	# the tagbox.
-	my @deactivate_tagnames	= grep { !$new_tagnames{$_} } sort keys %old_tagnames;
+	my @deactivate_tagnames;
+	if ( ! $options->{deactivate_by_operator} ) {
+		# Deactivate any tags previously specified that were deleted from the tagbox.
+		@deactivate_tagnames	= grep { !$new_tagnames{$_} } sort keys %old_tagnames;
+	} else {
+		# Deactivate any tags that are supplied as "-tag"
+		@deactivate_tagnames =
+			map { $1 if /^-(.+)/ }
+			split /[\s,]+/,
+			lc $tag_string;
+	}
 	for my $tagname (@deactivate_tagnames) {
 		$tags->deactivateTag({
 			uid =>		$uid,
 			name =>		$tagname,
 			table =>	$table,
 			id =>		$id
-		});
+		}, { tagname_required => $options->{tagname_required} });
 	}
 
 	my @created_tagnames = ( );
@@ -1135,7 +1144,7 @@
 	}
 
 	my $now_tags_ar = $tags->getTagsByNameAndIdArrayref($table, $id,
-		{ uid => $uid }); # don't list private tags
+		{ uid => $uid, include_private => $options->{include_private} }); # don't list private tags unless forced
 	my $newtagspreloadtext = join ' ', sort map { $_->{tagname} } @$now_tags_ar;
 	return $newtagspreloadtext;
 }
@@ -1299,6 +1308,119 @@
 	}
 }
 
+sub getUserNodNixForGlobj {
+	my($self, $globjid, $uid) = @_;
+	my $current_vote_tags_array = $self->getTagsByGlobjid($globjid, {
+		uid => $uid,
+		include_private => 1,
+		limit_to_tagnames => ['nod', 'nix']
+	});
+	return join ' ', sort map { $_->{tagname} } @$current_vote_tags_array;
+}
+
+sub ajaxSetGetCombinedTags {
+	my($slashdb, $constants, $user, $form) = @_;
+
+	my $type = $form->{type} || 'firehose';
+
+	my ($base_item, $base_writer);
+	my $globjid;
+	if ( $type eq 'firehose' ) {
+		$base_writer = getObject('Slash::FireHose');
+		$base_item = $base_writer->getFireHose($form->{id});
+		$globjid = $base_item->{globjid} if $base_item;
+	}
+	# XXX TO DO: handle other types here, setting $base_item appropriately
+
+	my $tags_reader = getObject('Slash::Tags', { db_type => 'reader' });
+	if (!$globjid || $globjid !~ /^\d+$/ || !$tags_reader) {
+		return getData('error', {}, 'tags');
+	}
+	my($table, $item_id) = $tags_reader->getGlobjTarget($globjid);
+
+	my $uid = $user && $user->{uid} || 0;
+
+	# if we have to execute commands, do them _before_ we fetch any tag lists
+	my $user_tags = '';
+	if ( $form->{tags} ) {
+		my $tags_writer = getObject('Slash::Tags');
+		$user_tags = $tags_writer->setTagsForGlobj($item_id, $table, '', {
+			deactivate_by_operator => 1,
+			tagname_required => 1,
+			include_private => 1
+		});
+		if ( $user->{is_admin} && $type eq 'firehose' ) {
+			my $added_tags =
+				join ' ',
+				grep { /^[^-]/ }
+				split /\s+/,
+				lc $form->{tags};
+
+			$base_writer->setSectionTopicsFromTagstring($form->{id}, $added_tags);
+			$base_item = $base_writer->getFireHose($form->{id});
+		};
+	} elsif ( ! $form->{global_tags_only} ) {
+		my $current_tags_array = $tags_reader->getTagsByNameAndIdArrayref($table, $item_id, { uid => $uid, include_private => 1 });
+		$user_tags = join ' ', sort map { $_->{tagname} } @$current_tags_array;
+	}
+
+	my $datatype_tag = $base_item ? $base_item->{type} : '';
+	my $top_tags = $base_item ? $base_item->{toptags} : '';
+
+	my $section_tag = '';
+	my $s = $base_item->{primaryskid};
+	if ( $s ) {
+		if ( $s != $constants->{mainpage_skid} ) {
+			my $skin = $base_writer->getSkin($s);
+			$section_tag = $skin->{name};
+		} else {
+			$section_tag = 'mainpage';
+		}
+	}
+
+	my $topic_tags = '';
+	my $t = $base_item->{tid};
+	if ( $t ) {
+		my $topic = $base_writer->getTopic($t);
+		$topic_tags = $topic->{keyword};
+	}
+
+	# XXX how to get the system tags?
+	my $system_tags = $datatype_tag . ' ' . $section_tag . ' ' . $topic_tags;
+
+	my $response = '<system>' . $system_tags . '<top>'. $top_tags;
+	$response .= '<user>' . $user_tags unless $form->{global_tags_only};
+
+	return $response;
+}
+
+sub setGetCombinedTags {
+	my($self, $id, $type, $user, $commands) = @_;
+
+	my $slashdb = getCurrentDB();
+	my $constants = getCurrentStatic();
+
+	my $options = {
+		'id'	=> $id,
+		'type'	=> $type,
+	};
+	$options->{global_tags_only} = 1 unless $user;
+	$options->{tags} = $commands if $commands;
+
+	my @tuples = split /<([\w:]*)>/, ajaxSetGetCombinedTags($slashdb, $constants, $user, $options);
+	shift @tuples; # bogus empty first elem when capturing separators
+
+	my $response = {};
+	while ( @tuples ) {
+		my $key = shift @tuples;
+		$response->{$key} = shift @tuples || '' if $key;
+#print STDERR "key => $key; value => $response->{$key}\n";
+	}
+#print STDERR "---------\n";
+
+	return $response;
+}
+
 {
 my %_adcmd_prefix = ( );
 sub normalizeAndOppositeAdminCommands {
@@ -1417,6 +1539,9 @@
 sub ajaxListTagnames {
 	my($slashdb, $constants, $user, $form) = @_;
 	my $tags_reader = getObject('Slash::Tags', { db_type => 'reader' });
+
+	$form->{prefix} ||= $form->{'q'} || '';
+
 	my $prefix = '';
 	$prefix = lc($1) if $form->{prefix} =~ /([A-Za-z0-9]{1,20})/;
 	my $len = length($prefix);
@@ -1444,7 +1569,7 @@
 
 	my $ret_str = '';
 	for my $tagname (sort { $tnhr->{$b} <=> $tnhr->{$a} } keys %$tnhr) {
-		$ret_str .= sprintf("%s%s\t%d\n", $notize, $tagname, $tnhr->{$tagname});
+		$ret_str .= sprintf("%s%s\n", $notize, $tagname);
 	}
 #use Data::Dumper; print STDERR scalar(localtime) . " ajaxListTagnames uid=$user->{uid} prefix='$prefix' tnhr: " . Dumper($tnhr);
 	return $ret_str;
@@ -1743,7 +1868,11 @@
 
 	# This seems like a horrendous query, but I _think_ it will run
 	# in acceptable time, even under fairly heavy load.
+	# (But see below, in listTagnamesRecent, for a possible
+	# optimization.)
+
 	# Round off time to the last minute.
+
 	my $now_ut = $self->getTime({ unix_format => 1 });
 	my $next_minute_ut = int($now_ut/60+1)*60;
 	my $next_minute_q = $self->sqlQuote( time2str( '%Y-%m-%d %H:%M:00', $next_minute_ut, 'GMT') );
@@ -1847,21 +1976,49 @@
 	my $seconds =         $options->{seconds}         || (3600*6);
 	my $include_private = $options->{include_private} || 0;
 	my $private_clause = $include_private ? '' : " AND private='no'";
-	my $recent_ar = $self->sqlSelectColArrayref(
-		'DISTINCT tagnames.tagname',
-		"users_info,
-		 tags LEFT JOIN tag_params
-		 	ON (tags.tagid=tag_params.tagid AND tag_params.name='tag_clout'),
-		 tagnames LEFT JOIN tagname_params
-			ON (tagnames.tagnameid=tagname_params.tagnameid AND tagname_params.name='tag_clout')",
-		"tagnames.tagnameid=tags.tagnameid
-		 AND inactivated IS NULL $private_clause
+
+	# Previous versions of this method grabbed tagname string along
+	# with tagnameid, and did a LEFT JOIN on tagname_params to exclude
+	# tagname_params with tagname_clout=0.  Its performance was
+	# acceptable up to about 50K tags, on the order of 1 tag insert/sec
+	# at the time interval used.  But performance fell off a cliff
+	# somewhere before 300K tags.  So I'm optimizing this to do an
+	# initial select of more-raw data from the DB and then do a
+	# second and third select to grab the full data set needed.
+	# Early testing suggests this runs at least 10x faster.
+	# - Jamie 2008-08-28
+
+	my $tagnameids_ar = $self->sqlSelectColArrayref(
+		'DISTINCT tags.tagnameid',
+		"tags LEFT JOIN tag_params
+			ON (tags.tagid=tag_params.tagid AND tag_params.name='tag_clout')",
+		"inactivated IS NULL
+		 $private_clause
 		 AND tags.created_at >= DATE_SUB(NOW(), INTERVAL $seconds SECOND)
 		 AND (tag_params.value IS NULL OR tag_params.value > 0)
-		 AND (tagname_params.value IS NULL OR tagname_params.value > 0)
-		 AND tags.uid=users_info.uid AND users_info.tag_clout > 0",
-		'ORDER BY tagnames.tagname'
+		 AND tags.uid=users_info.uid AND users_info.tag_clout > 0"
 	);
+
+	# Eliminate any tagnameid's with a reduced tagname_clout.
+	# This is probably smaller than the list of distinct tagnames
+	# used in the past n hours, so it's probably faster (and should
+	# never be noticeably slower) to grab them all and do a difference
+	# on the two lists in perl instead of SQL.
+	# XXX Not sure whether it's the best thing here to exclude all
+	# tagnames with even slightly-reduced clout, but I think so.
+	# Those tagnames probably aren't ones that would be valuable to
+	# see in a list of recent tags.
+	my $tagnameids_noclout_ar = $self->sqlSelectColArrayref(
+		'tagnameid',
+		'tagname_params',
+		"name='tag_clout' AND value+0 < 1");
+	my %noclout = ( map { $_, 1 } @$tagnameids_noclout_ar );
+	$tagnameids_ar = grep { ! $noclout{$_} } @$tagnameids_ar;
+
+	# Get the tagnames for those id's.
+	my $tagnameids_str = join(',', sort { $a <=> $b } @$tagnameids_ar);
+	my $recent_ar = $self->sqlSelectColArrayref('tagname', 'tagnames',
+		"tagnameid IN ($tagnameids_str)");
 	@$recent_ar = sort tagnameorder @$recent_ar;
 	return $recent_ar;
 }
@@ -1974,8 +2131,8 @@
 }
 
 sub getPrivateTagnames {
-	my ($self) = @_;
-	my $user = getCurrentUser;
+	my($self) = @_;
+	my $user = getCurrentUser();
 	my $constants = getCurrentStatic();
 
 	my @private_tags = ();
@@ -2143,12 +2300,13 @@
 	if ($firehose) {
 		$fh_min_score = $firehose->getMinPopularityForColorLevel($constants->{tags_rectn_mincare} || 5);
 	}
+	my $target_hr = $self->getGlobjTargets([ map { $_->{globjid} } @$tags_ar ]);
 	for my $tag_hr (@$tags_ar) {
 		my $tc = $tag_hr->{total_clout};
 		next unless $tc;
 		my $tagnameid = $tag_hr->{tagnameid};
 		my $globjid = $tag_hr->{globjid};
-		my($type) = $self->getGlobjTarget($globjid);
+		my $type = $target_hr->{$globjid}[0];
 		if ($firehose) {
 			my $fhid = $firehose->getFireHoseIdFromGlobjid($globjid);
 			my $item = $firehose->getFireHose($fhid) if $fhid;

Modified: slashjp/trunk/plugins/Tags/mysql_dump.sql
===================================================================
--- slashjp/trunk/plugins/Tags/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -10,6 +10,9 @@
 INSERT INTO vars (name, value, description) VALUES ('tags_admin_autoaddstorytopics', '1', 'Auto-add tags for story topic keywords?');
 INSERT INTO vars (name, value, description) VALUES ('tags_cache_expire', '180', 'Local data cache expiration for tags');
 INSERT INTO vars (name, value, description) VALUES ('tags_list_mintc', '4', 'Minimum value of total_clout for tagged items shown at /tags/foo');
+INSERT INTO vars (name, value, description) VALUES ('tags_overnight_minweightsum', '0.1', 'Minimum tagbox weight sum for overnight processing. To disable overnight difference, set to 1');
+INSERT INTO vars (name, value, description) VALUES ('tags_overnight_starthour', '7', 'GMT hour at which overnight processing begins');
+INSERT INTO vars (name, value, description) VALUES ('tags_overnight_stophour', '10', 'GMT hour after which overnight processing ends');
 INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_minc', '4', 'Minimum value of c (count) for tagnames returned by listTagnamesByPrefix');
 INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_minlen', '3', 'Minimum length of a tag prefix to bother looking up suggestions for');
 INSERT INTO vars (name, value, description) VALUES ('tags_prefixlist_mins', '3', 'Minimum value of s (clout sum) for tagnames returned by listTagnamesByPrefix');
@@ -24,6 +27,7 @@
 INSERT INTO vars (name, value, description) VALUES ('tags_stories_examples', '', 'Example tags for stories');
 INSERT INTO vars (name, value, description) VALUES ('tags_stories_lastscanned', '0', 'The last tagid scanned to update stories');
 INSERT INTO vars (name, value, description) VALUES ('tags_stories_top_minscore', '2', 'Minimum score a tag must have to make it into the top tags for a story');
+INSERT INTO vars (name, value, description) VALUES ('tags_feederlog_largerows', '50000', 'Number of rows at which the feederlog is considered "large", slowing additions');
 INSERT INTO vars (name, value, description) VALUES ('tags_udc_daysback', '182', 'Days back to crunch numbers for tags_udc related tables, should be a multiple of 7');
 INSERT INTO vars (name, value, description) VALUES ('tags_unknowntype_default_clid', '1', 'For tags of unknown type, which clout id do we pretend they are?');
 INSERT INTO vars (name, value, description) VALUES ('tags_unknowntype_default_mult', '0.3', 'For tags of unknown type, what multiplier do we give to the tagging user clout or type tags_unknowntype_default_clid?');
@@ -36,6 +40,7 @@
 INSERT INTO vars (name, value, description) VALUES ('tags_userfrac_read', '1', 'Fraction (0.0-1.0) of user UIDs which are allowed to read tags, if tags_*_allow* is set that way');
 INSERT INTO vars (name, value, description) VALUES ('tags_userfrac_write', '0.95', 'Fraction (0.0-1.0) of user UIDs which are allowed to tag, if tags_*_allow* is set that way');
 INSERT INTO vars (name, value, description) VALUES ('tags_usershow_cutoff', '200', 'More tags than this, and instead of showing the full taglist /~user/tags will show the list of tagnames');
+INSERT INTO vars (name, value, description) VALUES ('tags_tagbox_lastglobjid', '0', 'Last globjid that the tagbox scanned for possible insertion into feeder log');
 INSERT INTO vars (name, value, description) VALUES ('tags_tagname_regex', '^\!?[a-z][a-z0-9/]{0,63}$', 'Regex that tag names must conform to');
 INSERT INTO vars (name, value, description) VALUES ('tags_updateclouts_debuguids', '', 'UIDs to print debug info on during clout recalculation');
 INSERT INTO vars (name, value, description) VALUES ('tags_upvote_tagname', 'nod', 'Tag for upvote');
@@ -52,6 +57,7 @@
 INSERT INTO ajax_ops VALUES (NULL, 'tags_history', 'Slash::Tags', 'ajaxTagHistory', 'ajax_admin', 'createuse');
 INSERT INTO ajax_ops VALUES (NULL, 'tags_list_tagnames', 'Slash::Tags', 'ajaxListTagnames', 'ajax_tags_read', 'createuse');
 INSERT INTO ajax_ops VALUES (NULL, 'tags_deactivate', 'Slash::Tags', 'ajaxDeactivateTag', 'ajax_tags_write', 'use');
+INSERT INTO ajax_ops VALUES (NULL, 'tags_setget_combined', 'Slash::Tags', 'ajaxSetGetCombinedTags', 'ajax_user_static', 'createuse');
 
 INSERT INTO menus VALUES (NULL, 'tagszg', 'Active', 'active', '[% gSkin.rootdir %]/tags',        1, 1, 1);
 INSERT INTO menus VALUES (NULL, 'tagszg', 'Recent', 'recent', '[% gSkin.rootdir %]/tags/recent', 1, 1, 2);

Modified: slashjp/trunk/plugins/Tags/mysql_schema.sql
===================================================================
--- slashjp/trunk/plugins/Tags/mysql_schema.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/mysql_schema.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,3 @@
-#
-# $Id$
-#
-
 DROP TABLE IF EXISTS tags;
 CREATE TABLE tags (
 	tagid		int UNSIGNED NOT NULL AUTO_INCREMENT,
@@ -51,7 +47,8 @@
 	tagnameid	int UNSIGNED NOT NULL,
 	name		VARCHAR(32) DEFAULT '' NOT NULL,
 	value		VARCHAR(64) DEFAULT '' NOT NULL,
-	UNIQUE tagname_name (tagnameid, name)
+	UNIQUE tagname_name (tagnameid, name),
+	KEY name (name)
 ) TYPE=InnoDB;
 
 DROP TABLE IF EXISTS tagcommand_adminlog;
@@ -79,6 +76,7 @@
 	last_tagid_logged	int UNSIGNED NOT NULL,
 	last_tdid_logged	int UNSIGNED NOT NULL,
 	last_tuid_logged	int UNSIGNED NOT NULL,
+	nosy_gtids		varchar(255) DEFAULT '' NOT NULL,
 	PRIMARY KEY tbid (tbid),
 	UNIQUE name (name)
 ) TYPE=InnoDB;

Modified: slashjp/trunk/plugins/Tags/tagbox.pl
===================================================================
--- slashjp/trunk/plugins/Tags/tagbox.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/tagbox.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -40,26 +40,39 @@
 	}
 	tagboxLog('tagbox.pl starting');
 
-	my $exclude_behind = 0;
+	my $exclude_behind = 1;
 	my $max_activity_for_run = 10;
+	my $feederlog_largerows = $constants->{tags_feederlog_largerows} || 50_000;
 	while (!$task_exit_flag) {
 
-		# Insert into tagboxlog_feeder
-		my $activity_feeder = update_feederlog($exclude_behind);
-		sleep 2;
-		last if $task_exit_flag;
+		$exclude_behind = ! $exclude_behind;
 
-		# If there was a great deal of feeder activity, there is
-		# likely to be more yet to do, and it may obsolete the
-		# results we'd get by calling run() right now.  
-		if ($activity_feeder > 10) {
-			tagboxLog("tagbox.pl re-updating feederlog, activity $activity_feeder");
-			next;
+		# If tagboxlog_feeder has grown too large, temporarily exclude
+		# adding to it until it has shrunk to a more efficient size.
+
+		my $feederlog_rows = $tagboxdb->sqlCount('tagboxlog_feeder');
+		my $activity_feeder = undef;
+		if ($feederlog_rows < $feederlog_largerows) {
+
+			# Insert into tagboxlog_feeder
+			$activity_feeder = update_feederlog($exclude_behind);
+			sleep 2;
+			last if $task_exit_flag;
+
+			# If there was a great deal of feeder activity, there is
+			# likely to be more yet to do, and it may obsolete the
+			# results we'd get by calling run() right now.
+			if ($activity_feeder > 10) {
+				tagboxLog("tagbox.pl re-updating feederlog, activity $activity_feeder");
+				next;
+			}
+
 		}
 
 		# Run tagboxes (based on tagboxlog_feeder)
-		my $activity_run = run_tagboxes_until(time() + 30);
-		sleep 5;
+		my $force_overnight = $feederlog_rows < $feederlog_largerows ? 0 : 1;
+		my $activity_run = run_tagboxes_until(time() + 30, $force_overnight);
+		sleep 2;
 		last if $task_exit_flag;
 
 		# If nothing's going on, ease up more (not that it probably
@@ -71,7 +84,6 @@
 		}
 		last if $task_exit_flag;
 
-		$exclude_behind = ! $exclude_behind;
 	}
 
 	my $msg = sprintf("exiting after %d seconds", time - $start_time);
@@ -88,6 +100,42 @@
 	my $max_rows_per_tagbox = 1000;
 	my $max_rows_total = $max_rows_per_tagbox * 5;
 
+	# Pre-tagbox check:
+
+	# Get list of all new globjs since last update_feederlog, and
+	# insert NULL,NULL,NULL rows for each one wanted.
+	my $last_globjid_logged = $tagboxdb->getVar('tags_tagbox_lastglobjid', 'value', 1) || 0;
+	my $new_globjs_ar = $tagsdb->sqlSelectAllHashrefArray(
+		'globjid, gtid, target_id', 'globjs',
+		"globjid > $last_globjid_logged",
+		"ORDER BY globjid ASC LIMIT $max_rows_per_tagbox");
+	if ($new_globjs_ar && @$new_globjs_ar) {
+		my %tagbox_wants = ( );
+		for my $globj_hr (@$new_globjs_ar) {
+			my @tbids = $tagboxdb->getTagboxesNosyForGlobj($globj_hr);
+			for my $tbid (@tbids) {
+				$tagbox_wants{$tbid} ||= [ ];
+				push @{ $tagbox_wants{$tbid} }, $globj_hr->{globjid};
+			}
+		}
+		for my $tbid (keys %tagbox_wants) {
+			my $feeder_ar = [ ];
+			for my $globjid (@{ $tagbox_wants{$tbid} }) {
+				push @$feeder_ar, {
+					affected_id =>	$globjid,
+					importance =>	1,
+					tagid =>	undef,
+					tdid =>		undef,
+					tuid =>		undef,
+				};
+			}
+			insert_feederlog($tbid, $feeder_ar);
+		}
+		$tagboxdb->setVar('tags_tagbox_lastglobjid', $new_globjs_ar->[-1]{globjid});
+	}
+
+	# Now check tagboxes:
+
 	# If this is called with $exclude_behind set, ignore tagboxes
 	# which are too far behind other tagboxes.  For this purpose,
 	# only last_tagid_logged is examined, since the other two are
@@ -288,12 +336,35 @@
 }
 
 sub run_tagboxes_until {
-	my($run_until) = @_;
+	my($run_until, $force_overnight) = @_;
+	my $constants = getCurrentStatic();
 	my $activity = 0;
 	$tagboxes = $tagboxdb->getTagboxes();
+	my $overnight_sum = defined($constants->{tags_overnight_minweightsum})
+		? $constants->{tags_overnight_minweightsum}
+		: 1;
+	my $overnight_starthour = $constants->{tags_overnight_starthour} ||  7;
+	my $overnight_stophour  = $constants->{tags_overnight_stophour}  || 10;
 
 	while (time() < $run_until && !$task_exit_flag) {
-		my $affected_ar = $tagboxdb->getMostImportantTagboxAffectedIDs();
+		my $cur_count = 10;
+		my $cur_minweightsum = 1;
+
+		# If it's "overnight" (as defined in vars), purge the feeder log
+		# further down.
+		my $is_overnight = $force_overnight;
+		if (!$is_overnight) {
+			my $gmhour = (gmtime)[2];
+			if ($gmhour >= $overnight_starthour && $gmhour <= $overnight_stophour) {
+				$is_overnight = 1;
+			}
+		}
+		if ($is_overnight) {
+			$cur_count = 50;
+			$cur_minweightsum = $overnight_sum;
+		}
+
+		my $affected_ar = $tagboxdb->getMostImportantTagboxAffectedIDs($cur_count, $cur_minweightsum);
 		return $activity if !$affected_ar || !@$affected_ar;
 
 		$activity = 1;
@@ -309,7 +380,7 @@
 			last if time() >= $run_until || $task_exit_flag;
 		}
 
-		sleep 1;
+		Time::HiRes::sleep(0.2);
 	}
 	return $activity;
 }

Modified: slashjp/trunk/plugins/Tags/tags_tagnamecache.pl
===================================================================
--- slashjp/trunk/plugins/Tags/tags_tagnamecache.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/tags_tagnamecache.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: tags_tagnamecache.pl,v 1.1 2008/03/21 04:10:35 jamiemccarthy Exp $
+# $Id$
 
 # Once a day, rewrite the tags_tagnamecache table, used for finding
 # tagname suggestions based on prefixes.
@@ -14,7 +14,7 @@
 use Slash::Utility;
 use Slash::Constants ':slashd';
 
-(my $VERSION) = ' $Revision: 1.1 $ ' =~ /\$Revision:\s+([^\s]+)/;
+(my $VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
 
 $task{$me}{timespec} = "30 6 * * *";
 $task{$me}{timespec_panic_1} = ''; # not that important

Modified: slashjp/trunk/plugins/Tags/tags_udc.pl
===================================================================
--- slashjp/trunk/plugins/Tags/tags_udc.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/tags_udc.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
+# $Id$
 
 # Tags Upvote/Downvote Count
 #
@@ -21,7 +21,7 @@
 use Slash::Utility;
 use Slash::Constants ':slashd';
 
-(my $VERSION) = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+(my $VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
 
 $task{$me}{timespec} = '2-59/5 * * * *';
 $task{$me}{timespec_panic_1} = ''; # not that important

Modified: slashjp/trunk/plugins/Tags/tags_updateclouts.pl
===================================================================
--- slashjp/trunk/plugins/Tags/tags_updateclouts.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/tags_updateclouts.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 #
-# $Id: $
+# $Id$
 #
 # Slashd Task (c) OSTG 2004-2007
 
@@ -46,7 +46,7 @@
 			'tags_peerclout',
 			"clid=$clid AND gen = 0");
 		if ($tags_peerclout && %$tags_peerclout) {
-			$slashdb->sqlDelete('tags_peerclout', 'gen > 0');
+			$slashdb->sqlDelete('tags_peerclout', "gen > 0 AND clid=$clid");
 			sleep 5; # wait for that to replicate
 			my $g = 0;
 			while (1) {
@@ -78,7 +78,7 @@
 	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"; }
+if (!$rows) { use Data::Dumper; my $hd = Dumper($hr); $hd =~ s/\s+/ /g; slashdLog("insert hr: $hd"); }
                 $rows += $slashdb->sqlInsert('tags_peerclout', $hr);
                 $tags_peerclout->{ $hr->{uid} } = $hr->{clout};
         }

Modified: slashjp/trunk/plugins/Tags/templates/recenttagnamesbox;misc;default
===================================================================
--- slashjp/trunk/plugins/Tags/templates/recenttagnamesbox;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/templates/recenttagnamesbox;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -23,4 +23,4 @@
 __seclev__
 10000
 __version__
-$Id: recenttagnamesbox;misc;default,v 1.1 2007/12/06 02:49:31 jamiemccarthy Exp $
+$Id$

Modified: slashjp/trunk/plugins/Tags/templates/usertagnames;users;default
===================================================================
--- slashjp/trunk/plugins/Tags/templates/usertagnames;users;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/templates/usertagnames;users;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -40,4 +40,4 @@
 __seclev__
 10000
 __version__
-$Id: usertagnames;users;default,v 1.1 2008/03/27 00:10:26 jamiemccarthy Exp $
+$Id$

Modified: slashjp/trunk/plugins/Tags/templates/usertagsforname;users;default
===================================================================
--- slashjp/trunk/plugins/Tags/templates/usertagsforname;users;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Tags/templates/usertagsforname;users;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -55,4 +55,4 @@
 __seclev__
 10000
 __version__
-$Id: usertagsforname;users;default,v 1.2 2008/04/02 15:27:13 jamiemccarthy Exp $
+$Id$

Modified: slashjp/trunk/plugins/Validator/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Validator/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Validator/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -3,6 +3,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Validator',
-    'VERSION_FROM' => 'Validator.pm', # finds $VERSION
     'PM'	=> { 'Validator.pm' => '$(INST_LIBDIR)/Validator.pm' },
 );


Property changes on: slashjp/trunk/plugins/Validator/templates/html_invalid;misc;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/templates/html_invalid_subj;misc;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-html40-19980424/html40.tgz
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml-lat1.ent
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml-special.ent
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml-symbol.ent
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml.soc
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml1-frameset.dtd
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml1-strict.dtd
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml1-transitional.dtd
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Validator/validator/htdocs/sgml-lib/REC-xhtml1-20000126/xhtml1.dcl
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/plugins/YASS/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/YASS/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/YASS/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::YASS',
-    'VERSION_FROM' => 'YASS.pm', # finds $VERSION
     'PM'	=> { 'YASS.pm' => '$(INST_LIBDIR)/YASS.pm' },
 );

Modified: slashjp/trunk/plugins/YASS/YASS.pm
===================================================================
--- slashjp/trunk/plugins/YASS/YASS.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/YASS/YASS.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::YASS;
 
@@ -10,11 +9,10 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION @EXPORT);
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 sub new {
 	my($class, $user) = @_;

Modified: slashjp/trunk/plugins/Zoo/Makefile.PL
===================================================================
--- slashjp/trunk/plugins/Zoo/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Zoo/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -4,6 +4,5 @@
 # the contents of the Makefile that is written.
 WriteMakefile(
     'NAME'	=> 'Slash::Zoo',
-    'VERSION_FROM' => 'Zoo.pm', # finds $VERSION
     'PM'	=> { 'Zoo.pm' => '$(INST_LIBDIR)/Zoo.pm' },
 );

Modified: slashjp/trunk/plugins/Zoo/Zoo.pm
===================================================================
--- slashjp/trunk/plugins/Zoo/Zoo.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/plugins/Zoo/Zoo.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,7 +1,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Zoo;
 
@@ -12,11 +11,10 @@
 use Slash::Utility;
 use Slash::DB::Utility;
 
-use vars qw($VERSION @EXPORT);
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 # "There ain't no justice" -Niven
 # We can try. 	-Brian


Property changes on: slashjp/trunk/plugins/Zoo/templates/confirm;zoo;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/plugins/Zoo/templates/zoohead;zoo;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/sbin/portald
===================================================================
--- slashjp/trunk/sbin/portald	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/sbin/portald	2008-09-09 13:07:58 UTC (rev 742)
@@ -30,6 +30,7 @@
 use Slash;
 use Slash::Utility;
 use Slash::Display;
+use Slash::XML;
 
 my $virtual_user = $ARGV[0];
 createEnvironment($virtual_user);
@@ -76,9 +77,17 @@
 	my $moddb = getObject("Slash::$constants->{m1_pluginname}");
 	my $reasons = $moddb->getReasons;
 
+	my @items;
 	my $block = '<ul>';
 	foreach (@$A) {
-		my($sid, $title, $cid, $subj, $d, $nickname, $points, $reason) = @$_;
+		my($sid, $title, $cid, $subj, $d, $nickname, $points, $reason, $date) = @$_;
+		push @items, {
+			'link'  => "$gSkin->{absolutedir}/comments.pl?sid=$sid&cid=$cid",
+			title   => "$subj ($points points, $reasons->{$reason}{name})",
+			'time'  => $date,
+			creator => $nickname,
+			description => "Attached to <a href=\"$gSkin->{absolutedir}/article.pl?sid=$sid\">$title</a>"
+		};
 		$block .= <<EOT;
 
 <li> <b><a href="$gSkin->{rootdir}/comments.pl?sid=$sid&amp;cid=$cid">$subj</a>
@@ -92,6 +101,17 @@
 	$block .= '</ul>';
 	setblock('topcomments', $block);
 
+	if (@items && -d "$constants->{basedir}/privaterss/") {
+		my $rss = xmlDisplay('rss', {
+			channel => {
+				title       => "$constants->{sitename}: Hot Comments",
+				'link'      => "$gSkin->{absolutedir}/",
+			},
+			items   => \@items,
+			rdfitemdesc_html => 1
+		}, 1);
+		save2file("$constants->{basedir}/privaterss/topcomments.rss", $rss);
+	}
 }
 
 #################################################################

Modified: slashjp/trunk/sbin/slashd
===================================================================
--- slashjp/trunk/sbin/slashd	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/sbin/slashd	2008-09-09 13:07:58 UTC (rev 742)
@@ -23,6 +23,7 @@
 use Errno;
 use File::Basename;
 use File::Path;
+use File::Temp 'tempfile';
 use File::Spec::Functions qw(:DEFAULT devnull);
 use LWP::UserAgent;
 use HTTP::Request;
@@ -145,10 +146,11 @@
 		slashdLog("$taskname reaped ($pid)") if verbosity() >= 3;
 		delete $pids{$pid};
 		if ($status || $signal) {
-			slashdLog(sprintf
+			my $oddexit = sprintf
 				"%s odd exit (status %d, signal %d)",
-				$taskname, $status, $signal
-			);
+				$taskname, $status, $signal;
+			slashdLog($oddexit);
+			slashdErrnote($oddexit);
 		}
 		set_resources($taskname, -1);
 		insert_task_event($taskname, 0);
@@ -336,8 +338,57 @@
 EOT
 		}
 		my $file = basename($fullname);
+
+		# we want to encapsulate each task automatically.  to do that,
+		# we automatically create a package name for each task, and
+		# then we manually import the symbols we want into that package.
+		# then it is written out as a temp file, and THAT file is
+		# require'd, not the actual task.
+		# we may be importing more than we need for coderefs, but
+		# i didn't feel like looking at each task individually.
+
+		(my $tmppackage = $file) =~ s/\.pl$//;
+		$tmppackage =~ s/\W/_/g;
+		$tmppackage =~ s/^([^a-zA-Z])/a_$1/g;
+		$tmppackage = "Slash::Task::$tmppackage";
+
+		# replace tmppackage in string where appropriate
+		(my $addtxt = <<'EOT') =~ s/\${?tmppackage}?/$tmppackage/g;
+package $tmppackage;
+
+{ no strict 'refs';
+	my @scalar = qw(me task_exit_flag);
+	my @hash   = qw(task);
+	my @code   = (qw(
+			slashdLog slashdErrnote slashdLogDie
+			tagboxLog verbosity db_time init_cron
+		),
+		grep { *{"main::$_"}{CODE} }
+			@Slash::EXPORT, @Slash::Display::EXPORT,
+			@Slash::Utility::EXPORT,
+			@File::Spec::Functions::EXPORT,
+			@LWP::UserAgent::EXPORT, @URI::Escape::EXPORT,
+			@File::Basename::EXPORT, @File::Path::EXPORT,
+			@Time::Local::EXPORT, @Time::HiRes::EXPORT
+	);
+
+	*{"${tmppackage}::$_"} = *{"main::$_"}{HASH}   for @hash;
+	*{"${tmppackage}::$_"} = *{"main::$_"}{SCALAR} for @scalar;
+	*{"${tmppackage}::$_"} = *{"main::$_"}{CODE}   for @code;
+}
+
+#line 1
+EOT
+
+		my($tmpfh, $tmpfile) = tempfile();
+		my $tmptxt = do { open my $fh, '<', $fullname; local $/; <$fh> };
+		print $tmpfh $addtxt, $tmptxt;
+		$tmpfh->flush; # can't close fh until we require the file,
+		               # else the file might disappear
+
 		my $ok = 0;
-		eval { local $me = $file; $ok = require $fullname; };
+		eval { local $me = $file; $ok = require $tmpfile };
+
 		if ($@) {
 			slashdLog("requiring '$fullname' raised exception: $@");
 			$ok = 0;

Modified: slashjp/trunk/sql/mysql/defaults.sql
===================================================================
--- slashjp/trunk/sql/mysql/defaults.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/sql/mysql/defaults.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -27,6 +27,7 @@
 INSERT INTO al2_types VALUES (10, 8, 'nopostanon', 'No Comment Post Anon');
 INSERT INTO al2_types VALUES (11, 9, 'spammer', 'Spammer');
 INSERT INTO al2_types VALUES (12, 10, 'nom1', 'No Moderation');
+INSERT INTO al2_types VALUES (13, 11, 'openproxy', 'Open Proxy');
 
 
 #
@@ -199,6 +200,7 @@
 INSERT INTO discussion_kinds (dkid, name) VALUES (5, 'poll');
 INSERT INTO discussion_kinds (dkid, name) VALUES (6, 'submission');
 INSERT INTO discussion_kinds (dkid, name) VALUES (7, 'feed');
+INSERT INTO discussion_kinds (dkid, name) VALUES (8, 'project');
 
 #
 # Dumping data for table 'dst'
@@ -223,6 +225,7 @@
 INSERT INTO globj_types VALUES (NULL, 'submissions');
 INSERT INTO globj_types VALUES (NULL, 'journals');
 INSERT INTO globj_types VALUES (NULL, 'comments');
+INSERT INTO globj_types VALUES (NULL, 'projects');
 
 
 #
@@ -782,6 +785,8 @@
 INSERT INTO vars (name, value, description) VALUES ('charrefs_bad_entity','zwnj|zwj|lrm|rlm','Entities that approveCharref should always delete');
 INSERT INTO vars (name, value, description) VALUES ('charrefs_bad_numeric','8204|8205|8206|8207|8236|8237|8238','Numeric references that approveCharref should always delete');
 INSERT INTO vars (name, value, description) VALUES ('checklist_length','255','Length of user_index checklist fields (default is VARCHAR(255))');
+INSERT INTO vars (name, value, description) VALUES ('clientip_xff_trust_regex','^127\\.0\\.0\\.1$','IP addresses from which we will trust an X-Forwarded-For header');
+INSERT INTO vars (name, value, description) VALUES ('clientip_xff_trust_header','','Name of HTTP request header to prefer over "X-Forwarded-For", if present');
 INSERT INTO vars (name, value, description) VALUES ('cookie_location','classbid','Default for user\'s cookie_location value (also see users_info schema!)');
 INSERT INTO vars (name, value, description) VALUES ('comment_cache_max_hours','96','Discussion age at which comments are no longer cached');
 INSERT INTO vars (name, value, description) VALUES ('comment_compress_slice','500','Chars to slice comment into for compressOk');
@@ -833,7 +838,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_201','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_218','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?');
@@ -898,6 +903,7 @@
 INSERT INTO vars (name, value, description) VALUES ('id_md5_vislength','5','Num chars to display for ipid/subnetid (0 for all)');
 INSERT INTO vars (name, value, description) VALUES ('ignore_uid_date_index', '1', 'Ignore uid_date index on comments where it may slow performance');
 INSERT INTO vars (name, value, description) VALUES ('imagedir','//www.example.com/images','Absolute URL for image directory');
+INSERT INTO vars (name, value, description) VALUES ('imagemagick_convert', '/usr/bin/convert', 'Location of imagemagick convert for thumbnail generation');
 INSERT INTO vars (name, value, description) VALUES ('index_gse_backup_prob','0','Probability that index.pl getStoriesEssentials will look to backup_db_user instead of the main db: 0=never, 1=always');
 INSERT INTO vars (name, value, description) VALUES ('index_handler','index.pl','The perl servlet to call for connections to the root of the server.');
 INSERT INTO vars (name, value, description) VALUES ('index_handler_noanon','home','The shtml page to call if a user is anon and index_noanon is set');
@@ -1014,6 +1020,7 @@
 INSERT INTO vars (name, value, description) VALUES ('nick_maxlen', '20', 'Max length of nickname, should correspond with schema for users.nickname');
 INSERT INTO vars (name, value, description) VALUES ('no_prerendered_stories','0','Turn off use of prerendered stories in display');
 INSERT INTO vars (name, value, description) VALUES ('offer_insecure_login_link','0','Offer the user the \'totally insecure but very convenient\' index.pl login link');
+INSERT INTO vars (name, value, description) VALUES ('optipng', '', 'path to optipng if it is to be used for compressing thumbnails');
 INSERT INTO vars (name, value, description) VALUES ('organise_stories','','organise story blocks');
 INSERT INTO vars (name, value, description) VALUES ('panic','0','0:Normal, 1:No frills, 2:Essentials only');
 INSERT INTO vars (name, value, description) VALUES ('poll_cache','0','On home page, cache and display default poll for users (if false, is extra hits to database)');

Modified: slashjp/trunk/sql/mysql/slashschema_create.sql
===================================================================
--- slashjp/trunk/sql/mysql/slashschema_create.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/sql/mysql/slashschema_create.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -319,7 +319,22 @@
 	PRIMARY KEY (id)
 ) TYPE=InnoDB;
 
+#
+# Table structure for table 'comment_promote_log'
+#
+DROP TABLE IF EXISTS comment_promote_log;
 
+CREATE TABLE comment_promote_log (
+	id int unsigned NOT NULL auto_increment,
+	cid int unsigned NOT NULL default '0',
+	ts datetime NOT NULL default '1970-01-01 00:00:00',
+	PRIMARY KEY  (id),
+	KEY cid (cid)
+) ENGINE=InnoDB; 
+
+
+
+
 #
 # Table structure for table 'comment_text'
 #
@@ -717,6 +732,20 @@
 	KEY qid (qid,id,uid)
 ) TYPE=InnoDB;
 
+DROP TABLE IF EXISTS projects;
+CREATE TABLE projects (
+	id mediumint UNSIGNED NOT NULL auto_increment,
+	uid mediumint UNSIGNED NOT NULL DEFAULT 0,
+	unixname varchar(24) NOT NULL DEFAULT '',
+	textname varchar(64) NOT NULL DEFAULT '',
+	url_id INT(10) UNSIGNED NOT NULL DEFAULT 0,
+	createtime DATETIME DEFAULT '1970-01-01 00:00:00' NOT NULL,
+	srcname varchar(32) NOT NULL DEFAULT 0,
+	description         TEXT NOT NULL DEFAULT '',
+	PRIMARY KEY (id),
+	UNIQUE unixname (unixname)
+) Type=InnoDB;
+
 #
 # Table structure for table 'querylog'
 #
@@ -822,6 +851,7 @@
 	last_subid mediumint UNSIGNED,
 	last_sid varchar(16),
 	last_fhid mediumint UNSIGNED,
+	last_action varchar(16),
 	UNIQUE (uid),
 	PRIMARY KEY (session)
 ) TYPE=InnoDB;
@@ -975,9 +1005,10 @@
 	in_trash ENUM('no', 'yes') DEFAULT 'no' NOT NULL,
 	day_published DATE DEFAULT '1970-01-01' NOT NULL,
 	qid MEDIUMINT UNSIGNED DEFAULT NULL,
-	last_update timestamp NOT NULL,
+	last_update TIMESTAMP NOT NULL,
 	body_length MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL,
 	word_count MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL,
+	archive_last_update DATETIME DEFAULT '1970-01-01 00:00:00' NOT NULL,
 	PRIMARY KEY (stoid),
 	UNIQUE sid (sid),
 	INDEX uid (uid),
@@ -1069,7 +1100,7 @@
 #
 
 DROP TABLE IF EXISTS static_files;
-CREATE TABLE story_static_files(
+CREATE TABLE static_files(
 	sfid mediumint unsigned NOT NULL auto_increment,
 	stoid mediumint unsigned NOT NULL,
 	fhid mediumint unsigned NOT NULL,
@@ -1286,9 +1317,10 @@
 	validatedtitle VARCHAR(255),
 	tags_top VARCHAR(255) DEFAULT '' NOT NULL,
 	popularity float DEFAULT '0' NOT NULL,
+	anon_bookmarks MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL
 	PRIMARY KEY (url_id),
 	UNIQUE url_digest (url_digest),
-	anon_bookmarks MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL
+	INDEX bfu (believed_fresh_until)
 );
 
 #
@@ -1375,6 +1407,19 @@
 ) TYPE=InnoDB;
 
 #
+# Table structure for table 'users_comments_read_log'
+#
+
+DROP TABLE IF EXISTS users_comments_read_log;
+CREATE TABLE users_comments_read_log (
+	uid MEDIUMINT UNSIGNED NOT NULL,
+	discussion_id MEDIUMINT UNSIGNED NOT NULL,
+	cid INT UNSIGNED NOT NULL,
+	UNIQUE (discussion_id,uid,cid)
+) TYPE=InnoDB;
+
+
+#
 # Table structure for table 'users_hits'
 #
 
@@ -1510,6 +1555,15 @@
 	PRIMARY KEY (name)
 ) TYPE=InnoDB;
 
+DROP TABLE IF EXISTS xsite_auth_log;
+CREATE TABLE xsite_auth_log (
+	site VARCHAR(30) DEFAULT '' NOT NULL,
+	ts DATETIME DEFAULT '0000-00-00 00:00' NOT NULL,
+	nonce VARCHAR(30) DEFAULT '' NOT NULL,
+	UNIQUE KEY (site,ts,nonce)
+) TYPE=InnoDB;
+
+
 #ALTER TABLE backup_blocks ADD FOREIGN KEY (bid) REFERENCES blocks(bid);
 #ALTER TABLE comment_text ADD FOREIGN KEY (cid) REFERENCES comments(cid);
 #ALTER TABLE discussions ADD FOREIGN KEY (topic) REFERENCES topics(tid);

Modified: slashjp/trunk/sql/mysql/upgrades
===================================================================
--- slashjp/trunk/sql/mysql/upgrades	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/sql/mysql/upgrades	2008-09-09 13:07:58 UTC (rev 742)
@@ -5191,8 +5191,6 @@
 # 2008-03-19
 UPDATE vars SET value = 'T_2_5_0_198' WHERE name = 'cvs_tag_currentcode';
 
-# PUDGE LAST UPDATED HERE
-
 # for plugins/ResKey
 INSERT INTO reskey_resource_checks VALUES (NULL, 1, 'all', 'Slash::ResKey::Checks::HumanConf', 701);
 INSERT INTO reskey_vars VALUES (1, 'duration_uses-anon',         300, 'duration_uses for anon');
@@ -5247,10 +5245,6 @@
 # 2008-04-03
 UPDATE vars SET value = 'T_2_5_0_200' WHERE name = 'cvs_tag_currentcode';
 
-# SLASHCODE/USEPERL LAST UPDATED HERE
-
-# SLASHDOT LAST UPDATED HERE
-
 # For plugins/FireHose
 CREATE TABLE firehose_update_log(
   id mediumint(8) unsigned NOT NULL auto_increment,
@@ -5281,3 +5275,212 @@
 
 # 2008-04-09
 UPDATE vars SET value = 'T_2_5_0_201' WHERE name = 'cvs_tag_currentcode';
+
+# for plugins/ResKey (submit)
+INSERT INTO reskey_resource_checks VALUES (NULL, 6, 'all', 'Slash::ResKey::Checks::HumanConf',           701);
+INSERT INTO reskey_resource_checks VALUES (NULL, 6, 'all', 'Slash::ResKey::Checks::ProxyScan',           801);
+
+# for plugins/ResKey (comments)
+DELETE FROM reskey_vars WHERE rkrid = 1 AND name = 'max_duration';
+INSERT INTO reskey_vars VALUES (1, 'max_duration_touch', 1, 'boolean for whether to store max duration in reskey object on touch');
+
+# for plugins/FireHose
+ALTER TABLE firehose_update_log ADD bytes mediumint UNSIGNED DEFAULT 0 NOT NULL;
+ALTER TABLE firehose_setting_log DROP column bytes; 
+
+# 2008-04-16
+UPDATE vars SET value = 'T_2_5_0_202' WHERE name = 'cvs_tag_currentcode';
+
+ALTER TABLE sessions ADD column last_action varchar(16);
+
+# For plugins/FireHose
+INSERT INTO vars (name, value, description) VALUES ('firehose_mcd_disp', '1', 'Cache dispFireHose results');
+
+# 2008-05-01
+UPDATE vars SET value = 'T_2_5_0_203' WHERE name = 'cvs_tag_currentcode';
+
+# for plugins/FireHose
+ALTER TABLE firehose MODIFY type ENUM("submission","journal","bookmark","feed","story","vendor","misc", "comment") default 'submission';
+
+# for plugins/Stats
+INSERT INTO vars (name, value, description) VALUES ('stats_firehose_spamcount', '0', 'Number of firehose items marked as is_spam');
+
+# 2008-05-07
+UPDATE vars SET value = 'T_2_5_0_204' WHERE name = 'cvs_tag_currentcode';
+
+# for plugins/FireHose
+INSERT INTO vars (name, value, description) VALUES ('firehose_adminupclout', '0.5', 'Admin clout for upvotes can be reduced by specifying a number between 0 and 1');
+
+# for tagboxes/FHEditorPop
+UPDATE vars SET name='tagbox_fheditorpop_maxudcmult' WHERE name='tagbox_fhpopularity2_maxudcmult';
+
+CREATE TABLE comment_promote_log (
+  id int unsigned NOT NULL auto_increment,
+  cid int unsigned NOT NULL default '0',
+  ts datetime NOT NULL default '1970-01-01 00:00:00',
+  PRIMARY KEY  (id),
+  KEY cid (cid)
+) ENGINE=InnoDB; 
+
+
+# For plugins/Firehose
+ALTER TABLE firehose CHANGE COLUMN srcid srcid int UNSIGNED NOT NULL DEFAULT '0'; 
+
+ALTER TABLE firehose MODIFY type ENUM("submission","journal","bookmark","feed","story","vendor","misc","comment","discussion") default 'submission';
+
+# 2008-05-15
+UPDATE vars SET value = 'T_2_5_0_205' WHERE name = 'cvs_tag_currentcode';
+
+# 2008-05-21
+UPDATE vars SET value = 'T_2_5_0_206' WHERE name = 'cvs_tag_currentcode';
+
+INSERT INTO vars (name, value, description) VALUES ('imagemagick_convert', '/usr/bin/convert', 'Location of imagemagick convert for thumbnail generation');
+
+# 2008-05-22
+UPDATE vars SET value = 'T_2_5_0_207' WHERE name = 'cvs_tag_currentcode';
+
+# for plugins/HumanConf
+INSERT INTO vars (name, value, description) VALUES ('hc_turnover_secs', '259200', 'Seconds in which the entire humanconf pool should be replaced out');
+
+UPDATE vars SET name='clientip_xff_trust_regex' WHERE name='x_forwarded_for_trust_regex';
+INSERT IGNORE INTO vars (name, value, description) VALUES ('clientip_xff_trust_regex','^127\\.0\\.0\\.1$','IP addresses from which we will trust an X-Forwarded-For header');
+INSERT INTO vars (name, value, description) VALUES ('clientip_xff_trust_header','','Name of HTTP request header to prefer over "X-Forwarded-For", if present');
+
+ALTER TABLE urls ADD INDEX bfu (believed_fresh_until);
+
+# for plugins/FireHose
+ALTER TABLE firehose ADD INDEX url_id (url_id);
+
+ALTER TABLE stories ADD COLUMN archive_last_update DATETIME DEFAULT '1970-01-01 00:00:00' NOT NULL;
+# keep last_update the same
+UPDATE stories SET archive_last_update=last_update, last_update=last_update;
+
+
+# 2008-06-04
+UPDATE vars SET value = 'T_2_5_0_208' WHERE name = 'cvs_tag_currentcode';
+
+# PUDGE LAST UPDATED HERE
+
+# for plugins/Tags
+INSERT INTO vars (name, value, description) VALUES ('tags_overnight_minweightsum', '0.1', 'Minimum tagbox weight sum for overnight processing. To disable overnight difference, set to 1');
+INSERT INTO vars (name, value, description) VALUES ('tags_overnight_starthour', '7', 'GMT hour at which overnight processing begins');
+INSERT INTO vars (name, value, description) VALUES ('tags_overnight_stophour', '10', 'GMT hour after which overnight processing ends');
+
+# for tagboxes/CommentScoreReason
+INSERT INTO vars (name, value, description) VALUES ('tagbox_csr_baseneediness', '60', 'Base neediness score for comments that have been moderated');
+
+# 2008-06-19
+UPDATE vars SET value = 'T_2_5_0_209' WHERE name = 'cvs_tag_currentcode';
+
+# for plugins/FireHose
+# INSERT INTO ajax_ops VALUES (NULL, 'tags_get_top_firehose', 'Slash::FireHose', 'ajaxGetFireHoseTagsTop', 'ajax_tags_write', 'createuse');
+ALTER TABLE firehose ADD COLUMN neediness float NOT NULL default '0' AFTER editorpop;
+ALTER TABLE firehose ADD INDEX neediness (neediness);
+
+CREATE TABLE firehose_skin_volume(
+	skid SMALLINT UNSIGNED NOT NULL,
+	story_vol MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL,
+	other_vol MEDIUMINT UNSIGNED DEFAULT '0' NOT NULL,
+	PRIMARY KEY (skid)
+);
+
+DROP TABLE IF EXISTS users_comments_read_log;
+CREATE TABLE users_comments_read_log (
+	uid MEDIUMINT UNSIGNED NOT NULL,
+	discussion_id MEDIUMINT UNSIGNED NOT NULL,
+	cid INT UNSIGNED NOT NULL,
+	UNIQUE (discussion_id,uid,cid)
+) TYPE=InnoDB;
+
+# 2008-06-26
+UPDATE vars SET value = 'T_2_5_0_210' WHERE name = 'cvs_tag_currentcode';
+
+# for plugins/Tags
+ALTER TABLE tagboxes ADD COLUMN nosy_gtids varchar(255) DEFAULT '' NOT NULL;
+INSERT INTO vars (name, value, description) VALUES ('tags_feederlog_largerows', '50000', 'Number of rows at which the feederlog is considered "large", slowing additions');
+INSERT INTO vars (name, value, description) VALUES ('tags_tagbox_lastglobjid', '0', 'Last globjid that the tagbox scanned for possible insertion into feeder log');
+
+# for plugins/FireHose
+# INSERT INTO ajax_ops VALUES (NULL, 'tags_get_combined_firehose', 'Slash::FireHose', 'ajaxGetCombinedFirehose', 'ajax_tags_write', 'createuse');
+
+# 2008-07-03
+UPDATE vars SET value = 'T_2_5_0_211' WHERE name = 'cvs_tag_currentcode';
+
+# for plugins/Tags
+DELETE FROM ajax_ops WHERE op='tags_get_combined_firehose';
+DELETE FROM ajax_ops WHERE op='tags_get_top_firehose';
+INSERT INTO ajax_ops VALUES (NULL, 'tags_setget_combined', 'Slash::Tags', 'ajaxSetGetCombinedTags', 'ajax_tags_write', 'createuse');
+
+# for tagboxes/CommentScoreReason
+INSERT INTO vars (name, value, description) VALUES ('tagbox_csr_minneediness', '138', 'Minimum neediness score to possibly insert a needy comment into the firehose');
+INSERT INTO vars (name, value, description) VALUES ('tagbox_csr_needinesspercent', '5', 'Percentage of comments with the necessary minimum neediness which actually do get inserted into the firehose');
+
+# 2008-07-10
+UPDATE vars SET value = 'T_2_5_0_212' WHERE name = 'cvs_tag_currentcode';
+
+SELECT @maxbitpos := MAX(bitpos) FROM al2_types;
+INSERT INTO al2_types VALUES (NULL, @maxbitpos+1, 'openproxy', 'Open Proxy');
+
+UPDATE ajax_ops SET reskey_name='ajax_user_static' WHERE op='tags_setget_combined';
+
+# for tagboxes/FHEditorPop
+INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fheditorpop_maybefrac', '0.1', 'Amount that an editor nod+maybe boosts editorpop, expressed as fraction of a plain editor nod');
+
+# for tagboxes/FHPopularity
+INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fhpopularity_maybefrac', '1.0', 'Amount that an editor nod+maybe boosts popularity, expressed as fraction of a plain nod');
+
+# 2008-07-16
+UPDATE vars SET value = 'T_2_5_0_213' WHERE name = 'cvs_tag_currentcode';
+
+# 2008-07-31
+UPDATE vars SET value = 'T_2_5_0_214' WHERE name = 'cvs_tag_currentcode';
+
+# for plugins/FireHose
+ALTER TABLE firehose MODIFY type ENUM("submission","journal","bookmark","feed","story","vendor","misc", "comment","discussion","project") default 'submission';
+
+DROP TABLE IF EXISTS xsite_auth_log;
+CREATE TABLE xsite_auth_log (
+	site VARCHAR(30) DEFAULT '' NOT NULL,
+	ts DATETIME DEFAULT '0000-00-00 00:00' NOT NULL,
+	nonce VARCHAR(30) DEFAULT '' NOT NULL,
+	UNIQUE KEY (site,ts,nonce)
+) TYPE=InnoDB;
+
+
+# 2008-08-07
+UPDATE vars SET value = 'T_2_5_0_215' WHERE name = 'cvs_tag_currentcode';
+
+CREATE TABLE projects (
+	id mediumint UNSIGNED NOT NULL auto_increment,
+	uid mediumint UNSIGNED NOT NULL DEFAULT 0,
+	unixname varchar(24) NOT NULL DEFAULT '',
+	textname varchar(64) NOT NULL DEFAULT '',
+	url_id INT(10) UNSIGNED NOT NULL DEFAULT 0,
+	createtime DATETIME DEFAULT '1970-01-01 00:00:00' NOT NULL,
+	srcname varchar(32) NOT NULL DEFAULT 0,
+	description         TEXT NOT NULL DEFAULT '',
+	PRIMARY KEY (id),
+	UNIQUE unixname (unixname)
+) Type=InnoDB;
+
+INSERT INTO globj_types VALUES (NULL, 'projects');
+INSERT INTO discussion_kinds (dkid, name) VALUES (NULL, 'project');
+
+INSERT IGNORE INTO vars (name, value, description) VALUES ('optipng', '', 'path to optipng if it is to be used for compressing thumbnails');
+
+# 2008-08-13
+UPDATE vars SET value = 'T_2_5_0_216' WHERE name = 'cvs_tag_currentcode';
+
+# 2008-08-21
+UPDATE vars SET value = 'T_2_5_0_217' WHERE name = 'cvs_tag_currentcode';
+
+# SLASHCODE/USEPERL LAST UPDATED HERE
+
+# SLASHDOT LAST UPDATED HERE
+
+# for plugins/Tags
+ALTER TABLE tagname_params ADD INDEX name (name);
+
+# 2008-08-28
+UPDATE vars SET value = 'T_2_5_0_218' WHERE name = 'cvs_tag_currentcode';
+

Modified: slashjp/trunk/tagboxes/CommentScoreReason/CommentScoreReason.pm
===================================================================
--- slashjp/trunk/tagboxes/CommentScoreReason/CommentScoreReason.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/CommentScoreReason/CommentScoreReason.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,10 +2,11 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 # Requires TagModeration plugin (not (just) Moderation)
 
+# XXX add comments gtid as nosy
+
 package Slash::Tagbox::CommentScoreReason;
 
 =head1 NAME
@@ -22,6 +23,8 @@
 
 use strict;
 
+use Digest::MD5 'md5_hex';
+
 use Slash;
 use Slash::DB;
 use Slash::Utility::Environment;
@@ -29,8 +32,7 @@
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge
@@ -62,6 +64,7 @@
 	return undef if !$constants->{plugin}{Tags} || !$constants->{plugin}{TagModeration};
 	my($tagbox_name) = $class =~ /(\w+)$/;
 	return undef if !$constants->{tagbox}{$tagbox_name};
+	return 1;
 }
 
 sub feed_newtags {
@@ -142,20 +145,82 @@
 		my $tagnameid = $tagsdb->getTagnameidCreate($name);
 		$tagnameid_reasons{$tagnameid} = $reasons->{$id};
 	}
+	for my $tagname (qw( nod nix metanod metanix )) {
+		$self->{"${tagname}id"} ||= $tagsdb->getTagnameidCreate($tagname);
+	}
 
 	my $mod_score_sum = 0;
-	my($gtid, $cid) = $self->getGlobjTarget($affected_id);
+	my($type, $cid) = $self->getGlobjTarget($affected_id);
+	if ($type ne 'comments') {
+		my $comments_gtid = $self->getGlobjTypes()->{comments};
+		main::tagboxLog("ERROR - CommentScoreReason->run invoked for non-comment globj $affected_id, type='$type' comments_gtid=$comments_gtid");
+		return;
+	}
 	my $tags_ar = $tagboxdb->getTagboxTags($self->{tbid}, $affected_id, 0);
 	return unless $tags_ar && @$tags_ar;
 	my($keep_karma_bonus, $karma_bonus_downmods_left) = (1, $constants->{mod_karma_bonus_max_downmods});
 	my $current_reason_mode = 0;
+	my $base_neediness = $constants->{tagbox_csr_baseneediness} || 60;
+	my $neediness = $base_neediness;
+
+
+# Sun Jun 29 01:33:40 2008 CommentScoreReason->run setting cid=22886594 fhid=0 globjid=2059928 to score=0 reason=1 neediness=137
+# Sun Jun 29 01:33:40 2008 CommentScoreReason->run setting cid=22886640 fhid=0 globjid=2059992 to score=2 reason=7 neediness=137
+
+
+	# First scan: neediness (comments.f3).
+	my($up_rnf, $down_rnf) = (0, 0);
+	for my $tag (@$tags_ar) {
+		# Do nothing if this tag was inactivated.
+		next if $tag->{inactivated};
+		# If this was a moderation _or_ a nod/nix (indicating dis/agreement),
+		# neediness changes.  If this was done by an admin, neediness
+		# changes a lot.
+		my $tagnameid = $tag->{tagnameid};
+		my $reason = $tagnameid_reasons{$tagnameid};
+		my $dir = 0;
+		if ($reason->{val} > 0 || $tagnameid == $self->{nodid} || $tagnameid == $self->{metanodid}) {
+			$dir = 1;
+		} elsif ($reason->{val} < 0 || $tagnameid == $self->{nixid} || $tagnameid == $self->{metanixid}) {
+			$dir = -1;
+		}
+		next unless $dir;
+		my $mod_user = $self->getUser($tag->{uid});
+		my $net_fairs = $mod_user->{up_fair} + $mod_user->{down_fair}
+			- ($mod_user->{up_unfair} + $mod_user->{down_unfair});
+		my $root_net_fairs = ($net_fairs <= 1) ? 1 : ($net_fairs ** 0.5);
+		if ($dir > 0) { $up_rnf += $root_net_fairs }
+		else { $down_rnf += $root_net_fairs }
+		$neediness -= 1000 if $mod_user->{seclev} > 1;
+	}
+	$neediness -= abs($up_rnf - $down_rnf);
+	# Scale neediness to match the firehose color range.
+	my $top_entry_score = 290;
+	my $firehose = getObject('Slash::FireHose');
+	if ($firehose) {
+		$top_entry_score = $firehose->getEntryPopularityForColorLevel(1);
+	}
+	$neediness *= $top_entry_score/$base_neediness;
+	# If we are only doing a certain percentage of neediness here,
+	# this would be the place to hash the comment cid with salt and
+	# drop its score to -50 unless it randomly qualified.
+	# Minimum neediness is -50.
+	$neediness = -50 if $neediness < -50;
+
+	# Second scan: overall reason (comments.f2), and traditional
+	# comment score (comments.f1).
 	my $allreasons_hr = {( %{$reasons} )};
 	for my $id (keys %$allreasons_hr) {
 		$allreasons_hr->{$id} = { reason => $id, c => 0 };
 	}
 	for my $tag (@$tags_ar) {
+		# Do nothing if this tag was inactivated.
 		next if $tag->{inactivated};
-		my $reason = $tagnameid_reasons{$tag->{tagnameid}};
+		# Currently, only actual moderations (not nod/nixes) change a
+		# comment's score (and reason).  Only continue processing if
+		# this is an actual moderation.
+		my $tagnameid = $tag->{tagnameid};
+		my $reason = $tagnameid_reasons{$tagnameid};
 		next unless $reason;
 		if ($reason->{val} < 0) {
 			$keep_karma_bonus = 0 if --$karma_bonus_downmods_left < 0;
@@ -174,11 +239,42 @@
 
 #main::tagboxLog("CommentScoreReason->run setting cid $cid to score: $new_score, $reasons->{$current_reason_mode}{name} kb '$karma_bonus'->'$new_karma_bonus'");
 
+	if ($firehose) {
+		my $fhid = $firehose->getFireHoseIdFromGlobjid($affected_id);
+		if (!$fhid) {
+			$fhid = $self->addCommentToHoseIfAppropriate($firehose,
+				$affected_id, $cid, $neediness, $new_score);
+		}
+		$firehose->setFireHose($fhid, { neediness => $neediness }) if $fhid;
+	}
+
 	$self->sqlUpdate('comments', {
 			f1 =>	$new_score,
 			f2 =>	$current_reason_mode,
+			f3 =>	$neediness,
 		}, "cid='$cid'");
 }
 
+sub addCommentToHoseIfAppropriate {
+	my($self, $firehose, $globjid, $cid, $neediness, $score) = @_;
+	my $constants = getCurrentStatic();
+
+	my $fhid = 0;
+
+	# If neediness exceeds a threshold, the comment has a chance of appearing.
+	my $min = $constants->{tagbox_csr_minneediness} || 138;
+	return 0 if $neediness < $min;
+
+	# Hash its cid;  if the last 4 hex digits interpreted as a fraction are
+	# within the range determined, add it to the hose.
+	my $percent = $constants->{tagbox_csr_needinesspercent} || 5;
+	my $hex_percent = int(hex(substr(md5_hex($cid), -4)) * 100 / 65536);
+	return 0 if $hex_percent >= $percent;
+
+	$fhid = $firehose->createItemFromComment($cid);
+
+	return $fhid;
+}
+
 1;
 

Modified: slashjp/trunk/tagboxes/CommentScoreReason/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/CommentScoreReason/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/CommentScoreReason/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id: $
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::CommentScoreReason',
-    'VERSION_FROM' => 'CommentScoreReason.pm', # finds $VERSION
     'PM'	=> { 'CommentScoreReason.pm' =>   '$(INST_LIBDIR)/CommentScoreReason.pm' },
 );

Modified: slashjp/trunk/tagboxes/CommentScoreReason/TAGBOX
===================================================================
--- slashjp/trunk/tagboxes/CommentScoreReason/TAGBOX	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/CommentScoreReason/TAGBOX	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=CommentScoreReason
 description=Track comment score and reason
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/tagboxes/CommentScoreReason/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/CommentScoreReason/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/CommentScoreReason/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,8 @@
-# $Id: $
+# $Id$
 INSERT INTO tagboxes (tbid, name, affected_type, clid, weight, last_run_completed, last_tagid_logged, last_tdid_logged, last_tuid_logged) VALUES (NULL, 'CommentScoreReason', 'globj', 3, 1, '2000-01-01 00:00:00', 0, 0, 0);
 #INSERT INTO tagbox_userkeyregexes VALUES ('CommentScoreReason', '^tag_clout$');
 
+INSERT INTO vars (name, value, description) VALUES ('tagbox_csr_baseneediness', '60', 'Base neediness score for comments that have been moderated');
+INSERT INTO vars (name, value, description) VALUES ('tagbox_csr_minneediness', '138', 'Minimum neediness score to possibly insert a needy comment into the firehose');
+INSERT INTO vars (name, value, description) VALUES ('tagbox_csr_needinesspercent', '5', 'Percentage of comments with the necessary minimum neediness which actually do get inserted into the firehose');
+

Modified: slashjp/trunk/tagboxes/Despam/Despam.pm
===================================================================
--- slashjp/trunk/tagboxes/Despam/Despam.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/Despam/Despam.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 package Slash::Tagbox::Despam;
 
@@ -27,8 +26,7 @@
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge
@@ -309,6 +307,10 @@
 				main::tagboxLog(sprintf("%s->run force recalc tbid=%d globjid=%d",
 					ref($self), $tbid, $globjid));
 			}
+			# Add this change to the daily stats.
+			my $statsSave = getObject('Slash::Stats::Writer');
+			$statsSave->addStatDaily('firehose_binspam_despam',
+				$is_spam ? '+1' : '-1');
 		}
 	}
 

Modified: slashjp/trunk/tagboxes/Despam/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/Despam/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/Despam/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id: $
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::Despam',
-    'VERSION_FROM' => 'Despam.pm', # finds $VERSION
     'PM'	=> { 'Despam.pm' =>   '$(INST_LIBDIR)/Despam.pm' },
 );

Modified: slashjp/trunk/tagboxes/Despam/TAGBOX
===================================================================
--- slashjp/trunk/tagboxes/Despam/TAGBOX	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/Despam/TAGBOX	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=Despam
 description=Reduce (firehose) spam
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/tagboxes/Despam/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/Despam/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/Despam/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 INSERT INTO tagboxes (tbid, name, affected_type, clid, weight, last_run_completed, last_tagid_logged, last_tdid_logged, last_tuid_logged) VALUES (NULL, 'Despam', 'globj', 1, 1, '2000-01-01 00:00:00', 0, 0, 0);
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_despam_binspamsallowed', '1', 'Number of binspam tags allowed before action is taken');
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_despam_binspamsallowed_ip', '3', 'Number of binspam tags allowed before action is taken for an IP');

Copied: slashjp/trunk/tagboxes/DiscussionScore (from rev 741, slashjp/branches/upstream/2.5.0.218/tagboxes/DiscussionScore)

Modified: slashjp/trunk/tagboxes/FHActivity/FHActivity.pm
===================================================================
--- slashjp/trunk/tagboxes/FHActivity/FHActivity.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHActivity/FHActivity.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 package Slash::Tagbox::FHActivity;
 
@@ -27,8 +26,7 @@
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge

Modified: slashjp/trunk/tagboxes/FHActivity/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/FHActivity/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHActivity/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id: $
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::FHActivity',
-    'VERSION_FROM' => 'FHActivity.pm', # finds $VERSION
     'PM'	=> { 'FHActivity.pm' =>   '$(INST_LIBDIR)/FHActivity.pm' },
 );

Modified: slashjp/trunk/tagboxes/FHActivity/TAGBOX
===================================================================
--- slashjp/trunk/tagboxes/FHActivity/TAGBOX	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHActivity/TAGBOX	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=FHActivity
 description=Keep track of activity of firehose entries
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/tagboxes/FHActivity/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/FHActivity/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHActivity/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 INSERT INTO tagboxes (tbid, name, affected_type, clid, weight, last_run_completed, last_tagid_logged, last_tdid_logged, last_tuid_logged) VALUES (NULL, 'FHActivity', 'globj', 2, 1, '2000-01-01 00:00:00', 0, 0, 0);
 #INSERT INTO tagbox_userkeyregexes VALUES ('FHActivity', '^tag_clout$');
 

Modified: slashjp/trunk/tagboxes/FHEditorPop/FHEditorPop.pm
===================================================================
--- slashjp/trunk/tagboxes/FHEditorPop/FHEditorPop.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHEditorPop/FHEditorPop.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 # This goes by seclev right now but perhaps should define "editor"
 # to be more about author than admin seclev.  In which case the
@@ -26,13 +25,13 @@
 
 use Slash;
 use Slash::DB;
+use Slash::Utility::Comments;
 use Slash::Utility::Environment;
 use Slash::Tagbox;
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge
@@ -79,6 +78,9 @@
 	# 'nod' and 'nix', esp. from editors, are important.  Other tags are not.
 	my $upvoteid   = $tagsdb->getTagnameidCreate($constants->{tags_upvote_tagname}   || 'nod');
 	my $downvoteid = $tagsdb->getTagnameidCreate($constants->{tags_downvote_tagname} || 'nix');
+	my $maybeid    = $tagsdb->getTagnameidCreate('maybe');
+	my $metanodid  = $tagsdb->getTagnameidCreate('metanod');
+	my $metanixid  = $tagsdb->getTagnameidCreate('metanix');
 	my $admins = $self->getAdmins();
 	for my $uid (keys %$admins) {
 		$admins->{$uid}{seclev} = $tagsdb->getUser($uid, 'seclev');
@@ -86,7 +88,9 @@
 
 	my $ret_ar = [ ];
 	for my $tag_hr (@$tags_ar) {
-		next unless $tag_hr->{tagnameid} == $upvoteid || $tag_hr->{tagnameid} == $downvoteid;
+		next unless $tag_hr->{tagnameid} == $upvoteid || $tag_hr->{tagnameid} == $downvoteid
+			|| $tag_hr->{tagnameid} == $maybeid
+			|| $tag_hr->{tagnameid} == $metanodid || $tag_hr->{tagnameid} == $metanixid;
 		my $seclev = exists $admins->{ $tag_hr->{uid} }
 			? $admins->{ $tag_hr->{uid} }{seclev}
 			: 1;
@@ -133,7 +137,7 @@
 	my $constants = getCurrentStatic();
 	main::tagboxLog("FHEditorPop->feed_userchanges called: users_ar='" . join(' ', map { $_->{tuid} } @$users_ar) .  "'");
 
-	# XXX need to fill this in, and check FirstMover feed_userchanges too
+	# XXX need to fill this in
 
 	return [ ];
 }
@@ -190,18 +194,30 @@
 			# all its nexuses.
 			$color_level = $this_color_level if $this_color_level < $color_level;
 		}
+	} elsif ($type eq "comments") {
+		my $comment = $self->getComment($target_id);
+		my $score = constrain_score($comment->{points} + $comment->{tweak});
+		   if ($score >= 3) {	$color_level = 4 }
+		elsif ($score >= 2) {	$color_level = 5 }
+		elsif ($score >= 1) {	$color_level = 6 }
+		else {			$color_level = 7 }
 	}
 	$popularity = $firehose->getEntryPopularityForColorLevel($color_level) + $extra_pop;
 
 	# Add up nods and nixes.
 	my $upvoteid   = $tagsdb->getTagnameidCreate($constants->{tags_upvote_tagname}   || 'nod');
 	my $downvoteid = $tagsdb->getTagnameidCreate($constants->{tags_downvote_tagname} || 'nix');
+	my $maybeid    = $tagsdb->getTagnameidCreate('maybe') || 0;
+	my $metanodid  = $tagsdb->getTagnameidCreate('metanod');
+	my $metanixid  = $tagsdb->getTagnameidCreate('metanix');
 	my $admins = $self->getAdmins();
 	my $tags_ar = $tagboxdb->getTagboxTags($self->{tbid}, $affected_id, 0, $options);
 	$tagsdb->addCloutsToTagArrayref($tags_ar, 'vote');
 	my $udc_cache = { };
+	my($n_admin_maybes, $n_admin_nixes, $maybe_pop_delta) = (0, 0, 0);
 	for my $tag_hr (@$tags_ar) {
 		next if $options->{starting_only};
+		next if $tag_hr->{inactivated};
 		my $sign = 0;
 		$sign =  1 if $tag_hr->{tagnameid} == $upvoteid   && !$options->{downvote_only};
 		$sign = -1 if $tag_hr->{tagnameid} == $downvoteid && !$options->{upvote_only};
@@ -209,13 +225,42 @@
 		my $seclev = exists $admins->{ $tag_hr->{uid} }
 			? $admins->{ $tag_hr->{uid} }{seclev}
 			: 1;
-		my $editor_mult = $seclev >= 100 ? ($constants->{tagbox_fheditorpop_edmult} || 10) : 1;
-		my $extra_pop = $tag_hr->{total_clout} * $editor_mult * $sign;
+		my $editor_mult    = $seclev >= 100 ? ($constants->{tagbox_fheditorpop_edmult}    || 10   ) : 1;
+		my $noneditor_mult = $seclev ==   1 ? ($constants->{tagbox_fheditorpop_nonedmult} ||  0.75) : 1;
+		my $extra_pop = $tag_hr->{total_clout} * $editor_mult * $noneditor_mult * $sign;
 		my $udc_mult = get_udc_mult($tag_hr->{created_at_ut}, $udc_cache);
 #main::tagboxLog(sprintf("extra_pop for %d: %.6f * %.6f", $tag_hr->{tagid}, $extra_pop, $udc_mult));
 		$extra_pop *= $udc_mult;
+		if ($seclev > 1 && $sign == 1) {
+			# If this admin nod comes with a 'maybe', don't change
+			# popularity yet;  save it up and wait to see if any
+			# admins end up 'nix'ing.
+			if (grep {
+				     $_->{tagnameid} == $maybeid
+				&&   $_->{uid}       == $tag_hr->{uid}
+				&&   $_->{globjid}   == $tag_hr->{globjid}
+				&& ! $_->{inactivated}
+			} @$tags_ar) {
+				++$n_admin_maybes;
+				$maybe_pop_delta += $extra_pop;
+				$extra_pop = 0;
+			}
+		} elsif ($seclev > 1 && $sign == -1) {
+			++$n_admin_nixes;
+		}
 		$popularity += $extra_pop;
 	}
+	if ($n_admin_maybes > 0) {
+		if ($n_admin_nixes) {
+			# If any admin nixes, then all the admin nod+maybes are
+                        # ignored.  The nixes have already been counted normally.
+		} else {
+			# No admin nixes, so the maybes boost editor popularity by
+			# some fraction of the usual amount.
+			my $frac = $constants->{tagbox_fheditorpop_maybefrac} || 0.1;
+			$popularity += $maybe_pop_delta * $frac;
+		}
+	}
 
 	# If more than a certain number of users have tagged this item with
 	# public non-voting tags and its popularity is low, there may be a
@@ -247,6 +292,22 @@
 		$popularity = $max if $popularity > $max;
 	}
 
+	# If this is a comment item that's been nodded/nixed by an editor,
+	# its score goes way down (so no other editors have to bother with it).
+	if ($fhitem->{type} eq 'comment') {
+		for my $tag_hr (@$tags_ar) {
+			if ( (     $tag_hr->{tagnameid} == $upvoteid
+				|| $tag_hr->{tagnameid} == $downvoteid
+				|| $tag_hr->{tagnameid} == $metanodid
+				|| $tag_hr->{tagnameid} == $metanixid )
+			    && $admins->{ $tag_hr->{uid} }
+			) {
+				$popularity = -50 if $popularity > -50;
+				last;
+			}
+		}
+	}
+
 	# Set the corresponding firehose row to have this popularity.
 	warn "Slash::Tagbox::FHEditorPop->run bad data, fhid='$fhid' db='$firehose'" if !$fhid || !$firehose;
 	if ($options->{return_only}) {
@@ -297,7 +358,7 @@
 		$udc = $constants->{tagbox_fheditorpop_udcbasis};
 	}
 	my $udc_mult = $constants->{tagbox_fheditorpop_udcbasis}/$udc;
-	my $max_mult = $constants->{tagbox_fhpopularity2_maxudcmult} || 5;
+	my $max_mult = $constants->{tagbox_fheditorpop_maxudcmult} || 5;
 	$udc_mult = $max_mult if $udc_mult > $max_mult;
 #	main::tagboxLog(sprintf("get_udc_mult %0.3f time %d p %.3f c %.3f n %.3f th %.3f pw %.3f cw %.3f nw %.3f udc %.3f\n",
 #		$udc_mult, $time, $prevudc, $curudc, $nextudc, $thru_frac, $prevweight, $curweight, $nextweight, $udc));

Modified: slashjp/trunk/tagboxes/FHEditorPop/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/FHEditorPop/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHEditorPop/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id: $
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::FHEditorPop',
-    'VERSION_FROM' => 'FHEditorPop.pm', # finds $VERSION
     'PM'	=> { 'FHEditorPop.pm' =>   '$(INST_LIBDIR)/FHEditorPop.pm' },
 );

Modified: slashjp/trunk/tagboxes/FHEditorPop/TAGBOX
===================================================================
--- slashjp/trunk/tagboxes/FHEditorPop/TAGBOX	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHEditorPop/TAGBOX	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=FHEditorPop
 description=Keep track of popularity of firehose entries for editors
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/tagboxes/FHEditorPop/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/FHEditorPop/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHEditorPop/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,6 +1,9 @@
-# $Id: $
+# $Id$
 INSERT INTO tagboxes (tbid, name, affected_type, clid, weight, last_run_completed, last_tagid_logged, last_tdid_logged, last_tuid_logged) VALUES (NULL, 'FHEditorPop', 'globj', 2, 1, '2000-01-01 00:00:00', 0, 0, 0);
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fheditorpop_edmult', '10', 'Multiplier by which editor nod/nixes are weighted for editor view');
+INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fheditorpop_maxudcmult', '5', 'Maximum multiplier for an up/down tag based on the tags_udc table');
+INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fheditorpop_maybefrac', '0.1', 'Amount that an editor nod+maybe boosts editorpop, expressed as fraction of a plain editor nod');
+INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fheditorpop_nonedmult', '0.75', 'Multiplier by which non-editor nod/nixes are weighted for editor view');
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fheditorpop_udcbasis', '1000', 'Basis for tags_udc vote clout weighting');
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fheditorpop_susp_flagpop', '185', 'Admin score to artificially raise a suspicious host item to until an admin tags it');
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fheditorpop_susp_maxtaggers', '7', 'Max number of unique users tagging (not voting) a low-scoring firehose item that should not raise suspicion');

Modified: slashjp/trunk/tagboxes/FHPopularity/FHPopularity.pm
===================================================================
--- slashjp/trunk/tagboxes/FHPopularity/FHPopularity.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHPopularity/FHPopularity.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
+# This tagbox is outdated, superceded by FireHoseScores
 
 package Slash::Tagbox::FHPopularity;
 
@@ -27,8 +27,7 @@
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge
@@ -72,13 +71,15 @@
 	my $tagsdb = getObject('Slash::Tags');
 
 	# The algorithm of the importance of tags to this tagbox is simple.
-	# 'nod' and 'nix' are important.  Other tags are not.
+	# 'nod', 'nix', and sometimes 'maybe' are important.  Other tags are not.
 	my $upvoteid   = $tagsdb->getTagnameidCreate($constants->{tags_upvote_tagname}   || 'nod');
 	my $downvoteid = $tagsdb->getTagnameidCreate($constants->{tags_downvote_tagname} || 'nix');
+	my $maybeid    = $tagsdb->getTagnameidCreate('maybe');
 
 	my $ret_ar = [ ];
 	for my $tag_hr (@$tags_ar) {
-		next unless $tag_hr->{tagnameid} == $upvoteid || $tag_hr->{tagnameid} == $downvoteid;
+		next unless $tag_hr->{tagnameid} == $upvoteid || $tag_hr->{tagnameid} == $downvoteid
+			|| $tag_hr->{tagnameid} == $maybeid;
 		my $ret_hr = {
 			affected_id =>	$tag_hr->{globjid},
 			importance =>	1,
@@ -122,7 +123,7 @@
 	my $constants = getCurrentStatic();
 	main::tagboxLog("FHPopularity->feed_userchanges called: users_ar='" . join(' ', map { $_->{tuid} } @$users_ar) .  "'");
 
-	# XXX need to fill this in, and check FirstMover feed_userchanges too
+	# XXX need to fill this in
 
 	return [ ];
 }
@@ -176,22 +177,65 @@
 			# all its nexuses.
 			$color_level = $this_color_level if $this_color_level < $color_level;
 		}
+	} elsif ($type eq "comments") {
+		my $comment = $self->getComment($target_id);
+		my $score = constrain_score($comment->{points} + $comment->{tweak});
+		   if ($score >= 3) {   $color_level = 4 }
+		elsif ($score >= 2) {   $color_level = 5 }
+		elsif ($score >= 1) {   $color_level = 6 }
+		else {                  $color_level = 7 }
 	}
 	$popularity = $firehose->getEntryPopularityForColorLevel($color_level) + $extra_pop;
 
 	# Add up nods and nixes.
 	my $upvoteid   = $tagsdb->getTagnameidCreate($constants->{tags_upvote_tagname}   || 'nod');
 	my $downvoteid = $tagsdb->getTagnameidCreate($constants->{tags_downvote_tagname} || 'nix');
+	my $maybeid    = $tagsdb->getTagnameidCreate($constants->{tags_downvote_tagname} || 'nix');
+	my $admins = $self->getAdmins();
 	my $tags_ar = $tagboxdb->getTagboxTags($self->{tbid}, $affected_id, 0, $options);
 	$tagsdb->addCloutsToTagArrayref($tags_ar, 'vote');
+	my($n_admin_maybes, $n_admin_nixes, $maybe_pop_delta) = (0, 0, 0);
 	for my $tag_hr (@$tags_ar) {
 		next if $options->{starting_only};
+		next if $tag_hr->{inactivated};
 		my $sign = 0;
 		$sign =  1 if $tag_hr->{tagnameid} == $upvoteid   && !$options->{downvote_only};
 		$sign = -1 if $tag_hr->{tagnameid} == $downvoteid && !$options->{upvote_only};
 		next unless $sign;
-		$popularity += $tag_hr->{total_clout} * $sign;
+		my $seclev = exists $admins->{ $tag_hr->{uid} }
+			? $admins->{ $tag_hr->{uid} }{seclev}
+			: 1;
+		my $extra_pop = $tag_hr->{total_clout} * $sign;
+		if ($seclev > 1 && $sign == 1) {
+			# If this admin nod comes with a 'maybe', don't change
+			# popularity yet;  save it up and wait to see if any
+			# admins end up 'nix'ing.
+			if (grep {
+				     $_->{tagnameid} == $maybeid
+				&&   $_->{uid}       == $tag_hr->{uid}
+				&&   $_->{globjid}   == $tag_hr->{globjid}
+				&& ! $_->{inactivated}
+			} @$tags_ar) {
+				++$n_admin_maybes;
+				$maybe_pop_delta += $extra_pop;
+				$extra_pop = 0;
+			}
+		} elsif ($seclev > 1 && $sign == -1) {
+			++$n_admin_nixes;
+		}
+		$popularity += $extra_pop;
 	}
+	if ($n_admin_maybes > 0) {
+		if ($n_admin_nixes) {
+			# If any admin nixes, then all the admin nod+maybes are
+			# ignored.  The nixes have already been counted normally.
+		} else {
+			# No admin nixes, so the maybes boost editor popularity by
+			# some fraction of the usual amount.
+			my $frac = $constants->{tagbox_fhpopularity_maybefrac} || 1.0;
+			$popularity += $maybe_pop_delta * $frac;
+		}
+	}
 
 	# Set the corresponding firehose row to have this popularity.
 	my $affected_id_q = $self->sqlQuote($affected_id);

Modified: slashjp/trunk/tagboxes/FHPopularity/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/FHPopularity/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHPopularity/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id: $
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::FHPopularity',
-    'VERSION_FROM' => 'FHPopularity.pm', # finds $VERSION
     'PM'	=> { 'FHPopularity.pm' =>   '$(INST_LIBDIR)/FHPopularity.pm' },
 );

Modified: slashjp/trunk/tagboxes/FHPopularity/TAGBOX
===================================================================
--- slashjp/trunk/tagboxes/FHPopularity/TAGBOX	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHPopularity/TAGBOX	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=FHPopularity
 description=Keep track of popularity of firehose entries
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/tagboxes/FHPopularity/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/FHPopularity/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHPopularity/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,6 @@
-# $Id: $
+# $Id$
 INSERT INTO tagboxes (tbid, name, affected_type, clid, weight, last_run_completed, last_tagid_logged, last_tdid_logged, last_tuid_logged) VALUES (NULL, 'FHPopularity', 'globj', 2, 1, '2000-01-01 00:00:00', 0, 0, 0);
 #INSERT INTO tagbox_userkeyregexes VALUES ('FHPopularity', '^tag_clout$');
 
+INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_fhpopularity_maybefrac', '1.0', 'Amount that an editor nod+maybe boosts popularity, expressed as fraction of a plain nod');
+

Modified: slashjp/trunk/tagboxes/FHPopularity2/FHPopularity2.pm
===================================================================
--- slashjp/trunk/tagboxes/FHPopularity2/FHPopularity2.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHPopularity2/FHPopularity2.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,8 +2,9 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
+# This tagbox is outdated, superceded by FireHoseScores
+
 package Slash::Tagbox::FHPopularity2;
 
 =head1 NAME
@@ -27,8 +28,7 @@
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge

Modified: slashjp/trunk/tagboxes/FHPopularity2/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/FHPopularity2/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHPopularity2/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id: $
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::FHPopularity2',
-    'VERSION_FROM' => 'FHPopularity2.pm', # finds $VERSION
     'PM'	=> { 'FHPopularity2.pm' =>   '$(INST_LIBDIR)/FHPopularity2.pm' },
 );

Modified: slashjp/trunk/tagboxes/FHPopularity2/TAGBOX
===================================================================
--- slashjp/trunk/tagboxes/FHPopularity2/TAGBOX	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHPopularity2/TAGBOX	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=FHPopularity2
 description=Keep track of popularity of firehose entries (improved)
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/tagboxes/FHPopularity2/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/FHPopularity2/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FHPopularity2/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 INSERT INTO tagboxes (tbid, name, affected_type, clid, weight, last_run_completed, last_tagid_logged, last_tdid_logged, last_tuid_logged) VALUES (NULL, 'FHPopularity2', 'globj', 2, 1, '2000-01-01 00:00:00', 0, 0, 0);
 
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_firehosescores_maxudcmult', '5', 'Maximum multiplier for an up/down tag based on the tags_udc table');

Modified: slashjp/trunk/tagboxes/FireHoseScores/FireHoseScores.pm
===================================================================
--- slashjp/trunk/tagboxes/FireHoseScores/FireHoseScores.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FireHoseScores/FireHoseScores.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
 
 package Slash::Tagbox::FireHoseScores;
 
@@ -22,13 +21,13 @@
 
 use Slash;
 use Slash::DB;
+use Slash::Utility::Comments;
 use Slash::Utility::Environment;
 use Slash::Tagbox;
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision: $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge
@@ -204,6 +203,16 @@
 		}
 	}
 
+	# Also, admins may get reduced upvote clout.
+	if ($constants->{firehose_adminupclout} && $constants->{firehose_adminupclout} != 1) {
+		my $admins = $tagsdb->getAdmins();
+		for my $tag_hr (@$tags_ar) {
+			$tag_hr->{total_clout} *= $constants->{firehose_adminupclout}
+				if    $tag_hr->{tagnameid} == $upvoteid
+				   && $admins->{ $tag_hr->{uid} };
+		}
+	}
+
 	# Early in a globj's lifetime, if there have been few votes,
 	# upvotes count for more, and downvotes for less.
 	my($up_mult, $down_mult) = (1, 1);
@@ -291,6 +300,18 @@
 			# all its nexuses.
 			$color_level = $this_color_level if $this_color_level < $color_level;
 		}
+	} elsif ($type eq "comments") {
+		my $comment = $self->getComment($target_id);
+		my $score = constrain_score($comment->{points} + $comment->{tweak});
+		if ($score >= 3) {
+			$color_level = 4;
+		} elsif ($score == 2) {
+			$color_level = 5
+		} elsif ($score >= 0) {
+			$color_level = 6
+		} else {
+			$color_level = 7;
+		}
 	}
 	return($color_level, $extra_pop);
 }

Modified: slashjp/trunk/tagboxes/FireHoseScores/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/FireHoseScores/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FireHoseScores/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id: $
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::FireHoseScores',
-    'VERSION_FROM' => 'FireHoseScores.pm', # finds $VERSION
     'PM'	=> { 'FireHoseScores.pm' =>   '$(INST_LIBDIR)/FireHoseScores.pm' },
 );

Modified: slashjp/trunk/tagboxes/FireHoseScores/TAGBOX
===================================================================
--- slashjp/trunk/tagboxes/FireHoseScores/TAGBOX	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FireHoseScores/TAGBOX	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: $
+# $Id$
 name=FireHoseScores
 description=Keep track of popularity of firehose entries (final)
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/tagboxes/FireHoseScores/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/FireHoseScores/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/FireHoseScores/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: mysql_dump.sql,v 1.1 2007/09/28 03:33:20 jamiemccarthy Exp $
+# $Id$
 INSERT INTO tagboxes (tbid, name, affected_type, clid, weight, last_run_completed, last_tagid_logged, last_tdid_logged, last_tuid_logged) VALUES (NULL, 'FireHoseScores', 'globj', 2, 1, '2000-01-01 00:00:00', 0, 0, 0);
 
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_firehosescores_maxudcmult', '5', 'Maximum multiplier for an up/down tag based on the tags_udc table');

Copied: slashjp/trunk/tagboxes/Metamod (from rev 741, slashjp/branches/upstream/2.5.0.218/tagboxes/Metamod)

Modified: slashjp/trunk/tagboxes/RecentTags/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/RecentTags/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/RecentTags/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id: Makefile.PL,v 1.1 2008/04/02 15:21:44 jamiemccarthy Exp $
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::RecentTags',
-    'VERSION_FROM' => 'RecentTags.pm', # finds $VERSION
     'PM'	=> { 'RecentTags.pm' =>   '$(INST_LIBDIR)/RecentTags.pm' },
 );

Modified: slashjp/trunk/tagboxes/RecentTags/RecentTags.pm
===================================================================
--- slashjp/trunk/tagboxes/RecentTags/RecentTags.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/RecentTags/RecentTags.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: RecentTags.pm,v 1.4 2008/04/03 22:18:39 jamiemccarthy Exp $
 
 package Slash::Tagbox::RecentTags;
 
@@ -27,8 +26,7 @@
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision: 1.4 $ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge
@@ -153,7 +151,7 @@
 	@$tagnames_ar = grep { !$exclude_tagname{$_} } @$tagnames_ar;
 
 	# Max of 5 or whatever.
-	$#$tagnames_ar = 4 if scalar(@$tagnames_ar) > $num_wanted;
+	$#$tagnames_ar = $num_wanted-1 if scalar(@$tagnames_ar) > $num_wanted;
 
 	if (scalar(@$tagnames_ar) < $num_wanted) {
 		# If we don't get as many as we wanted, leave up

Modified: slashjp/trunk/tagboxes/RecentTags/TAGBOX
===================================================================
--- slashjp/trunk/tagboxes/RecentTags/TAGBOX	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/RecentTags/TAGBOX	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: TAGBOX,v 1.1 2008/04/02 15:21:44 jamiemccarthy Exp $
+# $Id$
 name=RecentTags
 description=Update the Recent Tags homepage slashbox
 mysql_dump=mysql_dump.sql

Modified: slashjp/trunk/tagboxes/RecentTags/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/RecentTags/mysql_dump.sql	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/RecentTags/mysql_dump.sql	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-# $Id: mysql_dump.sql,v 1.2 2008/04/03 20:30:24 jamiemccarthy Exp $
+# $Id$
 INSERT INTO tagboxes (tbid, name, affected_type, clid, weight, last_run_completed, last_tagid_logged, last_tdid_logged, last_tuid_logged) VALUES (NULL, 'RecentTags', 'globj', 1, 1, '2000-01-01 00:00:00', 0, 0, 0);
 
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_recenttags_secondsback', '7200', 'Number of seconds to look back');

Modified: slashjp/trunk/tagboxes/TagCountUser/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/TagCountUser/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/TagCountUser/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id$
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::TagCountUser',
-    'VERSION_FROM' => 'TagCountUser.pm', # finds $VERSION
     'PM'	=> { 'TagCountUser.pm' =>   '$(INST_LIBDIR)/TagCountUser.pm' },
 );

Modified: slashjp/trunk/tagboxes/TagCountUser/TagCountUser.pm
===================================================================
--- slashjp/trunk/tagboxes/TagCountUser/TagCountUser.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/TagCountUser/TagCountUser.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Tagbox::TagCountUser;
 
@@ -27,8 +26,7 @@
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge
@@ -113,10 +111,9 @@
 
 sub run {
 	my($self, $affected_id) = @_;
-	my $tagboxdb = getObject('Slash::Tagbox');
-	my $user_tags_ar = $tagboxdb->getTagboxTags($self->{tbid}, $affected_id, 0);
-	main::tagboxLog("TagCountUser->run called for $affected_id, ar count " . scalar(@$user_tags_ar));
-	my $count = grep { !defined $_->{inactivated} } @$user_tags_ar;
+	my $tagboxdb = getObject('Slash::Tagbox', { db_type => 'reader' });
+	my $count = $tagboxdb->sqlCount('tags', "uid=$affected_id AND inactivated IS NULL");
+	main::tagboxLog("TagCountUser->run called for $affected_id, count $count");
 	$self->setUser($affected_id, { tag_count => $count });
 }
 


Property changes on: slashjp/trunk/tagboxes/TagCountUser/TagCountUser.pm
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/tagboxes/Top/Makefile.PL
===================================================================
--- slashjp/trunk/tagboxes/Top/Makefile.PL	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/Top/Makefile.PL	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,9 +1,7 @@
 use ExtUtils::MakeMaker;
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
-# $Id$
 WriteMakefile(
     'NAME'	=> 'Slash::Tagbox::Top',
-    'VERSION_FROM' => 'Top.pm', # finds $VERSION
     'PM'	=> { 'Top.pm' =>   '$(INST_LIBDIR)/Top.pm' },
 );

Modified: slashjp/trunk/tagboxes/Top/Top.pm
===================================================================
--- slashjp/trunk/tagboxes/Top/Top.pm	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/tagboxes/Top/Top.pm	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,6 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id$
 
 package Slash::Tagbox::Top;
 
@@ -27,8 +26,7 @@
 
 use Data::Dumper;
 
-use vars qw( $VERSION );
-$VERSION = ' $Revision$ ' =~ /\$Revision:\s+([^\s]+)/;
+our $VERSION = $Slash::Constants::VERSION;
 
 use base 'Slash::DB::Utility';	# first for object init stuff, but really
 				# needs to be second!  figure it out. -- pudge


Property changes on: slashjp/trunk/tagboxes/Top/Top.pm
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/themes/slashcode/THEME
===================================================================
--- slashjp/trunk/themes/slashcode/THEME	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/THEME	2008-09-09 13:07:58 UTC (rev 742)
@@ -104,6 +104,7 @@
 image=htdocs/images/slc.gif
 image=htdocs/images/slr.gif
 image=htdocs/images/spinner.gif
+image=htdocs/images/spinner_grey.gif
 image=htdocs/images/sr.gif
 image=htdocs/images/srs.gif
 image=htdocs/images/tbl_g.gif

Modified: slashjp/trunk/themes/slashcode/htdocs/article.pl
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/article.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/article.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -15,6 +15,7 @@
 	my $constants = getCurrentStatic();
 	my $user      = getCurrentUser();
 	my $form      = getCurrentForm();
+	my $gSkin     = getCurrentSkin();
 
 	my $story;
 	my $reader = getObject('Slash::DB', { db_type => 'reader' });
@@ -83,6 +84,9 @@
 		my $SECT = $reader->getSection($story->{section});
 		# This should be a getData call for title
 		my $title = "$constants->{sitename} | $story->{title}";
+		if ($gSkin->{name} eq "idle") {
+			$title = "$gSkin->{hostname} | $story->{title}";
+		}
 
 		my $authortext;
 		if ($user->{is_admin} ) {
@@ -224,7 +228,7 @@
 			# is being called by slashd, and we need to write
 			# that file, then here's where we print an empty
 			# file that will satisfy slashd. - Jamie
-			Slash::_print_cchp({ stoid => "dummy" });
+			Slash::Utility::Comments::_print_cchp({ stoid => "dummy" });
 		}
 	} else {
 		header('Error', $form->{section}) or return;

Modified: slashjp/trunk/themes/slashcode/htdocs/badge.js
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/badge.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/badge.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,15 +1,18 @@
 (
   function() {
-    var url = encodeURIComponent(window.[% sitename %]_url || window.location.href);
-    var sty = window.[% sitename %]_badge_style || 'h0';
-    var title = encodeURIComponent(window.[% sitename %]_title || document.title);
+    var sitename   = '[% sitename | replace("[^A-Za-z_]+", "_")  %]';
+    var url_attr   = 'url='   + encodeURIComponent(window.[sitename + "_url"]         || window.location.href);
+    var style_attr = 'style=' + encodeURIComponent(window.[sitename + "_badge_style"] || 'h0');
+    var title_attr = 'title=' + encodeURIComponent(window.[sitename + "_title"]       || document.title);
+    var src_query  = '?' + [style_attr, url_attr, title_attr].join('&');
+
     var dx=130, dy=25;
-    if ( sty[0]=='v' ) {
+    if ( /^style=v/.test(style_attr) ) {
       dx=52;
       dy=80;
     }
     
-    var iframe = '<iframe src="http://[% basedomain %]/badge.pl?style=' + sty + '&url=' + url + '&amp;title=' + title + '"' +
+    var iframe = '<iframe src="[% absolutedir %]/badge.pl'+src_query+'"' +
                   ' height="' + dy + '" width="' + dx + '" scrolling="no" frameborder="0"></iframe>'
     document.write(iframe);
   }

Modified: slashjp/trunk/themes/slashcode/htdocs/badge.pl
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/badge.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/badge.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl
-# $Id: badge.pl,v 1.1 2007/12/13 15:55:16 scc Exp $
+# $Id$
 
 use strict;
 use Slash;
@@ -91,8 +91,9 @@
 		}
 
 		# ...and _now_ we can head into submit.pl
-		my $safe = strip_paramattr($form->{url});
-		$dest_url = "/submit.pl?url=${safe}";
+		my $safe_url = strip_paramattr($form->{url});
+		my $safe_title = strip_paramattr($form->{title});
+		$dest_url = "/submit.pl?url=$safe_url&subj=$safe_title";
 	} else {
 		$dest_url = "/faq/badges.shtml";
 	}

Modified: slashjp/trunk/themes/slashcode/htdocs/comments.pl
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/comments.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/comments.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -702,12 +702,19 @@
 	# multiple-point-spends if the user still has points.
 	my $can_del = ($constants->{authors_unlimited} && $user->{seclev} >= $constants->{authors_unlimited})
 		|| $user->{acl}{candelcomments_always};
+
 	for my $key (sort keys %{$form}) {
 		if ($can_del && $key =~ /^del_(\d+)$/) {
 			$total_deleted += deleteThread($sid, $1);
 		} elsif (!$hasPosted && $key =~ /^reason_(\d+)$/) {
-			my $cid = $1;
-			my $ret_val = $moddb->moderateComment($sid, $cid, $form->{$key});
+			my($cid, $can_mod, $ret_val, $comment) = (0, 0, 0);
+			$cid = $1;
+			$comment = $moddb->getComment($cid) if $cid;
+			$can_mod = Slash::Utility::Comments::_can_mod($comment) if $comment;
+			$ret_val = $moddb->moderateComment(
+				$sid, $cid, $form->{$key}, { comment => $comment }
+			) if $can_mod;
+
 			# If an error was returned, tell the user what
 			# went wrong.
 			if ($ret_val < 0) {

Modified: slashjp/trunk/themes/slashcode/htdocs/help.pl
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/help.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/help.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: help.pl,v 1.2 2008/02/20 17:04:38 entweichen Exp $
+# $Id$
 
 use strict;
 

Modified: slashjp/trunk/themes/slashcode/htdocs/images/comments.js
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/images/comments.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/images/comments.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,12 +1,11 @@
-// $Id: comments.js,v 1.26 2006/07/11 18:24:41 tvroom Exp $
-
 var comments;
-var root_comments;
+var root_comments = [];
 var noshow_comments;
 var pieces_comments;
 var placeholder_comments = [];
 var placeholder_no_update = {};
 var abbrev_comments = {};
+var read_comments = {};
 var init_hiddens = [];
 var fetch_comments = [];
 var fetch_comments_pieces = {};
@@ -29,8 +28,20 @@
 var viewmodevalue = { full: 3, oneline: 2, hidden: 1};
 var currents = { full: 0, oneline: 0, hidden: 0 };
 var commentelements = {};
-var thresh_totals = {};
+var thresh_totals = {
+	"-1":{"-1":0,0:0,1:0,2:0,3:0,4:0,5:0,6:0},
+	   0:{0:0,1:0,2:0,3:0,4:0,5:0,6:0},
+	   1:{1:0,2:0,3:0,4:0,5:0,6:0},
+	   2:{2:0,3:0,4:0,5:0,6:0},
+	   3:{3:0,4:0,5:0,6:0},
+	   4:{4:0,5:0,6:0},
+	   5:{5:0,6:0},
+	   6:{6:0}
+};
 var d2_keybindings_off = 0;
+var d2_keybindings_disable = {};
+var d2_reverse_shift = 0;
+var d2_comment_order = 0; // 0 == score, 1 == chrono
 
 var submitCountdowns = {};
 var ajaxCommentsWaitQueue = [];
@@ -38,14 +49,21 @@
 var comment_body_reply = [];
 var root_comment = 0;
 var discussion_id = 0;
+
 var user_is_subscriber = 0;
 var user_is_admin = 0;
 var user_is_anon = 0;
 var user_uid = 0;
+
+var no_lower_threshold = 0;
+var user_threshold_save = 1;
 var user_threshold = 0;
 var user_highlightthresh = 0;
 var user_threshold_orig = -9;
 var user_highlightthresh_orig = -9;
+var user_d2asp = 0;
+
+var async_off = 0;
 var loaded = 0;
 var shift_down = 0;
 var alt_down = 0;
@@ -57,8 +75,8 @@
 var adTimerSecs;
 var adTimerClicks;
 var adTimerInsert;
-var adTimerSecsMax   = 120;
-var adTimerClicksMax = 10;
+var adTimerSecsMax   = 90;
+var adTimerClicksMax = 8;
 var adTimerSeen = {};
 var adTimerUrl  = '';
 resetAdTimer();
@@ -124,50 +142,23 @@
 	return void(0);
 }
 
-function updateCommentTree(cid, threshold, subexpand) {
+function updateCommentTree(cid, threshold, lowestmode, skip_read) {
 	setDefaultDisplayMode(cid);
 	var comment = comments[cid];
 
-	// skip the root comment, if it exists; leave it full, but let user collapse
-	// if he chooses, and leave it that way: this comment will not move with
-	// T/HT changes
-	if ((subexpand || threshold) && cid != root_comment) {
-		if (subexpand && subexpand == 1) {
-			if (prehiddendisplaymode[cid] == 'oneline' || prehiddendisplaymode[cid] == 'full') {
-				futuredisplaymode[cid] = 'full';
-			} else {
-				futuredisplaymode[cid] = 'hidden';
-			}
-		} else {
-			futuredisplaymode[cid] = determineMode(cid, threshold, user_highlightthresh);
-		}
+	// skip the root comment, if it exists; leave it full
+	if (threshold && cid != root_comment)
+		futuredisplaymode[cid] = determineMode(cid, threshold, user_highlightthresh, lowestmode, skip_read);
 
+	if (displaymode[cid] != futuredisplaymode[cid]) {
 		updateDisplayMode(cid, futuredisplaymode[cid], 1);
+		update_comments[cid] = futuredisplaymode[cid];
 	}
 
-//	if (subexpand && subexpand == 2) {
-//		updateComment(cid, 'hidden');
-//		prehiddendisplaymode[cid] = futuredisplaymode[cid];
-//	} else if (futuredisplaymode[cid] && futuredisplaymode[cid] != displaymode[cid]) {
-		//updateComment(cid, futuredisplaymode[cid]);
-		if (displaymode[cid] != futuredisplaymode[cid]) {
-			update_comments[cid] = futuredisplaymode[cid];
-		}
-//	}
-
 	var kidhiddens = 0;
 	if (comment && comment['kids'] && comment['kids'].length) {
-// 		if (!subexpand) {
-// 			if (shift_down && !alt_down && futuredisplaymode[cid] == 'full') {
-// 				subexpand = 1;
-// 			} else if (shift_down && !alt_down && futuredisplaymode[cid] == 'oneline') {
-// 				subexpand = 2;
-// 				threshold = user_threshold;
-// 			}
-// 		}
-
 		for (var kiddie = 0; kiddie < comment['kids'].length; kiddie++) {
-			kidhiddens += updateCommentTree(comment['kids'][kiddie], threshold, subexpand);
+			kidhiddens += updateCommentTree(comment['kids'][kiddie], threshold, lowestmode, skip_read);
 		}
 	}
 
@@ -272,7 +263,7 @@
 	changeThreshold(user_threshold + ''); // needs to be a string value
 }
 
-function changeT(delta, skip_ht) {
+function changeT(delta, skip_ht, lowestmode) {
 	if (!delta)
 		return void(0);
 
@@ -281,10 +272,10 @@
 	threshold = Math.min(Math.max(threshold, -1), 6);
 
 	// HT moves with T, but that is taken care of by changeThreshold()
-	changeThreshold(threshold + '', skip_ht); // needs to be a string value
+	changeThreshold(threshold + '', skip_ht, lowestmode); // needs to be a string value
 }
 
-function changeThreshold(threshold, skip_ht) {
+function changeThreshold(threshold, skip_ht, lowestmode) {
 	var threshold_num = parseInt(threshold);
 	var t_delta = threshold_num + (user_highlightthresh - user_threshold);
 	user_threshold = threshold_num;
@@ -296,7 +287,7 @@
 	}
 
 	for (var root = 0; root < root_comments.length; root++) {
-		updateCommentTree(root_comments[root], threshold);
+		updateCommentTree(root_comments[root], threshold, lowestmode, skip_ht);
 	}
 	finishCommentUpdates(1);
 
@@ -305,7 +296,27 @@
 	return void(0);
 }
 
+// not currently used
+function parseCommentBitmap(bitmap) {
+	if (!bitmap)
+		return;
 
+	var lastcid = 0;
+	var comments_hash = {};
+	var temp = bitmap.split(',');
+
+	for (var i = 0; i < temp.length; i++) {
+		var thiscid = parseInt(temp[i]);
+		thiscid = lastcid ? (lastcid + thiscid) : thiscid;
+		comments_hash[thiscid] = 1;
+		lastcid = thiscid;
+	}
+
+	return comments_hash;
+}
+
+
+
 /*******************************/
 /* thread kid/hidden functions */
 /*******************************/
@@ -342,23 +353,28 @@
 	return 0;
 }
 
-function revealKids(cid) {
+function revealKids(cid, not_top) {
 	if (!loaded)
 		return false;
 
 	setDefaultDisplayMode(cid);
 	var comment = comments[cid];
+	var len = comment['kids'].length;
 
-	if (comment['kids'].length) {
-		for (var kiddie = 0; kiddie < comment['kids'].length; kiddie++) {
+	if (len) {
+		var only_one = 0;
+		if (!not_top && len == 1)
+			only_one = 1;
+
+		for (var kiddie = 0; kiddie < len; kiddie++) {
 			var kid = comment['kids'][kiddie];
 			setDefaultDisplayMode(kid);
 			if (comments[kid]['points'] == -2) { // -2 is special case for placeholder-hiddens
-				revealKids(kid);
+				revealKids(kid, 1); // 1 == not at the top level
 				continue;
 			}
 			if (displaymode[kid] == 'hidden') {
-				futuredisplaymode[kid] = 'oneline';
+				futuredisplaymode[kid] = only_one ? 'full' : 'oneline';
 				updateDisplayMode(kid, futuredisplaymode[kid], 1);
 				updateComment(kid, futuredisplaymode[kid]);
 			}
@@ -484,8 +500,8 @@
 	html = html || dummyComment(cid);
 
 	if (pid) {
-		var tree = $dom('tree_' + pid);
-		if (tree) {
+		var tree = $('#tree_' + pid);
+		if (tree.length) {
 			setDefaultDisplayMode(pid);
 			var parent = comments[pid];
 			if (front)
@@ -493,24 +509,25 @@
 			else
 				parent['kids'].push(cid);
 
-			var commtree = $dom('commtree_' + pid);
-			if (commtree) {
+			var commtree = $('#commtree_' + pid);
+			if (commtree.length) {
 				if (front)
-					commtree.innerHTML = html + commtree.innerHTML;
+					commtree.prepend(html);
 				else
-					commtree.innerHTML = commtree.innerHTML + html;
+					commtree.append(html);
 			} else {
-				tree.innerHTML = tree.innerHTML + '<ul id="commtree_' + pid + '">' + html + '</ul>';
+				tree.append('<ul id="commtree_' + pid + '">' + html + '</ul>');
 			}
 		}
 
 	} else {
-		var commlist = $dom('commentlisting');
-		if (commlist) {
+		var commlist = $('#commentlisting');
+
+		if (commlist.length) {
 			root_comments.push(cid);
 			root_comments_hash[cid] = 1;
 
-			commlist.innerHTML = commlist.innerHTML.replace(/(<li id="roothiddens" class="hide".*?>)/i, html + "$1");
+			$('#roothiddens').before(html);
 		}
 	}
 
@@ -646,18 +663,29 @@
 	];
 }
 
-function determineMode(cid, thresh, hthresh) {
+function determineMode(cid, thresh, hthresh, lowestmode, skip_read) {
 	if (!thresh)
 		thresh  = user_threshold;
 	if (!hthresh)
 		hthresh = user_highlightthresh;
 
+	// lowestmode tells us to NOT change the mode of a comment
+	// that is above a certain mode
+	if (lowestmode && viewmodevalue[displaymode[cid]] > viewmodevalue[lowestmode])
+		return displaymode[cid];
+
+	var mode;
 	if (thresh >= 6 || (comments[cid]['points'] < thresh && (user_is_anon || user_uid != comments[cid]['uid'])))
-		return 'hidden';
+		mode = 'hidden';
 	else if (comments[cid]['points'] < (hthresh - (root_comments_hash[cid] ? 1 : 0)))
-		return 'oneline';
+		mode = 'oneline';
 	else
-		return 'full';
+		mode = 'full';
+
+	if (skip_read && comments[cid]['read'] && (viewmodevalue[mode] > viewmodevalue['oneline']))
+		mode = 'oneline';
+
+	return mode;
 }
 
 function finishCommentUpdates(thresh) {
@@ -713,6 +741,15 @@
 	}).join(';');
 }
 
+function toArray(thisobject) {
+	return map_hash(thisobject, function (pair) {
+		return pair[0];
+	});
+}
+
+// option = 1: get more, 2: just send update data
+// thresh = send threshold
+// highlight = 1: go to next comment after loading; 2: collapse previous comment
 function ajaxFetchComments(cids, option, thresh, highlight) {
 	if (cids && !cids.length)
 		return;
@@ -720,11 +757,12 @@
 	if (!cids && ajaxCommentsWait())
 		return;
 
-	if (option)
+	if (option && option == 1)
 		thresh = 1;
 
-	var params = {};
-	params['op']              = 'comments_fetch';
+	var options = {};
+	var params  = {};
+	params['op'] = 'comments_fetch';
 
 	var newoldstuff = cids ? 0 : 1;
 
@@ -732,11 +770,17 @@
 		params['cids']    = cids;
 	} else {
 		cids              = [];
-		if (option && d2_seen)
-			params['d2_seen']  = d2_seen;
+		if (option && option == 1 && d2_seen)
+			params['d2_seen'] = d2_seen;
+		else if (option && option == 2)
+			options['async_off'] = 1; // otherwise browser closes before data sent!
 		else
 			params['cids']    = noshow_comments;
 	}
+
+	if (async_off) // global
+		options['async_off'] = 1;
+
 	if (thresh) {
 		params['threshold']       = user_threshold;
 		params['highlightthresh'] = user_highlightthresh;
@@ -754,7 +798,7 @@
 			abbrev[cids[i]] = abbrev_comments[cids[i]];
 	}
 	params['abbreviated'] = toHash(abbrev);
-
+	params['read_comments'] = toArray(read_comments);
 	params['pieces'] = toHash(cids ? fetch_comments_pieces : pieces_comments);
 
 	if (placeholder_comments.length) {
@@ -810,30 +854,18 @@
 			}
 
 			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_index = last_updated_comments.length - 1;
-
 				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] && comments[this_cid]['points'] >= -1) {
-						var mode = determineMode(this_cid);
+						var mode = determineMode(this_cid, null, null, null, (highlight > 1));
 						updateDisplayMode(this_cid, mode, 1);
 						currents[displaymode[this_cid]]++;
 						updateComment(this_cid, mode);
 					}
 
 					var this_id  = fetchEl('comment_top_' + this_cid);
-					if (this_id) {
-						this_id.className = this_id.className.replace(' oldcomment', ' newcomment');
+					if (this_id)
 						last_updated_comments.push(this_cid);
-					}
 				}
 
 				// later we may need to find a known point and scroll
@@ -843,6 +875,14 @@
 				//}
 			}
 
+			if (response.read_comments) {
+				for (var i = 0; i < response.read_comments.length; i++) {
+					var this_cid = response.read_comments[i];
+					// it has been updated now, ignore from now on
+					comments[this_cid]['read'] = 1;
+					delete read_comments[this_cid];
+				}
+			}
 			if (update && update.new_thresh_totals) {
 				for (var thresh in update.new_thresh_totals) {
 					for (var hthresh in update.new_thresh_totals[thresh]) {
@@ -851,34 +891,65 @@
 						}
 					}
 				}
-				$dom('titlecountnum').innerHTML = thresh_totals[6][6][1]; // total
+				$('#titlecountnum').html(thresh_totals[6][6][1]); // total
 				updateTotals();
 			}
 
 			updateHiddens(cids);
-			if (do_update && highlight && last_updated_comments.length) {
-				var next_cid = commTreeNextComm(0, 0, 1);
-				if (next_cid) {
+
+			ajaxCommentsStatus(0);
+
+			var next_cid_check = 0;
+			var next_cid_lower_thresh = 0;
+
+			if (highlight && last_updated_comments.length)
+				next_cid_check = 1;
+
+			if (!d2_comment_order)
+				next_cid_lower_thresh = 1;
+			else if (!do_update) {
+				next_cid_lower_thresh = 1;
+				if (highlight)
+					next_cid_check = 1;
+			}
+
+			if (next_cid_check) {
+				var next_cid = 0;
+
+				if (do_update)
+					next_cid = commTreeNextComm(0, 0, 1);
+
+//				while (next_cid_lower_thresh && !next_cid && currents['hidden'] > 0 && user_threshold > -1) {
+//					alert("No more visible comments; " + currents['hidden'] + " hidden comments.  Dropping threshold from " + user_threshold + " to " + (user_threshold - 1) + ".");
+//					user_threshold_save = 0;
+//					// if we are collapsing, then do not move HT too, so the comments stay closed
+//					changeT(-1, (highlight > 1));
+//					gCommentControlWidget.setTHT(user_threshold, user_highlightthresh);
+//					next_cid = commTreeNextComm(0, 0, 1);
+//				}
+
+				if (!next_cid && next_cid_lower_thresh)
+					reduceThresholdPrint(highlight);
+
+				else if (next_cid) {
 					if (highlight > 1)
 						setFocusComment('-' + current_cid, 1);
+					setFocusComment(next_cid, 1);
 					setCurrentComment(next_cid);
-					setFocusComment(next_cid, 1);
 				}
 			}
-			ajaxCommentsStatus(0);
 
 			if (adTimerInsert) {
-				var tree = $dom('tree_' + adTimerInsert);
-				if (tree) {
+				var tree = $('#tree_' + adTimerInsert);
+				if (tree.length) {
 					var adcall = '<iframe src="' + adTimerUrl + '" height="110" width="740" frameborder="0" border="0" scrolling="no" marginwidth="0" marginheight="0"></iframe>';
 					var html = '<li id="comment_ad_' + adTimerInsert + '" class="inlinead"> ' + adcall +'  </li>';
 
-					var commtree = $dom('commtree_' + adTimerInsert);
-					if (commtree) {
-						commtree.innerHTML = html + commtree.innerHTML;
-					} else {
-						tree.innerHTML = tree.innerHTML + '<ul id="commtree_' + adTimerInsert + '">' + html + '</ul>';
-					}
+					var commtree = $('#commtree_' + adTimerInsert);
+					if (commtree.length)
+						commtree.prepend(html);
+					else
+						tree.append('<ul id="commtree_' + adTimerInsert + '">' + html + '</ul>');
 					resetAdTimer();
 				}
 			}
@@ -886,7 +957,7 @@
 	};
 
 	ajaxCommentsStatus(1);
-	ajax_update(params, '', handlers);
+	ajax_update(params, '', handlers, options);
 
 	if (cids) {
 		for (var cid in fetch_comments_pieces) {
@@ -921,6 +992,8 @@
 function savePrefs() {
 	if (!user_is_anon
 		&&
+	    user_threshold_save
+		&&
 	    ((user_threshold_orig != user_threshold)
 		||
 	    (user_highlightthresh_orig != user_highlightthresh))
@@ -1078,7 +1151,19 @@
 			else if (cid) {
 				cancelReply(pid);
 				addComment(cid, { pid: pid, kids: [] }, '', 1);
+				setDefaultDisplayMode(cid);
+				// add it to the totals (for subtraction in updateComment())
+				currents[displaymode[cid]]++;
 				setFocusComment(cid, 1, 1);
+				var threshes = [-1,0,1,2,3,4,5,6];
+				for (var i = 0; i <= threshes.length; i++) {
+					var thresh = threshes[i];
+					for (var hthresh in thresh_totals[thresh]) {
+						var mode = determineMode(cid, thresh, hthresh);
+						thresh_totals[thresh][hthresh][ viewmodevalue[mode] ]++;
+					}
+				}
+				$('#titlecountnum').html(thresh_totals[6][6][1]); // total
 			}
 		}
 	});
@@ -1102,13 +1187,13 @@
 	});
 }
 
-function replyTo(pid) {
-	var replydiv = $dom('replyto_' + pid);
-	if (!replydiv)
+function replyTo(pid, nofocus) {
+	var replydiv = $('#replyto_' + pid);
+	if (!replydiv.length)
 		return false; // seems we shouldn't be here ...
 
-	var postercomment = $dom('postercomment_' + pid);
-	if (postercomment) {
+	var postercomment = $('#postercomment_' + pid);
+	if (postercomment.length) {
 		postercomment.focus(); // already have one, bail
 		return false;
 	}
@@ -1118,21 +1203,22 @@
 	params['pid'] = pid;
 	params['sid'] = discussion_id;
 
-	replydiv.innerHTML = '<span class="loading">Loading...</span>';
+	replydiv.html('<span class="loading">Loading...</span>');
 
 	var handlers = {
 		onComplete: function(transport) {
 			json_handler(transport);
 			if (pid) { // XXX
-				var reply_link = $dom('reply_link_' + pid);
+				var reply_link = $('#reply_link_' + pid);
 				// in some cases this won't exist; if not, fine, we
 				// just don't do it
-				if (reply_link) {
-					reply_link_html[pid] = reply_link.innerHTML;
-					reply_link.innerHTML = '<p><b><a href="#" onclick="cancelReply(' + pid + '); return false;">Cancel Reply</a></b></p>';
+				if (reply_link.length) {
+					reply_link_html[pid] = reply_link.html();
+					reply_link.html('<p><b><a href="#" onclick="cancelReply(' + pid + '); return false;">Cancel Reply</a></b></p>');
 				}
 			}
-			$dom('postercomment_' + pid).focus();
+			if (!nofocus)
+				$('#postercomment_' + pid).focus();
 		}
 	};
 
@@ -1147,11 +1233,8 @@
 		return;
 
 	var counter = submitCountdowns[pid];
-	if (counter) {
-		if (countSecs == counter['countSecs'])
-			return;
+	if (counter)
 		clearInterval(counter['counter']); // just in case
-	}
 
 	if (!countSecs || countSecs < 1) { // we're at 0, so let's go home
 		count.html('');
@@ -1454,7 +1537,7 @@
 		var oldpos = gd.style.position;
 
 		var mode = $dom('d2out').className;
-		if (mode=='horizontal rooted' || targetTop>vOffset) {
+		if (!user_d2asp && (mode=='horizontal rooted' || targetTop>vOffset)) {
 			gd.style.position = 'absolute';
 			gd.className      = 'rooted';
 			gd.style.top      = '0px';
@@ -1484,7 +1567,7 @@
 	gods.style.display = 'none';
 
 	// none -> ( vertical -> horizontal -> rooted )
-	if ( d2out.className == 'vertical' ) { // vertical->horizontal
+	if ( user_d2asp || d2out.className == 'vertical' ) { // vertical->horizontal
 		newMode = d2out.className = 'horizontal';
 		gCommentControlWidget.setOrientation('X');
 	} else if ( d2out.className == 'horizontal' ) { // horizontal->rooted
@@ -1527,7 +1610,7 @@
 
 	var num_a;
 	if (!num)
-		num_a = 'Check for more';
+		num_a = 'Get More Comments';
 	else {
 		if (num == 1)
 			num_a = 'Get 1 More Comment';
@@ -1931,24 +2014,46 @@
 		if (cid == current_cid)
 			return;
 
-		this_id = $('#comment_top_' + current_cid);
-		this_id.removeClass('newcomment');
-		this_id.addClass('oldcomment');
+		$('#comment_top_' + current_cid).removeClass('newcomment').addClass('oldcomment');
+		$('#comment_' + current_cid).removeClass('currcomment');
+		$('.current').remove();
 
-		this_id = $('#comment_' + current_cid);
-		this_id.removeClass('currcomment');
-		$('.current').remove();
+		setCommentRead(current_cid);
 	}
 
+	$('#comment_top_' + cid).removeClass('newcomment').addClass('oldcomment');
+	$('#comment_' + cid).addClass('currcomment').before('<span class="current">&rsaquo;</span>');
 
-	this_id = $('#comment_' + cid);
-	this_id.addClass('currcomment');
-	this_id.before('<span class="current">&rsaquo;</span>');
+	setCommentRead(cid);
 
 	current_cid = cid;
 }
 
+function setCommentRead (cid) {
+	if (!comments[cid]['read']
+		&& !read_comments[cid]
+		&& $('#comment_otherdetails_' + cid).length
+		&& !noSeeFirstComment(cid)
+	) {
+		// this happens later for logged-in users
+		if (user_is_anon)
+			comments[cid]['read'] = 1;
+		else
+			read_comments[cid] = 1;
+	}
+}
 
+function updateReadComments () {
+	for (var cid in read_comments) {
+		ajaxFetchComments(0, 2, '', 1); // if we have at least one, do it
+		break;
+	}
+}
+
+$(window).bind('beforeunload', updateReadComments);
+
+
+
 /* keys
 prev comment: A, H
 next comment: D, L
@@ -2028,6 +2133,8 @@
 			if (!k)
 				doModifiers(e);
 			var collapseCurrent = shift_down;
+			if (d2_reverse_shift)
+				collapseCurrent = !collapseCurrent;
 			var getNextUnread   = ctrl_down; // not working right, and interfering anyway -- pudge
 			var skipit = 0;
 			if (meta_down || alt_down || ctrl_down)
@@ -2039,7 +2146,10 @@
 
 			var update = 0;
 			var next_cid = 0;
-			var key = k || validkeys[c] ? c : String.fromCharCode(c);
+			var key = k || (validkeys[c] ? c : String.fromCharCode(c));
+			if (d2_keybindings_disable[key])
+				return;
+
 			var keyo = validkeys[key];
 			if (keyo) {
 				if (keyo['toggle']) {
@@ -2059,7 +2169,11 @@
 
 					} else if (keyo['parent']) {
 						if (current_cid && comments[current_cid] && comments[current_cid]['pid'])
-							selectParent(comments[current_cid]['opid'] || comments[current_cid]['pid']);
+							next_cid =
+								comments[current_cid]['opid']
+									||
+								comments[current_cid]['pid'];
+							update = 1;
 					}
 
 
@@ -2123,11 +2237,11 @@
 				else if (keyo['thread']) {
 					update = 1;
 					if (keyo['next']) {
-						if (noSeeFirstComment(current_cid))
+						if (keyo['unread'])
+							getNextUnread = 1;
+						if (current_cid && noSeeFirstComment(current_cid, getNextUnread))
 							next_cid = current_cid;
 						else {
-							if (keyo['unread'])
-								getNextUnread = 1;
 							if (keyo['comment']) {
 								next_cid = commTreeNextComm(current_cid, 0, getNextUnread);
 								if (!next_cid) { // && getNextUnread) {
@@ -2162,17 +2276,18 @@
 }
 
 // at first comment, and comment is not in window OR comment is not full
-function noSeeFirstComment (cid) {
+function noSeeFirstComment (cid, getNextUnread) {
 	setDefaultDisplayMode(cid);
 	if (!comments_started && (!commentIsInWindow(cid) || (viewmodevalue[displaymode[cid]] < viewmodevalue['full']))) {
-		return 1;
+		if (!getNextUnread || isUnread(cid))
+			return 1;
 	}
 	return 0;
 }
 
 // XXX somehow sync this with the prev/next by load order?  might require
 // a quick grep to find the position
-function commTreeNextComm (cid, old_cid, getNextUnread) {
+function commTreeNextComm (cid, old_cid, getNextUnread, no_parent) {
 	var kids;
 	if (cid)
 		kids = sortKids(cid);
@@ -2190,13 +2305,31 @@
 		}
 
 		if (this_cid) {
-			if (!getNextUnread || (this_cid = getNextUnreadCid(this_cid)))
+			if (!getNextUnread) {
+				setDefaultDisplayMode(this_cid);
+				if (displaymode[this_cid] == 'hidden' || comments[this_cid]['points'] <= -2) {
+					// try to dig deeper to find non-hidden
+					// if available
+					if (comments[this_cid].kids.length) {
+						var this_child = commTreeNextComm(
+							this_cid,
+							0,
+							getNextUnread,
+							1
+						);
+						if (this_child)
+							return this_child;
+					}
+				} else
+					return this_cid;
+			} else if (this_cid = getNextUnreadCid(this_cid))
 				return this_cid;
-			continue;
 		}
 	}
 
-	if (!cid)
+	// no_parent is if we are doing the "dig deeper" for non-hiddens
+	// we don't want to climb back out
+	if (!cid || no_parent)
 		return 0; // at the end, stay where we are
 
 	// we can't continue here, go back up a level
@@ -2228,8 +2361,12 @@
 }
 
 function commTreePrevComm (cid, to_parent) {
+	if (!cid)
+		return;
 	var root_kids = rootSort();
 	var comm = comments[cid];
+	if (!comm)
+		return;
 	var pid = comm.pid;
 
 	if (to_parent == 1) {
@@ -2266,15 +2403,37 @@
 }
 
 function isUnread(cid) {
-	var this_id  = fetchEl('comment_top_' + cid);
-	if (this_id)
-		if (this_id.className.match(' newcomment'))
-			return 1;
-		else
-			return 0;
+	// XXX should we loook at read_comments[cid],
+	// not just comments[cid]['read'] ?  -- pudge
+	setDefaultDisplayMode(cid);
+	// skip if hidden, or a placeholder (-2)
+	if (
+		(
+			(displaymode[cid] != 'hidden')
+				&&
+			(
+				(parseInt(comments[cid]['read']) == 0)
+					&&
+				!read_comments[cid]
+			)
+				&&
+			(comments[cid]['points'] > -2)
+		)
+	) {
+		return 1;
+	} else if (parseInt(comments[cid]['read']) == 1) {
+		// sometimes things happen in the wrong order, and
+		// a comment was not fully rendered when it was set
+		// to read, so clean up here just in case; this is a
+		// good place to do it, because this is where we might
+		// be confused if we are going to the next unread
+		// comment, but it is already read, but looks like
+		// it is not -- pudge
+		$('#comment_top_' + cid).removeClass('newcomment').addClass('oldcomment');
+		return 0;
+	}
 }
 
-// XXX should we climb all the way back up the tree if we find nothing?
 function getNextUnreadCid(cid) {
 	if (isUnread(cid))
 		return cid;
@@ -2311,3 +2470,65 @@
 
 	return(html.replace(/\-\-CID\-\-/g, cid));
 }
+
+function reduceThreshold(highlight, no_save) {
+	if (highlight < 0) {
+		hide_modal_box();
+		no_lower_threshold = 1;
+		return;
+	}
+
+	if (no_save)
+		user_threshold_save = 0;
+
+	hide_modal_box();
+	$('#modal_box_content').html('');
+
+	// this could trigger a comment load, which could interfere with the
+	// comment load on setFocusComment if they return in the wrong order
+	async_off = 1;
+
+	// if we are collapsing, then do not move HT too, so the comments stay closed
+	changeT(-1, (highlight > 1), 'hidden');
+	gCommentControlWidget.setTHT(user_threshold, user_highlightthresh);
+	async_off = 0;
+
+	var next_cid = commTreeNextComm(0, 0, 1);
+	if (!next_cid)
+		return;
+	if (highlight)
+		setFocusComment('-' + current_cid, 1);
+	setFocusComment(next_cid, 1);
+	setCurrentComment(next_cid);
+}
+
+function reduceThresholdPrint(highlight) {
+	if (currents['hidden'] <= 0 || user_threshold <= -1 || no_lower_threshold)
+		return;
+
+	$('#preference_title').html('No More Comments At This Threshold');
+	show_modal_box();
+
+	var html = '<div>\
+<p>There are no more comments available at Score:--SCORE--, but there might be more at Score:--SCORE1--.</p><p>Would you like to lower your threshold for \
+<input type="button" value="this" onclick="reduceThreshold(--HIGHLIGHT--,1)"> ';
+	if (!user_is_anon)
+		html = html + '<input type="button" value="all"  onclick="reduceThreshold(--HIGHLIGHT--)"> ';
+	html = html + 'discussion(s)?<br>\
+<input type="button" value="No Thanks" onclick="reduceThreshold(-1)">\
+</p>\
+\
+<p><i>(Remember that you can always adjust these controls with the slider widget \
+visible to the --LEFTORTOP-- of the discussion.)</i></p>\
+</div>';
+
+	html = html.replace(/\-\-SCORE\-\-/g, user_threshold);
+	html = html.replace(/\-\-SCORE1\-\-/g, (user_threshold-1));
+	html = html.replace(/\-\-HIGHLIGHT\-\-/g, highlight);
+
+	var leftortop = $('#d2out').hasClass('horizontal') ? 'top' : 'left';
+	html = html.replace(/\-\-LEFTORTOP\-\-/g, leftortop);
+
+	$('#modal_box_content').html(html);
+}
+

Modified: slashjp/trunk/themes/slashcode/htdocs/images/dumper.js
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/images/dumper.js	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/images/dumper.js	2008-09-09 13:07:58 UTC (rev 742)
@@ -1,4 +1,4 @@
-// $Id: dumper.js,v 1.2 2006/05/26 22:51:36 pudge Exp $
+// $Id$
 
 // javascript:$dom('commentControlBox').innerHTML = Dumper(displaymode)
 

Copied: slashjp/trunk/themes/slashcode/htdocs/images/spinner_grey.gif (from rev 741, slashjp/branches/upstream/2.5.0.218/themes/slashcode/htdocs/images/spinner_grey.gif)
===================================================================
(Binary files differ)


Property changes on: slashjp/trunk/themes/slashcode/htdocs/slashguide.shtml
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/themes/slashcode/htdocs/users.pl
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/users.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/users.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -1838,7 +1838,7 @@
 			$story023_default{nexus}{$tid} = 3;
 		} elsif ($prefs{story_full_best_nexus}{$tid}) {
 			$story023_default{nexus}{$tid} = 2;
-		} elsif ($prefs{story_brief_best_nexus}) {
+		} elsif ($prefs{story_brief_best_nexus}{$tid}) {
 			$story023_default{nexus}{$tid} = 1;
 		} else {
 			# If brief_sectional_mainpage is set, then all

Modified: slashjp/trunk/themes/slashcode/htdocs/users2.pl
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/users2.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/htdocs/users2.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: users2.pl,v 1.1 2008/04/02 14:38:23 entweichen Exp $
+# $Id$
 
 use strict;
 use Digest::MD5 'md5_hex';
@@ -1363,6 +1363,7 @@
 			$tagshist = $tags_reader->getAllTagsFromUser($requested_user->{uid}, { orderby => 'created_at', orderdir => 'DESC', limit => 30, include_private => 1 });
 		}
 
+                # Latest comments
                 my $comment_blocks = $reader->sqlSelectAllHashref(
                         'uid', 'bid, uid, block', 'user_event_blocks', "uid = $uid and code = 1");
 
@@ -1372,49 +1373,58 @@
                 foreach my $comment_block (@block_ids) {
                         ($latest_comments{$comment_block}->{sid}, $latest_comments{$comment_block}->{subject})
                                 = $reader->sqlSelect("sid, subject", "comments", "cid = $comment_block");
-                        #$latest_comments{$comment_block}->{text} = $reader->sqlSelect("comment", "comment_text", "cid = $comment_block");
                 }
 
+                # Latest journals
                 my $journal_blocks = $reader->sqlSelectAllHashref(
                         'uid', 'bid, uid, block', 'user_event_blocks', "uid = $uid and code = 2");
 
                 @block_ids = split(/,/, $journal_blocks->{$uid}->{block});
+
                 my %latest_journals;
                 foreach my $journal_block (@block_ids) {
                         ($latest_journals{$journal_block}->{id}, $latest_journals{$journal_block}->{desc})
                                 = $reader->sqlSelect("id, description", "journals", "discussion = $journal_block");
                 }
 
+                # Latest submissions
+                my $submissions_blocks = $reader->sqlSelectAllHashref(
+                        'uid', 'bid, uid, block', 'user_event_blocks', "uid = $uid and code = 3");
+
+                @block_ids = split(/,/, $submissions_blocks->{$uid}->{block});
+
+                my %latest_submissions;
+                foreach my $submission_block (@block_ids) {
+                        ($latest_submissions{$submission_block}->{id}, $latest_submissions{$submission_block}->{title})
+                                = $reader->sqlSelect("id, title", "firehose_text", "id = $submission_block");
+                }
+
                 # Latest event
                 my @latest_event_index = $reader->sqlSelect("event, code", "user_events", "uid = $uid", "order by date desc limit 1");
 
-                my ($root_table, $text_table, $event_subject, $event_text, $event_rkey, $event_tkey);
+                my $latest_event;
+                if ($latest_event_index[1] == 1) {
+                        ($latest_event->{key}, $latest_event->{subject}) =
+                                $reader->sqlSelect("cid, subject", "comments", "uid = $uid and cid = " . $latest_event_index[0]);
 
-                if ($latest_event_index[1] == 1) {
-                        $root_table    = 'comments';
-                        $text_table    = 'comment_text';
-                        $event_subject = 'subject';
-                        $event_text    = 'comment';
-                        $event_rkey    = 'cid';
-                        $event_tkey    = 'cid';
+                        $latest_event->{text} =
+                                $reader->sqlSelect("comment, comment_text", "id = " . $latest_event->{key});
+                } elsif ($latest_event_index[1] == 2) {
+                        ($latest_event->{key}, $latest_event->{subject}) =
+                                $reader->sqlSelect("id, description", "journals", "uid = $uid and discussion = " . $latest_event_index[0]);
+
+                        $latest_event->{text} =
+                                $reader->sqlSelect("article", "journals_text", "id = " . $latest_event->{key});
                 } else {
-                        $root_table    = 'journals';
-                        $text_table    = 'journals_text';
-                        $event_subject = 'description';
-                        $event_text    = 'article';
-                        $event_rkey    = 'discussion';
-                        $event_tkey    = 'id';
+                        ($latest_event->{key}, $latest_event->{subject}) =
+                                $reader->sqlSelect("id, title", "firehose_text", "id = " . $latest_event_index[0]);
+
+                        $latest_event->{text} =
+                                $reader->sqlSelect("introtext", "firehose_text", "id = " . $latest_event->{key});
                 }
 
-                my $latest_event;
-                ($latest_event->{key}, $latest_event->{subject}) =
-                        $reader->sqlSelect("$event_tkey, $event_subject", "$root_table", "uid = $uid and $event_rkey = " . $latest_event_index[0]);
+                $latest_event->{code} = $latest_event_index[1];                
 
-                $latest_event->{text} =
-                        $reader->sqlSelect($event_text, $text_table, "$event_tkey = " . $latest_event->{key});
-
-                $latest_event->{code} = $latest_event_index[1];
-
 		slashDisplay('userInfo2', {
 			title			=> $title,
 			uid			=> $uid,
@@ -1439,7 +1449,9 @@
 			tagshist		=> $tagshist,
                         latest_comments         => \%latest_comments,
                         latest_journals         => \%latest_journals,
+                        latest_submissions      => \%latest_submissions,
                         latest_event            => $latest_event,
+                        data_pane               => $form->{dp},
 		}, { Page => 'users', Skin => 'default'});
 	}
 
@@ -1852,7 +1864,7 @@
 			$story023_default{nexus}{$tid} = 3;
 		} elsif ($prefs{story_full_best_nexus}{$tid}) {
 			$story023_default{nexus}{$tid} = 2;
-		} elsif ($prefs{story_brief_best_nexus}) {
+		} elsif ($prefs{story_brief_best_nexus}{$tid}) {
 			$story023_default{nexus}{$tid} = 1;
 		} else {
 			# If brief_sectional_mainpage is set, then all

Modified: slashjp/trunk/themes/slashcode/tasks/delete_accesslog.pl
===================================================================
--- slashjp/trunk/themes/slashcode/tasks/delete_accesslog.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/tasks/delete_accesslog.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -20,7 +20,7 @@
 $task{$me}{timespec} = '22 * * * *'; # Normally run once an hour
 $task{$me}{timespec_panic_1} = '20 1,2,3,4,5,6 * * *'; # Just run at night if an issue pops up
 $task{$me}{timespec_panic_2} = ''; # In a pinch don't do anything
-$task{$me}{resource_locks} = { logdb => 1 };
+$task{$me}{resource_locks} = { logdb => 1, log_slave => 1 };
 $task{$me}{fork} = SLASHD_NOWAIT;
 $task{$me}{code} = sub {
 	my($virtual_user, $constants, $slashdb, $user) = @_;
@@ -37,6 +37,13 @@
 		return "nothing to do";
 	}
 
+	# If the log master is ENGINE=BLACKHOLE, we can't delete from there;
+	# delete from the log slave instead.
+	my $delete_db = $logdb;
+	if (! $logdb->sqlSelect('id', 'accesslog', "id=$id")) {
+		$delete_db = $log_slave;
+	}
+
 	my $rows;
 	my $total = 0;
 	my $limit = 100_000;
@@ -44,14 +51,14 @@
 	my $last_err = "";
 	my $done = 0;
 	MAINLOOP: while (!$done) {
-		while ($rows = $logdb->sqlDelete("accesslog", "id < $id", $limit)) {
+		while ($rows = $delete_db->sqlDelete("accesslog", "id < $id", $limit)) {
 			$total += $rows;
 			last if $rows eq "0E0";
 			slashdLog("deleted so far $total of $limit rows");
 			sleep 10;
 		}
 		my $err = "";
-		if ( $counter >= $failures || !($err = $logdb->sqlError()) ) {
+		if ( $counter >= $failures || !($err = $delete_db->sqlError()) ) {
 			# If either we're giving up because there are too many
 			# failures, or the last attempt was successful, then
 			# break out of the loop, we're done.

Modified: slashjp/trunk/themes/slashcode/tasks/im_messages.pl
===================================================================
--- slashjp/trunk/themes/slashcode/tasks/im_messages.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/tasks/im_messages.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: $
+# $Id$
 
 use strict;
 

Modified: slashjp/trunk/themes/slashcode/tasks/process_file_queue.pl
===================================================================
--- slashjp/trunk/themes/slashcode/tasks/process_file_queue.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/tasks/process_file_queue.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: process_file_queue.pl,v 1.1 2007/10/16 22:59:52 tvroom Exp $
+# $Id$
 
 use File::Path;
 use File::Temp;
@@ -21,7 +21,11 @@
 $task{$me}{fork} = SLASHD_NOWAIT;
 $task{$me}{code} = sub {
 	my($virtual_user, $constants, $slashdb, $user, $info, $gSkin) = @_;
-	
+
+	if (!$constants->{imagemagick_convert}) {
+		slashdLog("no imagemagick convert location specified, exiting");
+	}
+
 	my $file_queue_cmds = [];
 	my $cmd;
 	while (!$task_exit_flag) {
@@ -46,6 +50,9 @@
 sub handleFileCmd {
 	my($cmd) = @_;
 	my $slashdb = getCurrentDB();
+	my $constants = getCurrentStatic();
+	my $convert = $constants->{imagemagick_convert};
+
 	if ($cmd->{action} eq "thumbnails") {
 		slashdLog("Creating Thumbnails");
 		my $files = uploadFile($cmd);
@@ -57,8 +64,14 @@
 			my ($namebase, $suffix) = $name =~ /^(\w+\-\d+)\.(\w+)$/;
 			my $thumb = $namebase . "-thumb." . $suffix;
 			my $thumbsm = $namebase . "-thumbsm." . $suffix;
+			my $thumblg = $namebase . "-thumblg." . $suffix;
+
 			slashdLog("About to create thumb $path$thumb");
-			system("/usr/bin/convert -size 260x194  $path$name  -resize '130x97>'  -bordercolor transparent  -border 48 -gravity center -crop 130x97+0+0 -page +0+0 $path$thumb");
+			system("$convert -size 260x194  $path$name  -resize '130x97>'  -bordercolor transparent  -border 48 -gravity center -crop 130x97+0+0 -page +0+0 -colors 256 -depth 8 -compress BZip $path$thumb");
+
+			if ($constants->{optipng} && $suffix eq "png") {
+				system("$constants->{optipng} -q $path$thumb");
+			}
 			my $data = {
 				stoid => $cmd->{stoid} || 0,
 				fhid  => $cmd->{fhid} || 0 ,
@@ -74,13 +87,28 @@
 			}
 
 			slashdLog("About to create thumbsms $path$thumbsm");
-			system("/usr/bin/convert -size 100x74 $path$name  -resize '50x37>'  -bordercolor transparent -border 18 -gravity center -crop 50x37+0+0 -page +0+0 $path$thumbsm");
+			system("$convert -size 100x74 $path$name  -resize '50x37>'  -bordercolor transparent -border 18 -gravity center -crop 50x37+0+0 -page +0+0 -colors 256 -depth 8 -compress BZip $path$thumbsm");
 			$data = {
 				stoid => $cmd->{stoid} || 0,
 				fhid  => $cmd->{fhid} || 0,
 				name => "$path$thumbsm"
 			};
+			if ($constants->{optipng} && $suffix eq "png") {
+				system("$constants->{optipng} -q $path$thumbsm");
+			}
 			addFile($data);
+
+			slashdLog("About to create thumblg $path$thumblg");
+			system("$convert $path$name  -resize '309x250>' -colors 256 -depth 8 -compress BZip $path$thumblg");
+			if ($constants->{optipng} && $suffix eq "png") {
+				system("$constants->{optipng} -q $path$thumblg");
+			}
+			$data = {
+				stoid => $cmd->{stoid} || 0,
+				fhid  => $cmd->{fhid} || 0,
+				name => "$path$thumblg"
+			};
+			addFile($data);
 		}
 	}
 	if ($cmd->{action} eq "upload") {
@@ -141,6 +169,9 @@
 	my($cmd) = @_;
 	my @suffixlist = ();
 	my $slashdb = getCurrentDB();
+	my $constants = getCurrentStatic();
+	my $convert = $constants->{imagemagick_convert};
+
 	my $story = $slashdb->getStory($cmd->{stoid});
 	my @files;
 
@@ -148,8 +179,13 @@
 	if ($file =~ /\.(gif|jpg)$/i) {
 		my $filepng = $file;
 		$filepng =~s /\.(gif|jpg)$/\.png/;
-		system("/usr/bin/convert $file $filepng");
+		if ($convert) {
+			system("$convert $file $filepng");
+		}
 		$file = $filepng;
+		if ($constants->{optipng}) {
+			system("$constants->{optipng} -q $filepng");
+		}
 	}
 
 	if ($story->{sid}) {

Modified: slashjp/trunk/themes/slashcode/tasks/rotate_semirandom_block.pl
===================================================================
--- slashjp/trunk/themes/slashcode/tasks/rotate_semirandom_block.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/tasks/rotate_semirandom_block.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -2,7 +2,7 @@
 # This code is a part of Slash, and is released under the GPL.
 # Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: rotate_semirandom_block.pl,v 1.1 2008/01/24 17:25:16 entweichen Exp $
+# $Id$
 
 use strict;
 
@@ -17,7 +17,7 @@
 
         my($virtual_user, $constants, $slashdb, $user) = @_;
         
-        my @choices = qw/askslashdot developers interview science yro firehose topcomments books activetags/;
+        my @choices = qw/askslashdot developers interview science yro firehose topcomments books activetags idle_pics idle_video/;
         my $choice;
         my $lastchoice = $slashdb->getVar('lastsrandsec', 'value', 1);
        
@@ -32,10 +32,12 @@
         if ($choice eq 'interview')   { $title = 'Interviews'; }
         if ($choice eq 'bsd')         { $title = 'BSD'; }
         if ($choice eq 'yro')         { $title = 'YRO'; }
-        if ($choice eq 'firehose')    { $title = 'Firehose'; $url = "http://slashdot.org/firehose/" }
+        if ($choice eq 'firehose')    { $title = 'Firehose'; $url = "//slashdot.org/firehose/" }
         if ($choice eq 'topcomments') { $title = 'Hot Comments'; $url = '' }
         if ($choice eq 'books')       { $title = 'Book Reviews'; }
         if ($choice eq 'activetags')  { $title = 'Recent Tags'; $url = "/tags" }
+        if ($choice eq 'idle_video')  { $title = 'Idle Video'; $url = "//idle.slashdot.org" }
+        if ($choice eq 'idle_pics')  { $title = 'Idle Pics'; $url = "//idle.slashdot.org" }
 
         $slashdb->sqlUpdate("blocks",{ block=>$slashdb->getBlock($choice, 'block'), title=>$title, url=> $url }, "bid='srandblock'");
         

Modified: slashjp/trunk/themes/slashcode/tasks/url_checker.pl
===================================================================
--- slashjp/trunk/themes/slashcode/tasks/url_checker.pl	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/tasks/url_checker.pl	2008-09-09 13:07:58 UTC (rev 742)
@@ -8,9 +8,9 @@
 # validated titles
 #
 use Slash::Constants ':slashd';
-use LWP::UserAgent;
+use LWP::Parallel::UserAgent;
+use HTTP::Request;
 use Encode 'encode_utf8';
-use HTML::HeadParser;
 
 use strict;
 
@@ -23,20 +23,30 @@
 $task{$me}{fork} = SLASHD_NOWAIT;
 $task{$me}{code} = sub {
 	my($virtual_user, $constants, $slashdb, $user, $info, $gSkin) = @_;
+	my $reader = getObject("Slash::DB", { type => 'reader'});
 
+	my $fresh_until_min = 86400 * 30;
 	my $start_time = time();
-	my $timeout = 60;
 
 	my $ua = LWP::UserAgent->new;
 	$ua->agent($constants->{url_checker_user_agent}) if $constants->{url_checker_user_agent};
-	$ua->timeout(30);
+	my $timeout = 60;
+	$ua->timeout(20);
 
-	my $urls = $slashdb->getUrlsNeedingFirstCheck();
+	my $urls = $reader->getUrlsNeedingFirstCheck({ limit_to_firehose => 1 });
+	my $refresh_urls = $reader->getUrlsNeedingRefresh();
 
-	my $refresh_urls = $slashdb->getUrlsNeedingRefresh();
+	my $urls_hr;
 
-	URL_CHECK: for my $url (@$urls, @$refresh_urls) {
-		
+	my @all_urls = (@$urls, @$refresh_urls);
+
+	foreach (@all_urls) {
+		$urls_hr->{$_->{url}} = $_;
+	}
+
+	URL_CHECK: while (@all_urls) {
+		my @set = splice(@all_urls, 0, 5);
+
 		# Don't run forever...
 		if (time > $start_time + $timeout) {
 			slashdLog("Aborting checking urls, too much elapsed time");
@@ -46,55 +56,57 @@
 			slashdLog("Aborting url_checker, got SIGUSR1");
 			last URL_CHECK;
 		}
-		
 
-		my $url_update = { url_id => $url->{url_id} };
-	
-		my $response = $ua->get($url->{url});
-		#slashdLog("getting $url->{url}");	
-		if ($response->is_success) {
-			#slashdLog("success on $url->{url}");	
-			my $content =  $response->content;
-			my $hp = HTML::HeadParser->new;
-			{
-				local $SIG{__WARN__} = sub {
-					warn @_ unless $_[0] =~
-					/Parsing of undecoded UTF-8 will give garbage when decoding entities/
-				};
-				$hp->parse(encode_utf8($content));
+		my $ua = LWP::Parallel::UserAgent->new();
+		$ua->duplicates(0);
+		$ua->timeout   (15);
+		$ua->redirect  (1);
+
+		foreach (@set) {
+			my $req = HTTP::Request->new("GET", $_->{url});
+			$slashdb->setUrl($_->{url_id}, { '-last_attempt' => 'NOW()' });
+			$ua->register($req);
+		}
+		my $entries = $ua->wait();
+		foreach (keys %$entries) {
+			my $res = $entries->{$_}->response;
+			while (defined $res->previous) {
+				$res = $res->previous;
 			}
-			my $validatedtitle = $hp->header('Title');
-			if (defined $validatedtitle) {
-				#slashdLog("vt $validatedtitle");	
-				$url_update->{validatedtitle} = strip_notags($validatedtitle);
-				$url_update->{"-last_success"} = "NOW()";
-				$url_update->{is_success} = 1;
-				$url_update->{"-believed_fresh_until"} = "DATE_ADD(NOW(), INTERVAL 2 DAY)";
+			my $url = $res->request->url;
+			
+			my $item = $urls_hr->{"$url"};
+			
+			my $url_update = { url_id => $item->{url_id} };
+
+			if ($res->is_success) {
+				my $validatedtitle = $res->title;
+				if (defined $validatedtitle) {
+					$url_update->{validatedtitle} = strip_notags($validatedtitle);
+					$url_update->{"-last_success"} = "NOW()";
+					$url_update->{is_success} = 1;
+					$url_update->{"-believed_fresh_until"} = "DATE_ADD(NOW(), INTERVAL 2 DAY)";
+				}
+			} else {
+				$url_update->{is_success} = 0;
+				$url_update->{"-believed_fresh_until"} = "DATE_ADD(NOW(), INTERVAL 30 MINUTE)";
 			}
-		} else {
-			#slashdLog("failure on $url->{url}");	
-			$url_update->{is_success} = 0;
-			$url_update->{"-believed_fresh_until"} = "DATE_ADD(NOW(), INTERVAL 30 MINUTE)";
-		}
+			# If this is a second or greater, we adjust the amount of time between refreshes to slowly increase
+			# time between refreshes
+			if ($item->{last_attempt} && $res->is_success) {
+				my $secs = $slashdb->sqlSelect("UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP('$item->{last_attempt}')");
+				$secs = $fresh_until_min if !$secs || $secs < $fresh_until_min;
+				my $decay = 1.2;
+				my $secs_until_next = int($secs * $decay);
+				$url_update->{"-believed_fresh_until"} = "DATE_ADD(NOW(), INTERVAL $secs_until_next SECOND)";
+			}
 
-		# If this is a second or greater, we adjust the amount of time between refreshes to slowly increase
-		# time between refreshes
-		if ($url->{last_attempt}) {
-			my $secs = $slashdb->sqlSelect("UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP('$url->{last_attempt}')");
-			my $decay = 1.2;
-			my $secs_until_next = int($secs * $decay);
-			$url_update->{"-believed_fresh_until"} = "DATE_ADD(NOW(), INTERVAL $secs_until_next SECOND)";
+			$url_update->{status_code} = $res->code;
+			$url_update->{reason_phrase} = $res->status_line;
+			$url_update->{"-last_attempt"} = "NOW()";
+			$slashdb->setUrl($item->{url_id}, $url_update);
 		}
 
-		my $status_line = $response->status_line;
-		my ($code, $reason) = $status_line =~ /^(\d+)\s+(.*)$/;
-
-		$url_update->{status_code} = $code;
-		$url_update->{reason_phrase} = $reason;
-		$url_update->{"-last_attempt"} = "NOW()";
-
-
-		$slashdb->setUrl($url->{url_id}, $url_update);
 	}
 };
 

Modified: slashjp/trunk/themes/slashcode/templates/autocomplete;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/autocomplete;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/autocomplete;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -18,4 +18,4 @@
 __seclev__
 10000
 __version__
-$Id: $
+$Id$


Property changes on: slashjp/trunk/themes/slashcode/templates/bannedtext_rss;misc;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/themes/slashcode/templates/dispComment;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/dispComment;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/dispComment;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -27,7 +27,7 @@
 <div id="comment_status_[% cid %]" class="commentstatus"></div>
 <div id="comment_[% cid %]"[% IF discussion2 %] class="[% class %]"[% END %]>
 [% END; IF !options.noshow %]
-	<div id="comment_top_[% cid %]" class="commentTop newcomment">
+	<div id="comment_top_[% cid %]" class="commentTop [% has_read ? 'oldcomment' : '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>

Modified: slashjp/trunk/themes/slashcode/templates/dispCommentDetails;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/dispCommentDetails;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/dispCommentDetails;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -41,4 +41,4 @@
 __seclev__
 10000
 __version__
-$Id: $
+$Id$

Modified: slashjp/trunk/themes/slashcode/templates/edit_comment;comments;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/edit_comment;comments;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/edit_comment;comments;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -20,10 +20,11 @@
 edit_comment
 __template__
 <div id="wide">
+[% discussion2 = Slash.discussion2() %]
 [% IF form.pid %]
         [% PROCESS titlebar title="Reply to: $reply.subject" %]
         <div class="generalbody">
-		<ul id="commentlisting">
+		<ul id="commentlisting" class="[% discussion2 ? 'd2' : 'd1' %]">
                 [% Slash.dispComment(reply) %]
 		</li>
 		</ul>
@@ -129,7 +130,7 @@
 		<a href="[% gSkin.rootdir %]/users.pl">Create an Account!</a>
 		[% END %]
 
-[% IF !user.is_anon && user.discussion2 && user.discussion2 == "slashdot";
+[% IF !user.is_anon && discussion2;
         prefslink = "<a href=\"" _ gSkin.rootdir _ "/my/comments\" target=\"_blank\"";
 
         IF constants.modal_prefs_active;
@@ -184,7 +185,7 @@
 	[% IF !user.is_anon || (user.is_anon && preview) %]
 	<input type="submit" name="op" value="Submit" class="button">
 	[% END %]
-	[% IF form.pid && Slash.discussion2() == "slashdot" %]
+	[% IF form.pid && discussion2 %]
 	<script src="[% constants.imagedir %]/comments.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 	<script type="text/javascript">
 <!--

Modified: slashjp/trunk/themes/slashcode/templates/firehose_related;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/firehose_related;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/firehose_related;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -17,4 +17,4 @@
 	<span class="storytitle"><a href="[% rootdir %]/firehose.pl?id=[% fh_item.id %]&amp;op=view">Firehose:[% fh_item.title %]</a></span> by [% IF !is_anon %]<a href="[% constants.real_rootdir %]/~[% fh_user.nickname | strip_paramattr %]">[% END %][% fh_user.nickname | strip_literal%][% IF !is_anon %] ([% fh_user.uid %])</a>[% END %]
 </div>
 __version__
-$Id: $
+$Id$


Property changes on: slashjp/trunk/themes/slashcode/templates/formbox;misc;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/themes/slashcode/templates/help_anon;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/help_anon;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/help_anon;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -39,4 +39,4 @@
 __seclev__
 500
 __version__
-$Id: help_anon;misc;default,v 1.1 2008/02/12 21:45:30 entweichen Exp $
+$Id$

Modified: slashjp/trunk/themes/slashcode/templates/help_main;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/help_main;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/help_main;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -115,4 +115,4 @@
 __seclev__
 500
 __version__
-$Id: help_main;misc;default,v 1.2 2008/02/20 16:57:19 entweichen Exp $
+$Id$

Modified: slashjp/trunk/themes/slashcode/templates/html-header;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/html-header;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/html-header;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -28,13 +28,20 @@
 [% IF file.ie_cond %]<!--[if [% file.ie_cond %]]>[% END %]<link rel="[% file.rel %]" type="[% file.type %]" media="[% file.media %]" href="[% IF constants.css_use_imagedir; constants.imagedir; ELSE; constants.rootdir; END %]/[% file.file %]?[% constants.cvs_tag_currentcode %]"[% IF file.title %] title="[% file.title %]"[% END %]>[% IF file.ie_cond %]<![endif]-->[% END %]
 [% END -%]
 [%- IF constants.plugin.Ajax %]
-<script src="[% constants.imagedir %]/jquery-1.2.3.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
+<script src="[% constants.imagedir %]/jquery/jquery-1.2.6.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
+<script src="[% constants.imagedir %]/jquery/jquery.metadata.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
+<script src="[% constants.imagedir %]/jquery/jquery.slashdot.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 <script src="[% constants.imagedir %]/yui/yahoo.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 <script src="[% constants.imagedir %]/yui/dom.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 <script src="[% constants.imagedir %]/yui/event.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 <script src="[% constants.imagedir %]/yui/dragdrop.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 <script src="[% constants.imagedir %]/yui/animation.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 [% IF user.currentPage == "firehose" || user.currentPage == "console" -%]
+<script src="[% constants.imagedir %]/jquery/ui.core.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
+<script src="[% constants.imagedir %]/jquery/ui.sortable.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
+<script src="[% constants.imagedir %]/jquery/jquery.textselection.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
+<script src="[% constants.imagedir %]/jquery/jquery.autocomplete.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
+<script src="[% constants.imagedir %]/tagui.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 <script src="[% constants.imagedir %]/yui/slider.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
 [% END -%]
 <script src="[% constants.imagedir %]/yui/connection.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>


Property changes on: slashjp/trunk/themes/slashcode/templates/linkrel;misc;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/themes/slashcode/templates/newdiscussion;comments;default
___________________________________________________________________
Name: svn:executable
   - *


Property changes on: slashjp/trunk/themes/slashcode/templates/pagination;comments;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/themes/slashcode/templates/preview_comm;comments;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/preview_comm;comments;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/preview_comm;comments;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -13,7 +13,7 @@
 __name__
 preview_comm
 __template__
-<ul id="commentlisting">
+<ul id="commentlisting" class="[% Slash.discussion2() ? 'd2' : 'd1' %]">
 [% Slash.dispComment(preview) %]
 </li>
 </ul>

Modified: slashjp/trunk/themes/slashcode/templates/printCommComments;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/printCommComments;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/printCommComments;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -38,11 +38,11 @@
 [% END %]
 
 [% IF discussion2 %]
-	[% IF discussion2 == "slashdot" %]
 	<script src="[% constants.imagedir %]/comments.js?[% constants.cvs_tag_currentcode %]" type="text/javascript"></script>
-	[%- END %]
 	<script type="text/javascript">
 <!--
+[%- IF gSkin.name != 'idle' %]
+	d2_keybindings_disable[191] = 1;[% END # turn off '/' key %]
 	window.onscroll = d2act;
 	boxStatus(1);
 [% Slash.jsSelectComments(Slash.db, constants, user, { sid => sid, cid => cid }, gSkin) %]
@@ -51,7 +51,7 @@
 [% END %]
 
 [% IF cid && !discussion2 %]
-	<ul id="commentlisting" class="[% user.mode %]">
+	<ul id="commentlisting" class="[% user.mode %] d1">
 	[% Slash.dispComment(comment) %]
 	<div class="comment_footer">
 	[% IF previous %]
@@ -92,10 +92,12 @@
 
 	[% lcp %]
 	[% IF lvl; END %]
-	[% this_pid = discussion2 ? 0 : pid;
-	   thread = Slash.displayThread(sid, this_pid, lvl, comments) %]
+	[% IF comments;
+	     this_pid = discussion2 ? 0 : pid;
+	     thread = Slash.displayThread(sid, this_pid, lvl, comments);
+	   END %]
 	[% IF thread || discussion2 %]
-		[% IF !cid || discussion2 %]<ul id="commentlisting"[% IF discussion2 %] class="d2"[% END %]>[% END %]
+		[% IF !cid || discussion2 %]<ul id="commentlisting" class="[% discussion2 ? 'd2' : 'd1' %]">[% END %]
 			[% thread || '' %]
 			<li id="roothiddens" class="hide"></li>
 		[% IF !cid || discussion2 %]</ul>[% END %]
@@ -125,6 +127,9 @@
 }) %]</b></p></span>
 [% END %]
 
+[% IF !user.is_anon %]
+<span class="nbutton"><p><b><a href="[% gSkin.rootdir %]/my/comments"[% IF constants.modal_prefs_active %] onclick="getModalPrefs('d2', 'Discussion 2'); return false"[% END %]>Prefs</a></b></p></span>[% END %]
+
 [% IF (can_moderate || user.acl.candelcomments_always) %]
 <span class="nbutton"><p><b><a href="[% gSkin.rootdir %]/moderation.shtml">Moderator Help</a></b></p></span>[% END %]
 
@@ -141,9 +146,9 @@
 	        [%- ELSE %]<input type="submit" value="moderate" class="button">
 	        [% END %]
 	[% END %]
-	</form>
 [% END %]
 </div>
+[% IF moderate_form %]	</form>[% END %]
 
 [% IF discussion2 %]
 	<script type="text/javascript">
@@ -159,6 +164,13 @@
 		init_hiddens         = [[% user.state.comments.hiddens.join(',') %]];
 
 		finishLoading();
+
+[% UNLESS user.state.discussion_archived || user.state.discussion_future_nopost %]
+		if (thresh_totals[6][6][1] == 0) {
+			replyTo(0, 1);
+		}
+[% END %]
+
 //-->
 	</script>
 [% END %]

Modified: slashjp/trunk/themes/slashcode/templates/printCommentsLinks;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/printCommentsLinks;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/printCommentsLinks;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -15,9 +15,7 @@
 __template__
 [% IF discussion2 %]
 	<a href="#" onclick="ajaxFetchComments(0,1); return false"><span id="more_comments_num_[% commentslinks_id %]"></span> More</a> | 
-[% END; IF user.is_anon;
-	PROCESS userlogin_cover
-		return_url = gSkin.rootdir _ '/comments.pl?sid=' _ sid %]
+[% END; IF user.is_anon %]
 	<a href="[% gSkin.rootdir %]/login.pl" onclick="show_login_box(); return false">Login</a>
 [% ELSE %]
 	<a href="[% gSkin.rootdir %]/my/comments"[% IF constants.modal_prefs_active %] onclick="getModalPrefs('d2', 'Discussion 2'); return false"[% END %]>Prefs</a>
@@ -36,4 +34,4 @@
 __seclev__
 10000
 __version__
-$Id: printCommentsLinks;misc;default,v 1.1 2008/04/10 05:22:29 pudge Exp $
+$Id$

Modified: slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -27,9 +27,11 @@
    	horiz = 1 IF rooted || user.comments_control == 'horizontal';
    ELSE;
    	horiz = 1 IF constants.comments_control_horizontal;
-   END %]
-[% discussion2 = Slash.discussion2() %]
-[% spilltext = "Spill at <b>${user.commentspill}</b>!";
+   END;
+   count = count || 0;
+   discussion2 = Slash.discussion2();
+   this_title = title;
+   spilltext = "Spill at <b>${user.commentspill}</b>!";
    fineprint = 'The following comments are owned by whoever posted them.  We are not responsible for them in any way.';
    modpoints = BLOCK %]
 	| <b>[% user.points %]</b>
@@ -40,17 +42,17 @@
 
 <a name="acomments"></a>
 <div class="commentwrap" id="commentwrap">
-[% IF discussion2 %]
+[% IF discussion2; IF !user.state.d2asp %]
 <div class="commentBox" style="font-size: 120%">
 	<div>
-[% IF title %]<span class="escape-link"><a href="[% link | strip_urlattr %]" title="Back to Article - [% title | strip_attribute %]">[% title %]</a></span>[% END %]
+[% IF this_title %]<span class="escape-link"><a href="[% link | strip_urlattr %]" title="Back to Article - [% this_title | strip_attribute %]">[% this_title %]</a></span>[% END %]
 <span class="commentBoxLinks">[% PROCESS printCommentsLinks commentslinks_id => 'd' %]</span>
 	</div>
 </div>
-[% ELSE %]
+[% END; ELSE %]
 <div class="commentBox">
-[% IF title %]
-	<a href="[% link | strip_urlattr %]">[% title %]</a>
+[% IF this_title %]
+	<a href="[% link | strip_urlattr %]">[% this_title %]</a>
 [% ELSE %]
 	[% Slash.linkComment({
 		sid	=> sid,
@@ -67,18 +69,18 @@
 [% ELSE %]
 		<a href="[% gSkin.rootdir %]/my/comments">Preferences</a>
 [% END %]
-
+[% IF sid %]
 		| [% Slash.linkComment({
 			sid	=> sid,
 			pid	=> 0,
 			subject	=> 'Top',
 			subject_only => 1,
-		}) %]
+		}); END %]
 
 [% IF user.points; modpoints; END %]
 [% IF count %]| <b>[% count %]</b> comments[% END %]
 [% IF lvl && user.mode == 'thread' %]([% spilltext %]) | Index Only[% END %]
-[% IF form.startat %]| Starting at #[% form.startat %][% END %]
+[% IF sid && form.startat %]| Starting at #[% form.startat %][% END %]
 		| <a href="[% gSkin.rootdir %]/search.pl?op=comments&amp;sid=[% sid %]">Search Discussion</a>
 </div>
 [% END %]
@@ -133,10 +135,16 @@
 		<div class="loki" id="gods">
 		<div class="block">
 			<div class="title">
+[% IF user.state.d2asp -%]<span class="soda pop[% options.fh_item.popval || 0 %]"></span>
+<a href="[% gSkin.rootdir %]/firehose.pl?op=view&amp;id=[% options.fh_item.id %]"><span id="updown-[% options.fh_item.id %]" class="vote[% IF vote == "down" %]ddown[% ELSIF vote == "up" %]dup[% END %]" style="top: 0.3em">
+<span class="up">+</span><span class="down">-</span>
+</span></a>[% END %]
 				<h4>
-				[% IF title %]
-					<span class="h-inline"><a href="[% link | strip_urlattr %]" title="Back to Article - [% title | strip_attribute %]">[% title %]</a></span>
-					<span class="titlecount"><a href="[% link | strip_urlattr %]#topcomment" title="Back to Top Comment - [% title | strip_attribute %]"><span id="titlecountnum">[% count %]</span>&nbsp;Comment[% count == 1 ? '' : 's' %]</a></span>
+				[% IF this_title %]
+					<span class="h-inline">[% IF user.state.d2asp -%]
+					<a href="[% constants.rootdir %]/" title="[% constants.sitename | strip_attribute %]" style="margin-left:4em">[% constants.sitename %]</a>:[% END %]
+					<a href="[% link | strip_urlattr %]" title="Back to Article - [% this_title | strip_attribute %]">[% this_title %]</a></span>
+					<span class="titlecount"><a href="[% link | strip_urlattr %]#topcomment" title="Back to Top Comment - [% this_title | strip_attribute %]"><span id="titlecountnum">[% count %]</span>&nbsp;Comment[% count == 1 ? '' : 's' %]</a></span>
 				[% ELSE %] 
 					[% Slash.linkComment({
 						sid	=> sid,
@@ -209,7 +217,12 @@
         </div>
       </div>
 		</div>
-		<div class="commentControlFooter">[% PROCESS printCommentsLinks commentslinks_id => 'c' %]</div>
+		<div class="commentControlFooter">[% 
+			PROCESS printCommentsLinks commentslinks_id => 'c';
+			IF user.is_anon;  # XXX no sid?
+			   	PROCESS userlogin_cover return_url = gSkin.rootdir _ '/comments.pl?sid=' _ sid;
+   			END;
+		%]</div>
 		<div id="commentControlBoxStatus" class="hide"><b>Loading... please wait.</b></div>
 	</div>
 </div>
@@ -217,6 +230,10 @@
 	[% END %]
 </div>
 <a name="topcomment"></a>
+[% IF user.state.d2asp %]
+<div style="text-align:center; margin-top: 1.5em; margin-bottom: -1.5em;">
+<iframe src="http://slashdot.org/images/iframe/idle.html" height="110" width="740" frameborder="0" border="0" scrolling="no" marginwidth="0" marginheight="0"></iframe></div>
+[% END %]
 
 __seclev__
 10000


Property changes on: slashjp/trunk/themes/slashcode/templates/udiscuss_list;comments;default
___________________________________________________________________
Name: svn:executable
   - *

Modified: slashjp/trunk/themes/slashcode/templates/userFireHose;users;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/userFireHose;users;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/userFireHose;users;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -47,4 +47,4 @@
 __seclev__
 500
 __version__
-$Id: $
+$Id$

Modified: slashjp/trunk/themes/slashcode/templates/userInfo2;users;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/userInfo2;users;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/userInfo2;users;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -15,23 +15,14 @@
 [% orig_title = title %]
 
         <div class="head">
-                <div class="article">
-                        <h3>[% latest_event.subject %]</h3>
-                        <div class="body">
-                                [% latest_event.text %]
-                        </div>
-                </div>
+                <div class="yui-b">
+                        <div class="block" id="user_bio">
+                                <div class="title" id="user_bio_title">
+                                        <h4>User Bio</h4>
+                                </div>
 
-        </div>
-
-        <div id="slashboxes" class="yui-b">
-                <div class="block">
-                        <div class="title">
-                                <h4>User Bio</h4>
-                        </div>
-
-                        <div class="content">
-                                [%
+                                <div class="content" id="user_bio_content">
+                                        [%
                                 '<a href="'; gSkin.rootdir; '/~';
                                 useredit.nickname | strip_paramattr; '/">';
                                 useredit.nickname | strip_literal; '</a> ';
@@ -66,7 +57,7 @@
                                         END;
                                 END;
 
-                                IF useredit.homepage;
+                        IF useredit.homepage;
                                 '<br><a href="';
                                 useredit.homepage | strip_attribute;
                                 '"';
@@ -127,128 +118,90 @@
                                 Slash.parseDomainTags(useredit.bio);
                         END;
                         %]
-                        </div>
-                </div>
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Latest Comments</h4>
-                        </div>
+                                </div>
 
-                        <div class="content">
-                                <ul>
-                                [% FOREACH cid = latest_comments.keys.sort %]
-                                        <li><a href="[% constants.absolutedir_secure %]/comments.pl?sid=[% latest_comments.$cid.sid %]&cid=[% cid %]">[% latest_comments.$cid.subject %]</a></li>
-                                [% END %]
-                                </ul>
+                                <div class="foot"></div>
                         </div>
                 </div>
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Latest Journal Entries</h4>
+                <div class="article" id="marquee_content">
+                        <h3>[% latest_event.subject %]</h3>
+                        <div class="body">
+                                [% latest_event.text %]
                         </div>
-
-                        <div class="content">
-                                <ul>
-                                [% FOREACH jid = latest_journals.keys.sort %]
-                                        <li><a href="[% constants.absolutedir_secure %]/~[% useredit.nickname %]/journal/[% latest_journals.$jid.id %]">[% latest_journals.$jid.desc %]</a><br></li>
-                                [% END %]
-                                </ul>
-                        </div>
                 </div>
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Box 3</h4>
-                        </div>
+        </div>
 
-                        <div class="content">
-                                <ul>
-                                <li>Foo</li>
-                                <li>Bar</li>
-                                </ul>
-                        </div>
+        <div class="nav">
+                <ul class="menu" id="tablist">
+                [% IF latest_comments.size != 0 %]<li><a href="[% constants.absolutedir_secure %]/^[% useredit.nickname %]/comments">Comments</a></li>[% END %]
+                [% IF latest_journals.size != 0 %]<li><a href="[% constants.absolutedir_secure %]/^[% useredit.nickname %]/journal">Journals</a></li>[% END %]
+                [% IF latest_submissions.size != 0 %]<li><a href="[% constants.absolutedir_secure %]/^[% useredit.nickname %]/submissions">Submissions</a></li>[% END %]
+                </ul>
+        </div>
+
+        <div class="yui-b" id="userboxes">
+        [% IF latest_comments.size != 0 %]
+        <div class="block" id="latest_comments">
+                <div class="title" id="latest_comments_title">
+                        <h4>Latest Comments</h4>
                 </div>
+                <div class="content" id="latest_comments_content">
+                        <ul>
+                        [% FOREACH cid = latest_comments.keys.sort %]
+                        <li><a href="[% constants.absolutedir_secure %]/comments.pl?sid=[% latest_comments.$cid.sid %]&cid=[% cid %]">[% latest_comments.$cid.subject %]</a></li>
+                        [% END %]
+                        </ul>
+                </div>
+        </div>
+        [% END %]
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Box 4</h4>
-                        </div>
-
-                        <div class="content">
-                                <ul>
-                                <li>Foo</li>
-                                <li>Bar</li>
-                                </ul>
-                        </div>
+        [% IF latest_journals.size != 0 %]
+        <div class="block" id="latest_journals">
+                <div class="title" id="latest_journals_titles">
+                        <h4>Latest Journal Entries</h4>
                 </div>
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Box 5</h4>
-                        </div>
-
-                        <div class="content">
-                                <ul>
-                                <li>Foo</li>
-                                <li>Bar</li>
-                                </ul>
-                        </div>
+                <div class="content" id="latest_journals_content">
+                        <ul>
+                        [% FOREACH jid = latest_journals.keys.sort %]
+                        <li><a href="[% constants.absolutedir_secure %]/~[% useredit.nickname %]/journal/[% latest_journals.$jid.id %]">[% latest_journals.$jid.desc %]</a><br></li>
+                        [% END %]
+                        </ul>
                 </div>
+        </div>
+        [% END %]
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Box 6</h4>
-                        </div>
-
-                        <div class="content">
-                                <ul>
-                                <li>Foo</li>
-                                <li>Bar</li>
-                                </ul>
-                        </div>
+        [% IF latest_submissions.size != 0 %]
+        <div class="block" id="latest_submissions">
+                <div class="title" id="latest_submissions_title">
+                        <h4>Latest Submissions</h4>
                 </div>
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Box 7</h4>
-                        </div>
-
-                        <div class="content">
-                                <ul>
-                                <li>Foo</li>
-                                <li>Bar</lil>
-                                </ul>
-                        </div>
+                <div class="content" id="latest_submissions_content">
+                        <ul>
+                        [% FOREACH sid = latest_submissions.keys.sort %]
+                        <li><a href="[% constants.absolutedir_secure %]/firehose.pl?op=view&id=[% latest_submissions.$sid.id %]">[% latest_submissions.$sid.title %]</a></li>
+                        [% END %]
+                        </ul>
                 </div>
+        </div>
+        [% END %]
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Box 8</h4>
-                        </div>
+        </div>
 
-                        <div class="content">
-                                <ul>
-                                <li>Foo</li>
-                                <li>Bar</li>
-                                </ul>
-                        </div>
-                </div>
+        <div id="yui-main">
+                <div class="yui-b">
 
-                <div class="block">
-                        <div class="title">
-                                <h4>Box 9</h4>
-                        </div>
+                [% IF data_pane == 'journal' %]
+                [% ELSIF data_pane == 'submissions' %]
+                [% ELSE %]
+                        [% PROCESS listComments admin_flag=admin_flag commentstruct=commentstruct commentcount=commentcount min_comment=min_comment reasons=reasons cids_to_mods=cids_to_mods type="user" useredit=useredit comment_time=comment_time %]
+                [% END %]
 
-                        <div class="content">
-                                <ul>
-                                <li>Foo</li>
-                                <li>Bar</li>
-                                </ul>
-                        </div>
                 </div>
-
         </div>
 
 [% title = orig_title %]
@@ -256,4 +209,4 @@
 __seclev__
 500
 __version__
-$Id: userInfo2;users;default,v 1.1 2008/04/02 14:42:24 entweichen Exp $
+$Id$

Modified: slashjp/trunk/themes/slashcode/templates/userboxes2;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/userboxes2;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/userboxes2;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -144,4 +144,4 @@
 __seclev__
 1000
 __version__
-$Id: userboxes2;misc;default,v 1.1 2008/04/02 14:41:12 entweichen Exp $
+$Id$

Modified: slashjp/trunk/themes/slashcode/templates/userlogin_cover;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/userlogin_cover;misc;default	2008-09-09 08:53:05 UTC (rev 741)
+++ slashjp/trunk/themes/slashcode/templates/userlogin_cover;misc;default	2008-09-09 13:07:58 UTC (rev 742)
@@ -29,4 +29,4 @@
 __seclev__
 10000
 __version__
-$Id: $
+$Id$

Copied: slashjp/trunk/utils/update_storable_network.plx (from rev 741, slashjp/branches/upstream/2.5.0.218/utils/update_storable_network.plx)
===================================================================
--- slashjp/trunk/utils/update_storable_network.plx	                        (rev 0)
+++ slashjp/trunk/utils/update_storable_network.plx	2008-09-09 13:07:58 UTC (rev 742)
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -s
+use warnings;
+use strict;
+
+# convert freeze to nfreeze
+
+our($debug, $dump);
+
+use Slash::Test shift || 'slash';
+
+my $constants = getCurrentStatic();
+my $slashdb = getCurrentDB();
+
+update_nfreeze('users_info', 'uid', 'people');
+
+update_nfreeze('message_drop', 'id', 'message')
+	if $constants->{plugin}{Messages};
+
+update_nfreeze('dilemma_agents', 'daid', 'memory')
+	if $constants->{plugin}{Dilemma};
+
+# this will take too much time to do; if we ever need to get this data
+# out, we'll just need to find a little-endian 32-bit perl to do it with
+#$slashdb = getObject('Slash::DB', { virtual_user => $constants->{log_db_user} });
+#update_nfreeze('accesslog_admin', 'id', 'form');
+
+
+sub update_nfreeze {
+	my($table, $key, $blob) = @_;
+
+	print "updating $blob in $table\n";
+	my $sth = $slashdb->{_dbh}->prepare("SELECT $key, $blob FROM $table");
+	$sth->execute or die;
+	while (my $row = $sth->fetchrow_arrayref) {
+		if ($row->[0] && $row->[1]) {
+			print "updating $key $row->[0]\n" if $debug;
+			print Dumper thaw($row->[1]) if $dump;
+			if ($row->[1]) {
+				$slashdb->sqlUpdate($table, {
+					$blob => nfreeze(thaw($row->[1])),
+				}, "$key=$row->[0]");
+			}
+		}
+	}
+	$sth->finish;
+	print "\n";
+}
+


Slashdotjp-dev メーリングリストの案内
Back to archive index