log in." unless $remote; return LJ::no_access_error("You don't have access to use this tool.", "moneyenter") unless LJ::remote_has_priv($remote, "moneyenter"); # heading my $ret = "

Account Management

"; # no user specified, get one unless ($GET{'user'}) { $ret .= "
"; $ret .= "User: " . LJ::html_text({ 'name' => 'user', 'size' => 15, 'maxlength' => 15 }) . " "; $ret .= LJ::html_submit('Load'); $ret .= "
"; return $ret; } # load user my $user = LJ::canonical_username($GET{'user'}); my $u = LJ::load_user($user, "force"); return "Invalid user: '$user'" unless $u; # establish some cap bit -> item mappings my %bonus_caps = map { $LJ::Pay::bonus{$_}->{'cap'}, $_ } keys %LJ::Pay::bonus; my $zerodate = "0000-00-00 00:00:00"; my $dbh = LJ::get_db_writer(); # save chanes if (LJ::did_post()) { # 'notes' field is required return "" unless $POST{'notes'}; my @bits_set; my @bits_del; my $logmsg; # save bit-only features foreach my $bit (0..14) { # make sure $bit is a valid cap as specified by %LJ::CAP (for general caps), # or either %LJ::Pay::capinf or %LJ::Pay::bonus (for local caps) next unless ( ref $LJ::CAP{$bit} eq 'HASH' || (grep { defined $_->{cap} && $_->{cap} == $bit } values %LJ::Pay::bonus) || (grep { defined $_->{cap} && $_->{cap} == $bit } values %LJ::Pay::capinf) ); # build bit mask to set at the end unless ($POST{"cap_${bit}_set"}) { push @bits_del, $bit; next; } push @bits_set, $bit; } # save paid account expiration { my $exp = $POST{'paid_exp'}; # check expiration date format if (defined $exp) { return "Error: Invalid expiration date format, expecting: yyyy-mm-dd hh:mm:ss" unless $exp =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/; } # does a paiduser row already exist? my $paiduntil = $dbh->selectrow_array("SELECT paiduntil FROM paiduser WHERE userid=?", undef, $u->{'userid'}); # update existing row if ($paiduntil) { # if expdate is 0000-00-00 00:00:00, just delete the row if ($exp eq $zerodate) { $dbh->do("DELETE FROM paiduser WHERE userid=?", undef, $u->{'userid'}); $logmsg .= "[delete] item: paid_account, paiduntil: $exp\n"; } # unnecessary query? next if $paiduntil eq $exp; # otherwise do an update $dbh->do("UPDATE paiduser SET paiduntil=? WHERE userid=?", undef, $exp, $u->{'userid'}); $logmsg .= "[update] item: paid_account, paiduntil: $exp\n"; # insert new, non-blank, row } elsif ($exp ne $zerodate) { $dbh->do("INSERT INTO paiduser (userid, paiduntil) " . "VALUES (?, ?)", undef, $u->{'userid'}, $exp); $logmsg .= "[insert] item: paid_account, paiduntil: $exp\n"; } } # update bonus feature foreach my $itemname (sort keys %LJ::Pay::bonus) { my $bitem = $LJ::Pay::bonus{$itemname}; next unless ref $bitem eq 'HASH'; my ($exp, $size, $days) = map { $POST{"${itemname}_$_"} } qw(exp size daysleft); # check expiration date format if (defined $exp) { return "Error: Invalid expiration date format, expecting: yyyy-mm-dd hh:mm:ss" unless $exp =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/; } # see if row exists my $dbrow = $dbh->selectrow_hashref("SELECT expdate, size, daysleft FROM paidexp " . "WHERE userid=? AND item=?", undef, $u->{'userid'}, $itemname); # row exists, do an update if ($dbrow) { # if a zero row, just delete if ($exp eq $zerodate && ! $size && ! $days) { $dbh->do("DELETE FROM paidexp WHERE userid=? AND item=?", undef, $u->{'userid'}, $itemname); $logmsg .= "[delete] item: $itemname, expdate: $exp, size: $size, daysleft: $days\n"; next; } # prepare update query my $sets; $sets .= "expdate=" . $dbh->quote($exp) . "," if defined $exp && $dbrow->{'expdate'} ne $exp; $sets .= "size=" . $dbh->quote($size) . "," if defined $size && $dbrow->{'size'} != $size; $sets .= "daysleft=" . $dbh->quote($days) . "," if defined $days && $dbrow->{'daysleft'} != $days; chop $sets if $sets; # unnecessary query? next unless $sets; # otherwise do an update $dbh->do("UPDATE paidexp SET $sets WHERE userid=? AND item=?", undef, $u->{'userid'}, $itemname); $logmsg .= "[update] item: $itemname, expdate: $exp, size: $size, daysleft: $days\n"; # if no rows, then we need to insert a new row, but not an empty one } elsif ($exp ne $zerodate || $size > 0 || $days > 0) { $exp ||= $zerodate; $size ||= 0; $days ||= 0; $dbh->do("INSERT INTO paidexp (userid, item, size, expdate, daysleft) VALUES (?, ?, ?, ?, ?)", undef, $u->{'userid'}, $itemname, $size, $exp, $days); $logmsg .= "[insert] item: $itemname, expdate: $exp, size: $size, daysleft: $days\n"; } # call any necessary apply_hooks my $apply_hook = $bitem->{apply_hook}; if ($apply_hook && ref $apply_hook eq 'CODE') { $apply_hook->($u, $itemname); } } # note which caps were changed and log $logmsg to statushistory { my $caps_add = join(",", @bits_set); my $caps_del = join(",", @bits_del); $logmsg .= "[caps] add: $caps_add, del: $caps_del\n"; $logmsg .= "[notes] $POST{'notes'}"; LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, "acctedit", $logmsg); } # done looping through possible bits LJ::modify_caps($u, \@bits_set, \@bits_del); return ""; } ### update form $ret .= "
"; $ret .= ""; $ret .= ""; # so we know which bits to skip when going through %LJ::CAP hash my %special_bit = ($LJ::Pay::capinf{'paid'}->{'bit'} => 1); while (my ($itemname, $ref) = each %LJ::Pay::bonus) { $special_bit{$ref->{'cap'}} = 1; } # do bit-only features foreach my $bit (sort { $a <=> $b } keys %LJ::CAP) { next unless ref $LJ::CAP{$bit} eq 'HASH'; next if $special_bit{$bit}; my $has_cap = $u->{'caps'} & 1 << $bit || 0; my $name = $LJ::CAP{$bit}->{'_name'} || "(no name)"; $name = "$name" if $has_cap; $ret .= ""; # expiration $ret .= ""; } # paid account status { my $bit = $LJ::Pay::capinf{'paid'}->{'bit'}; my $has_cap = $u->{'caps'} & 1 << $bit || 0; my $name = "Paid Account"; $name = "$name" if $has_cap; $ret .= ""; $ret .= ""; # get paid account status from database my $exp = $dbh->selectrow_array("SELECT paiduntil FROM paiduser WHERE userid=?", undef, $u->{'userid'}); # expiration text box $ret .= ""; } # bonus features foreach my $itemname (sort { $LJ::Pay::bonus{$a}->{'bit'} <=> $LJ::Pay::bonus{$b}->{'bit'} } keys %LJ::Pay::bonus) { my $bitem = $LJ::Pay::bonus{$itemname}; next unless ref $bitem eq 'HASH'; my $bit = $bitem->{'cap'}; my $has_cap = $u->{'caps'} & 1 << $bit || 0; my $name = $bitem->{'name'}; $name = "$name" if $has_cap; $ret .= ""; $ret .= ""; # get activation status from the db my ($exp, $size, $daysleft) = $dbh->selectrow_array("SELECT expdate, size, daysleft FROM paidexp " . "WHERE userid=? AND item=?", undef, $u->{'userid'}, $itemname); $size += 0; $daysleft += 0; # expire text box $ret .= ""; } $ret .= ""; $ret .= "
BitClassSet?Expiration
$bit"; $ret .= LJ::html_check({ 'type' => 'check', 'name' => "cap_${bit}_set", 'id' => "cap_${bit}_set", 'value' => 1, 'selected' => $has_cap }) . " 
$bit"; $ret .= LJ::html_check({ 'type' => 'check', 'name' => "cap_${bit}_set", 'id' => "cap_${bit}_set", 'value' => 1, 'selected' => $has_cap }) . ""; $ret .= LJ::html_text({ 'name' => "paid_exp", 'value' => $exp || $zerodate, 'size' => 19, 'maxlength' => 19 }); $ret .= "
$bit"; if (defined $bit) { $ret .= LJ::html_check({ 'type' => 'check', 'name' => "cap_${bit}_set", 'id' => "cap_${bit}_set", 'value' => 1, 'selected' => $has_cap }); } else { $ret .= " "; } $ret .= ""; $ret .= LJ::html_text({ 'name' => "${itemname}_exp", 'value' => $exp || $zerodate, 'size' => 19, 'maxlength' => 19 }); # need a size box? if (LJ::Pay::is_bonus($bonus_caps{$bit}, 'sized')) { $ret .= "
Size: "; $ret .= LJ::html_text({ 'name' => => "${itemname}_size", 'value' => $size, 'size' => 5, 'maxlength' => 5 }); } # daysleft text box $ret .= "
Daysleft: "; $ret .= LJ::html_text({ 'name' => => "${itemname}_daysleft", 'value' => $daysleft, 'size' => 3, 'maxlength' => 3 }); $ret .= "
Notes: (required)
"; $ret .= LJ::html_textarea({ 'name' => 'notes', 'rows' => 3, 'cols' => 60, 'wrap' => 'soft' }); $ret .= "
"; $ret .= LJ::html_submit('Update') . "
"; $ret .= "
"; return $ret; } _code?>