+my $user = eval {
+ my $rootpath = ($ENV{REQUEST_URI} // '/writer') =~ s{(?<!^)/.+}{}r;
+ if (defined $post{username}) {
+ $cookie{login} = EncodeURI(join ':', @post{qw( username pass )});
+ }
+ elsif (exists $fields{logout}) {
+ require CGI::Cookie;
+ if (AddCookie(CGI::Cookie->new(
+ -name => 'login',
+ -value => '',
+ -path => $rootpath,
+ -expires => 'now',
+ )->as_string)) {
+ delete $cookie{login};
+ die "Logged out as requested\n";
+ }
+ Alert("Failed to log out", "Login cookie could not be removed.");
+ }
+
+ my $cookiedata = $cookie{login} or return;
+ my ($name, $key) = split /[:\v]/, DecodeURI($cookiedata);
+ my %rowmatch = (username => $name, pass => $key);
+ my $found = $db->select(login => '*', \%rowmatch)->hash
+ or die "Invalid user or password\n";
+
+ eval {
+ require CGI::Cookie;
+ my $httpcookie = CGI::Cookie->new(
+ -name => 'login',
+ -value => join(':', @{$found}{qw( username pass )}),
+ -path => $rootpath,
+ ) or die "prepared object is empty\n";
+ AddCookie($httpcookie->as_string);
+ } or Abort(["Unable to create login cookie", $@], 403);
+
+ return $found;
+} or do {
+ say '<h1>Login to edit words</h1>';
+ Alert('Access denied', $@) if $@;
+ say '<form action="?" method="post" class="inline"><ul>';
+ my $loginform = bless {%post}, 'Shiar_Sheet::FormRow';
+ say '<li>', $loginform->input(@{$_}), '</li>' for pairs (
+ username => {-label => 'User name'},
+ pass => {-label => 'Password', type => 'password'},
+ );
+ say '<li><input type="submit" value="Login" /></li>';
+ say '</ul></form>';
+ exit;
+};
+
+my %lang = (
+ nl => ["\N{REGIONAL INDICATOR SYMBOL LETTER N}\N{REGIONAL INDICATOR SYMBOL LETTER L}", 'nederlands'],
+ en => ["\N{REGIONAL INDICATOR SYMBOL LETTER G}\N{REGIONAL INDICATOR SYMBOL LETTER B}", 'english'],
+ eo => ['<span style="color:green">★</span>', 'esperanto'],
+ ru => ["\N{REGIONAL INDICATOR SYMBOL LETTER R}\N{REGIONAL INDICATOR SYMBOL LETTER U}", 'русский'],
+ zh => ["\N{REGIONAL INDICATOR SYMBOL LETTER C}\N{REGIONAL INDICATOR SYMBOL LETTER N}", '中文'],
+ la => ["\N{PUSHPIN}", 'latin'],
+);
+my @wordcols = pairkeys
+my %wordcol = (
+ lang => {-label => 'Language', -select => {
+ map { $_ => "@{$lang{$_}}" } keys %lang
+ }},
+ cat => [{-label => 'Category'}, 'ref'],
+ ref => {-label => 'Reference'},
+ prio => [
+ {-label => 'Level', -select => sub {
+ my ($row) = @_;
+ my @enum = qw[ essential basic common distinctive optional invisible ];
+ return {
+ ('' => 'parent') x (defined $row->{ref}),
+ map { $_ => $enum[$_] } 0 .. $#enum
+ };
+ }},
+ 'cover', 'grade',
+ ],
+ cover => {-label => 'Highlighted', type => 'checkbox'},
+ grade => {-label => 'Order', type => 'number'},
+ form => {-label => 'Title'},
+ alt => {-label => 'Synonyms', -multiple => 1},
+ wptitle => {-label => 'Wikipedia'},
+ source => {-label => 'Image', -json => 'image', -src => sub {
+ return "data/word/org/$_[0]->{id}.jpg";
+ }},
+ convert => {-label => 'Convert options', -json => 'image', -multiple => 1, -src => sub {
+ return "data/word/en/$_[0]->{id}.jpg";
+ }},
+ story => {-label => 'Story', type => 'textarea', hidden => 'hidden'},