From 46b9418b8f1eeb2d5cebd5a025c53a49faa05bfe Mon Sep 17 00:00:00 2001 From: hylom Date: Tue, 25 Oct 2016 03:15:45 +0900 Subject: [PATCH] Model::LegacyDB: add 'getCurrentStatic' method --- src/newslash_web/lib/Newslash/Model/LegacyDB.pm | 427 +++++++++++++++++++++++- 1 file changed, 426 insertions(+), 1 deletion(-) diff --git a/src/newslash_web/lib/Newslash/Model/LegacyDB.pm b/src/newslash_web/lib/Newslash/Model/LegacyDB.pm index cb212304..bb819ece 100644 --- a/src/newslash_web/lib/Newslash/Model/LegacyDB.pm +++ b/src/newslash_web/lib/Newslash/Model/LegacyDB.pm @@ -4,6 +4,432 @@ use Newslash::Model::Base -base; ## WORNING: ## This is legacy from slash. deprecated, and you can use only backword-compatible. +#======================================================================== + +=head2 dbAvailable([TOKEN]) + +Returns TRUE if (as usual) the DB(s) are available for reading and +writing. Returns FALSE if the DB(s) are not available and should not +be accessed. If a TOKEN is named, return FALSE if either the DB(s) +required for that purpose are down or all DBs are down. If no TOKEN is +named, return FALSE only if all DBs are down. + +Whether or not the DBs are down is determined only by whether files exist +at /usr/local/slash/dboff or /usr/local/slash/dboff_TOKEN. For best +results, admins will want to write their own db-angel scripts that detect +DBs having gone down and create one or more of those files. + +=over 4 + +=item Parameters + +=over 4 + +=item TOKEN + +Name of the resource specifically being asked about, or the +empty string. + +=back + +=item Return value + +0 or 1. + +=back + +=cut + +sub dbAvailable { + return 1; +} + +#======================================================================== + +=head2 getCurrentStatic([MEMBER]) + +Returns the current static variables (or variable). + +Slash's original implement was depended to Apache and memcached, +but this implement uses redis for cache. + +And in this implement, this function is method. + +=over 4 + +=item Parameters + +=over 4 + +=item MEMBER + +A member from the static record to be returned. + +=back + +=item Return value + +A hash reference with the static information is returned unless MEMBER is passed. If +MEMBER is passed in then only its value will be returned. + +=back + +=cut + +sub getCurrentStatic { + my ($self, $value, $force_secure) = @_; + my $kvs = $self->connect_kvs; + my $kvs_key = "slash_static"; + my $constants; + + if ($kvs->exists($kvs_key)) { + $constants = $kvs->hgetall($kvs_key); + } + else { + $constants = $self->getSlashConf(0, 0); + $kvs->hmset($kvs_key, $constants); + } + + return defined $value ? $constants->{$value} : $constants; +} + +######################################################## +sub _getSlashConf_rawvars { + my($self, $secure, $skipcache) = @_; + $secure = $secure ? 1 : 0; +# my $vu = $self->{virtual_user}; +# return undef unless $vu; +# my $mcd = $self->getMCD({ no_getcurrentstatic => 1 }); +# my $mcdkey= "x:vars$secure"; +# my $got_from_memcached = 0; + my $vars_hr; +# if ($mcd && !$skipcache) { +# if ($vars_hr = $mcd->get($mcdkey)) { +# $got_from_memcached = 1; +# } +# } + $vars_hr ||= $self->sqlSelectAllKeyValue('name, value', 'vars'); +# if ($mcd && !$got_from_memcached) { +# # Cache this for about 3 minutes. should be a var. +# my $expire_time = 180; +# $mcd->set($mcdkey, $vars_hr, $expire_time); +# } + return $vars_hr; +} + +######################################################## +# Now, the idea is to not cache here, since we actually +# cache elsewhere (namely in %Slash::Apache::constants) - Brian +# I'm caching this in memcached now though. - Jamie +sub getSlashConf { + my($self, $secure, $skipcache) = @_; + + # Get the raw vars data (possibly from a memcached cache). + + my $vars_hr = $self->_getSlashConf_rawvars($secure, $skipcache); + return if !defined $vars_hr; + my %conf = %$vars_hr; + + # Now start adding and tweaking the data for various reasons: + # convenience, fixing bad data, etc. + + # This allows you to do stuff like constant.plugin.Zoo in a template + # and know that the plugin is installed -Brian + my $plugindata = $self->sqlSelectColArrayref('value', 'site_info', + "name='plugin'"); + for my $plugin (@$plugindata) { + $conf{plugin}{$plugin} = 1; + } + my $tagboxdata = $self->sqlSelectColArrayref('value', 'site_info', + "name='tagbox'"); + for my $tagbox (@$tagboxdata) { + $conf{tagbox}{$tagbox} = 1; + } + + # This really should be a separate piece of data returned by + # getReasons() the same way getTopicTree() works. It's only part + # of $constants for historical, er, reasons. + if ($conf{m1}) { + $conf{reasons} = $self->sqlSelectAllHashref( + "id", "*", "modreasons" + ); + $conf{reasons_base} = $self->sqlSelectAllHashref( + "id", "*", "modreasons", "m2able = 1 OR val = 0" + ); + $conf{reasons_plused} = $self->sqlSelectAllHashref( + "id", "*", "modreasons", "m2able = 1 OR val <= 0" + ); + $conf{reasons_minused} = $self->sqlSelectAllHashref( + "id", "*", "modreasons", "m2able = 1 OR val >= 0" + ); + foreach my $d (split(/,/, $conf{modreasons_select_disabled} || '')) { + $conf{reasons}{int($d)}{select_disabled} = 1; + $conf{reasons_base}{int($d)}{select_disabled} = 1; + $conf{reasons_plused}{int($d)}{select_disabled} = 1; + $conf{reasons_minused}{int($d)}{select_disabled} = 1; + } + } + + $conf{rootdir} ||= "//$conf{basedomain}"; + $conf{real_rootdir} ||= $conf{rootdir}; # for when rootdir changes + $conf{real_section} ||= $conf{section}; # for when section changes + $conf{absolutedir} ||= "http://$conf{basedomain}"; + $conf{imagedir} ||= "$conf{rootdir}/images"; + # If absolutedir_secure is not defined, it defaults to the + # same as absolutedir. Same for imagedir_secure. + $conf{absolutedir_secure} ||= $conf{absolutedir}; + $conf{imagedir_secure} ||= $conf{imagedir}; + $conf{css_extension} = 'css'; +# if (defined &Slash::Apache::ConnectionIsSSL && Slash::Apache::ConnectionIsSSL()) + if ($secure) { + # On Secure HTTP connections, force absolutedir/imagedir to + # be the secure versions. + $conf{imagedir} = $conf{imagedir_secure}; + $conf{absolutedir} = $conf{absolutedir_secure}; + $conf{css_extension} = 'ssl.css'; + } + $conf{cssdir} ||= $conf{css_use_imagedir} ? $conf{imagedir} : $conf{rootdir}; + $conf{rdfimg} ||= "$conf{imagedir}/topics/topicslash.gif"; + $conf{adminmail_mod} ||= $conf{adminmail}; + $conf{adminmail_post} ||= $conf{adminmail}; + $conf{adminmail_ban} ||= $conf{adminmail}; + $conf{basedir} ||= "$conf{datadir}/public_html"; + $conf{index_handler} ||= 'index.pl'; + $conf{cookiepath} ||= URI->new($conf{rootdir})->path . '/'; + $conf{maxkarma} = 999 unless defined $conf{maxkarma}; + $conf{minkarma} = -999 unless defined $conf{minkarma}; + $conf{expiry_exponent} = 1 unless defined $conf{expiry_exponent}; + $conf{panic} ||= 0; + $conf{textarea_rows} ||= 10; + $conf{textarea_cols} ||= 50; + $conf{allow_deletions} ||= 1; + $conf{authors_unlimited} = 100 if !defined $conf{authors_unlimited} + || $conf{authors_unlimited} == 1; + # m2_consensus must be odd + $conf{m2_consensus} = 2*int(($conf{m2_consensus} || 5)/2) + 1 + if !$conf{m2_consensus} + || ($conf{m2_consensus}-1)/2 != int(($conf{m2_consensus}-1)/2); + $conf{nick_chars} ||= q{ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_.+!*'(),-}; + $conf{nick_maxlen} ||= 20; + $conf{cookie_location} ||= 'classbid'; + $conf{login_temp_minutes} ||= 10; + # For all fields that it is safe to default to -1 if their + # values are not present... + for (qw[min_expiry_days max_expiry_days min_expiry_comm max_expiry_comm]) { + $conf{$_} = -1 unless exists $conf{$_}; + } + + # no trailing newlines on directory variables + # possibly should rethink this for basedir, + # since some OSes don't use /, and if we use File::Spec + # everywhere this won't matter, but still should be do + # it for the others, since they are URL paths + # -- pudge + for (qw[rootdir absolutedir imagedir imagedir_secure basedir]) { + $conf{$_} =~ s|/+$||; + } + + my $fixup = sub { + return [ ] if !$_[0]; + [ + map {( + s/^\s+//, + s/\s+$//, + $_ + )[-1]} + split /\|/, $_[0] + ]; + }; + my $fixup_hash = sub { + my $ar = $fixup->(@_); + my $hr = { }; + return $hr if !$ar; + for my $str (@$ar) { + my($k, $v) = split(/=/, $str); + $v = 1 if !defined($v); + $v = [ split ",", $v ] if $v =~ /,/; + $hr->{$k} = $v; + } + $hr; + }; + + my %conf_fixup_arrays = ( + # var name # default array value + # -------- # ------------------- + anonymous_coward_uids => [ $conf{anonymous_coward_uid} ], + # See + approved_url_schemes => [qw( ftp http gopher mailto news nntp telnet wais https )], + approvedtags => [qw( b i p br a ol ul li dl dt dd em strong tt blockquote div ecode quote)], + approvedtags_break => [qw( p br ol ul li dl dt dd blockquote div img hr )], + # all known tags, plus table, pre, and slash; this can be overridden + # in vars, but since we make this all known tags by default ... + # easier to just keep it in here + approvedtags_admin => [qw( b i p br a ol ul li dl dt dd em strong tt blockquote div ecode + img hr big small sub sup span + dfn code samp kbd var cite address ins del + h1 h2 h3 h4 h5 h6 + table thead tbody tfoot tr th td pre + slash + )], + charrefs_bad_entity => [qw( zwnj zwj lrm rlm )], + charrefs_bad_numeric => [qw( 8204 8205 8206 8207 8236 8237 8238 )], + charrefs_good_entity => [qw( amp lt gt euro pound yen rsquo lsquo rdquo ldquo ndash mdash )], + charrefs_good_numeric => [ ], + cur_performance_stat_ops => [ ], + firehose_story_ignore_skids => [ ], + fixhrefs => [ ], + hc_possible_fonts => [ ], + lonetags => [ ], + m2_sliding_consensus => [ ], + op_exclude_from_countdaily => [qw( rss )], + op_extras_countdaily => [ ], + mod_stats_reports => [ $conf{adminmail_mod} ], + stats_reports => [ $conf{adminmail} ], + stats_metrics_reports => [ $conf{adminmail} ], + stats_sfnet_groupids => [ 4421 ], + submit_categories => [ ], + skins_recenttopics => [ ], + subnet_karma_post_limit_range => [ ], + search_ignore_skids => [ ], + ); + my %conf_fixup_hashes = ( + # var name # default hash of keys/values + # -------- # -------------------- + ad_messaging_sections => { }, + comments_perday_bykarma => { -1 => 2, 25 => 25, 99999 => 50 }, + karma_adj => { -10 => 'Terrible', -1 => 'Bad', 0 => 'Neutral', + 12 => 'Positive', 25 => 'Good', 99999 => 'Excellent' }, + mod_up_points_needed => { }, + # 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 )], + 0.49 => [qw( 0 0 -4 0 )], + 0.60 => [qw( 0 0 +1 0 )], + 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 -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 }, + ); + for my $key (keys %conf_fixup_arrays) { + if (defined($conf{$key})) { + $conf{$key} = $fixup->($conf{$key}); + } else { + $conf{$key} = $conf_fixup_arrays{$key}; + } + } + for my $key (keys %conf_fixup_hashes) { + if (defined($conf{$key})) { + $conf{$key} = $fixup_hash->($conf{$key}); + } else { + $conf{$key} = $conf_fixup_hashes{$key}; + } + } + + for my $var (qw(email_domains_invalid submit_domains_invalid)) { + if ($conf{$var}) { + my $regex = sprintf('[^\w-](?:%s)$', + join '|', map quotemeta, split ' ', $conf{$var}); + $conf{$var} = qr{$regex}; + } + } + + if ($conf{comment_nonstartwordchars}) { + # Expand this into a complete regex. We catch not only + # these chars in their raw form, but also all HTML entities + # (because Windows/MSIE refuses to break before any word + # that starts with either the chars, or their entities). + # Build the regex with qr// and match entities for + # optimal speed. + my $src = $conf{comment_nonstartwordchars}; + my @chars = ( ); + my @entities = ( ); + for my $i (0..length($src)-1) { + my $c = substr($src, $i, 1); + push @chars, "\Q$c"; + push @entities, ord($c); + push @entities, sprintf("x%x", ord($c)); + } + my $dotchar = + '(?:' + . '[' . join("", @chars) . ']' + . '|&#(?:' . join("|", @entities) . ');' + . ')'; + my $regex = '(\s+)' . "((?:<[^>]+>)*$dotchar+)" . '(\S)'; + $conf{comment_nonstartwordchars_regex} = qr{$regex}i; + } + + for my $regex (qw( + accesslog_imageregex + x_forwarded_for_trust_regex + lowbandwidth_bids_regex + )) { + next if !$conf{$regex} || $conf{$regex} eq 'NONE'; + $conf{$regex} = qr{$conf{$regex}}; + } + + # anchor + for my $regex (qw( + feed_types + )) { + next if !$conf{$regex}; + $conf{$regex} = qr{^(?:$conf{$regex})$}; + } + + + for my $var (qw(approvedtags approvedtags_break lonetags)) { + $conf{$var} = [ map lc, @{$conf{$var}} ]; + } + + for my $attrname (qw(approvedtags_attr approvedtags_attr_admin)) { + if ($conf{$attrname}) { + my $approvedtags_attr = $conf{$attrname}; + $conf{$attrname} = {}; + my @tags = split /\s+/, $approvedtags_attr; + foreach my $tag (@tags){ + my($tagname, $attr_info) = $tag =~ /([^:]*)(?:\:(.*))?$/; + my @attrs = split ',', ($attr_info || ''); + my $ord = 1; + foreach my $attr (@attrs){ + my($at, $extra) = split /_/, $attr; + $extra ||= ''; + $at = lc $at; + $tagname = lc $tagname; + $conf{$attrname}{$tagname}{$at}{ord} = $ord; + $conf{$attrname}{$tagname}{$at}{req} = 1 if $extra =~ /R/; + $conf{$attrname}{$tagname}{$at}{req} = 2 if $extra =~ /N/; # "necessary" + $conf{$attrname}{$tagname}{$at}{url} = 1 if $extra =~ /U/; + $ord++; + } + } + } + } + if ($conf{approvedtags_attr} && $conf{approvedtags_attr_admin}) { + for (keys %{$conf{approvedtags_attr}}) { + # only add to _admin if not already in it + $conf{approvedtags_attr_admin}{$_} ||= $conf{approvedtags_attr}{$_}; + } + } + + # We only need to do this on startup. This var isn't really used; + # see the code comment in getObject(). + $conf{classes} = $self->getClasses(); + + if ($conf{utf8}) { + foreach my $k (keys %conf) { + next if ref($conf{$k}) ne 'SCALAR' || Encode::is_utf8($conf{$k}); + Encode::_utf8_on($conf{$k}); + } + } + + return \%conf; +} + + sub sqlConnect { my ($self, $restart) = @_; if ($restart) { @@ -185,5 +611,4 @@ sub sqlGetCharColumnLength { } } # end closure - 1; -- 2.11.0