Changeset 13
- Timestamp:
- 02/18/07 23:37:11 (3 years ago)
- Location:
- veekun
- Files:
-
- 1 added
- 9 modified
- 7 moved
-
README.pod (modified) (2 diffs)
-
lib/Vee.pm (modified) (4 diffs)
-
lib/Vee/Controller/Dex.pm (modified) (1 diff)
-
lib/Vee/Controller/Users.pm (modified) (5 diffs)
-
lib/Vee/View/TT.pm (modified) (1 diff)
-
root/images/icons/contact (added)
-
root/images/icons/contact/aim.png (moved) (moved from veekun/root/images/icons/aim.png)
-
root/images/icons/contact/email.png (moved) (moved from veekun/root/images/icons/email.png)
-
root/images/icons/contact/homepage.png (moved) (moved from veekun/root/images/icons/homepage.png)
-
root/images/icons/contact/icq.png (moved) (moved from veekun/root/images/icons/icq.png)
-
root/images/icons/contact/lj.png (moved) (moved from veekun/root/images/icons/lj.png)
-
root/images/icons/contact/msn.png (moved) (moved from veekun/root/images/icons/msn.png)
-
root/images/icons/contact/yim.png (moved) (moved from veekun/root/images/icons/yim.png)
-
site_options.yml (modified) (2 diffs)
-
templates/forum/common.tt (modified) (1 diff)
-
templates/users/edit.tt (modified) (1 diff)
-
templates/users/info.tt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
veekun/README.pod
r4 r13 25 25 Catalyst::Plugin::Session::Store::DBIC 26 26 DBIx::Class 27 Email::Valid 28 Image::Size 29 JSON 30 String::Approx 27 31 Template 28 String::Approx29 JSON30 32 YAML 31 33 … … 33 35 development. 34 36 35 Catalyst:: Helper37 Catalyst::Devel 36 38 37 39 =head2 Database Setup -
veekun/lib/Vee.pm
r8 r13 7 7 8 8 # load crap 9 # Authorization::Roles?9 # first group are DEBUG-ONLY! 10 10 use Catalyst qw/ 11 11 -Debug 12 12 StackTrace 13 14 13 Static::Simple 15 14 … … 33 32 our $VERSION = '0.01'; 34 33 34 =head1 NAME 35 36 Vee - Code for veekun.com 37 38 =head1 SYNOPSIS 39 40 script/vee_server.pl 41 42 =head1 DESCRIPTION 43 44 Codebase for veekun.com; includes a forum, Pokedex, gallery, and other such 45 generic website things. 46 47 =cut 48 35 49 # have to get site config before setup so controller init can play with options 36 50 my $siteopt_source = 'site_options.yml'; … … 41 55 __PACKAGE__->model('DBIC')->storage->dbh->disconnect; 42 56 43 # override cookie handling to allow for session cookies 44 # this is so beautiful :D I love perl 45 #{ 46 # no strict 'refs'; 47 # no warnings 'redefine'; 48 # my $old_sub = \&Catalyst::Plugin::Session::State::Cookie::finalize_cookies; 49 # *Catalyst::Plugin::Session::State::Cookie::finalize_cookies = sub { 50 # my $c = $_[0]; 51 # local $c->config->{session}{cookie_expires} = 0 52 # if $c->session->{session_cookie}; 53 # 54 # &$old_sub( @_ ); 55 # }; 56 #} 57 =head1 METHODS 57 58 58 # shortcut to get website options (rather than app options) 59 # what can I say, I'm lazy 59 =head2 site_opts 60 61 Extremely lazy method for getting site options. Seriously, seriously lazy. 62 63 =cut 64 60 65 sub site_opts { 61 66 return shift->config->{site}; 62 67 } 63 68 64 # shortcut for generating URIs 69 =head2 uri 70 71 Shortcut for generating URIs. 72 73 $c->uri( $controller, $action, @arguments ) 74 75 =cut 76 65 77 sub uri { 66 78 my ($self, $con, $sub, @args) = @_; … … 158 170 } 159 171 160 =head1 NAME161 162 Vee - Code for veekun.com163 164 =head1 SYNOPSIS165 166 script/vee_server.pl167 168 =head1 DESCRIPTION169 170 Codebase for veekun.com; includes a forum, Pokedex, gallery, and other such171 generic website things.172 173 172 =head1 SEE ALSO 174 173 -
veekun/lib/Vee/Controller/Dex.pm
r6 r13 184 184 $c->vee_stop('No match for ', $entry, ' was found. You may wish to try the <a href="' . $c->uri('Dex', 'pokemon_list') . '">Pokémon list</a>, <a href="' . $c->uri('Dex', 'move_list') . '">move list</a>, or <a href="' . $c->uri('Dex', 'type_list') . '">type list</a> to find what you are looking for.'); 185 185 } elsif (@results == 1) { 186 $c->flash->{info_msg} = 'You entered ' , $entry,", but there is no page with that name. This page is the only close match.";186 $c->flash->{info_msg} = 'You entered ' . $c->vee_cleanse($entry) . ", but there is no page with that name. This page is the only close match."; 187 187 my $category = $results[0]{type}; 188 188 $category .= 's' unless $category eq 'pokemon'; -
veekun/lib/Vee/Controller/Users.pm
r10 r13 5 5 use base 'Catalyst::Controller'; 6 6 7 use Vee::BBCode; 8 use Vee::Utils; 7 9 use Digest::SHA1 qw/sha1_hex/; 8 10 use Image::Size; 9 11 use Email::Valid; 12 13 our @ContactTypes = ( 14 { name => 'AIM', url => '', }, 15 { name => 'ICQ', url => '', }, 16 { name => 'MSN', url => '', }, 17 { name => 'YIM', url => '', }, 18 { name => 'LJ', url => 'http://%s.livejournal.com/', }, 19 { name => 'Homepage', url => '%s', }, 20 { name => 'email', url => 'mailto:%s', }, 21 ); 10 22 11 23 =head1 NAME … … 36 48 remember => { type => 'checkbox', default => 1 }, 37 49 }; 38 39 sub pad { sprintf "%0$_[1]d", $_[0] }40 50 41 51 sub register : Local { … … 206 216 207 217 # TODO: these are probably completely unnecessary 208 209 218 $s->{postrank } = sub { Vee::Utils::postrank(shift, $c->site_opts->{post_ranks}) }; 210 $s->{postwidth } = \&Vee::Utils::post_width;211 219 $s->{postbar_color} = sub { Vee::Utils::hsv2rgb(shift, 192, 192) }; 212 220 … … 235 243 # TODO: these are probably completely unnecessary 236 244 $s->{postrank} = sub { Vee::Utils::postrank(shift, $c->site_opts->{post_ranks}) }; 237 $s->{postwidth} = \&Vee::Utils::post_width;238 245 $s->{postbar_color} = sub { Vee::Utils::hsv2rgb(shift, 192, 192) }; 239 246 … … 254 261 255 262 sub edit : Local : Args(0) { 256 my ($self, $c) = @_; 257 my $s = $c->stash; 258 my %changes; 259 my (@errors, @success); 260 261 if (!$c->user) { $c->vee_abort('You must be logged in to edit user info.'); } 263 my ($self, $c) = @_; 264 my $s = $c->stash; 265 my %changes; 266 my (@errors, @success); 267 268 if (not $c->user) { $c->vee_abort('You must be logged in to edit user info.'); } 269 270 $s->{page_title} = 'Edit Options for ' . $c->user->name; 271 $s->{link_name } = 'user/edit'; 272 $s->{crumbs } = [ '<a href="' . $c->uri('User') . 'list">Users</a>', 'Edit ' . $c->user->name ]; 273 274 $s->{userinfo} = $c->user->obj; 275 $s->{template} = 'users/edit.tt'; 276 277 return unless %{ $c->req->params }; 278 279 # Check to see what has been changed, and what hasn't (this block IGNORES avatars, it assumes it has been changed) 280 for my $k (keys %{ $c->req->params }) { 281 unless (Vee::Utils::in($k => qw/submit avatardel avatarurl avatarfile/)) { 282 $changes{$k} = $c->req->params->{$k} unless $c->req->params->{$k} eq $c->user->obj->$k; 283 } 284 if ($k eq 'avatarfile' or $k eq 'avatarurl') { $changes{avatar} = $c->req->params->{$k}; } 285 } 262 286 263 # Check to see what has been changed, and what hasn't (this block IGNORES avatars, it assumes it has been changed) 264 for my $k (keys %{ $c->req->params }) { 265 my $obj = $c->user->obj-$k; 266 unless (($k eq "submit") or ($k eq "avatardel") or ($k eq "avatarurl") or ($k eq "avatarfile")) { 267 $changes{$k} = $c->req->params->{$k} unless (lc $c->req->params->{$k} eq lc $c->user->obj->$k); 268 } 269 if (($k eq "avatarfile") or ($k eq "avatarurl")) { $changes{avatar} = $c->req->params->{$k}; } 270 } 271 272 if ($c->req->params->{submit}) { 273 # Setup various variables? 274 my $query = $c->req->params; 275 my $padid = pad($c->user->obj->id, 11); 276 my $user_limits = $c->site_opts->{user_limits}; 277 my $avmaxbytes = $user_limits->{avatarbytes}; 278 my $avmaxpixels = $user_limits->{avatarpixels}; 279 my $contacts = $user_limits->{contacts}; 280 281 # Working with avatars; to me, this seems oddly.. disorganized and messy. If anyone wants to recode it, please, be my guest. 282 if ($query->{avatardel}) { 283 # Compared to the rest, this is simple; delete the avatar? 284 unlink "root/images/avatars/" . $c->user->obj->avatar; 285 $changes{avatar} = ''; 286 push @success, "Deleted your avatar."; 287 } elsif (exists $query->{avatarfile} or exists $query->{avatarurl}) { 288 my $av; 289 # Check which method the user is trying to use for avatar: uploaded file, or URL? 290 if (exists $query->{avatarfile}) { 291 # This is for file (obviously); very straight forward, simply uploads the file. 292 $av = $c->request->upload('avatarfile'); 293 # Gets the height/width/filetype of the file 294 my ($width, $height, $type) = imgsize($av->tempname); 295 if ( my $upload = $av ) { 296 if ($avmaxbytes * 1024 < $upload->size) { push @errors, 'Filesize for avatar is bigger than ' . $avmaxbytes . ' kibibytes.'; delete $changes{avatar}; } 297 if ($width > $avmaxpixels or $height > $avmaxpixels) { push @errors, 'The height and/or width of your avatar is too large.'; delete $changes{avatar}; } 298 if (lc $type ne ('png' or 'gif' or 'jpg' or 'jpeg')) { push @errors, 'Avatar is using an invalid filetype (.' . lc $type . ').'; delete $changes{avatar}; } 299 my $target = "root/images/avatars/$padid"; 300 301 if ($changes{avatar}) { 302 unless ($upload->link_to($target) || $upload->copy_to($target) ) { $c->vee_abort("Failed to copy '" . $padid . "' to '" . $target . "': " . $!); } 303 push @success, "Updated your avatar from file $query->{avatarfile}"; 304 $changes{avatar} = $padid; 305 } 306 } 307 } elsif (exists $query->{avatarurl}) { 308 # Check to see if the filesize of the remote avatar follows the restrictions of the max avatar size. I dunno how to explain it, really; I'm sure you who is reading this can understand? 309 my $ua = new LWP::UserAgent; 310 $ua->agent( $c->site_opts->{title} ); 311 my $req = new HTTP::Request 'HEAD' => $query->{avatarurl}; 312 $req->header('Accept' => 'text/html'); 313 my $header = $ua->request($req); 314 unless ($header->is_success) { $c->vee_abort('Remote file not found; maybe you mistyped the URL?') } 315 $header = $header->headers; 316 $req = HTTP::Request->new(GET => $query->{avatarurl}); 317 $av = $ua->request($req)->content; 318 # Do error checking 319 my ($width, $height, $type) = imgsize(\$av); 320 if ($width > $avmaxpixels or $height > $avmaxpixels) { push @errors, 'The height and/or width of your avatar is too large.'; delete $changes{avatar}; } 321 if (lc $type ne ('png' or 'gif' or 'jpg' or 'jpeg')) { push @errors, 'Avatar is using an invalid filetype (.' . lc $type . ').'; delete $changes{avatar}; } 322 if ($avmaxbytes * 1024 < $header->content_length) { push @errors, 'Filesize for avatar is bigger than ' . $avmaxbytes . ' kibibytes.'; delete $changes{avatar}; } 323 # Okay, we're good; copy the file to $padid (which is the user's id)! 324 if ($changes{avatar}) { open AVATAR, ">root/images/avatars/" . $padid; binmode AVATAR; print AVATAR $av; close AVATAR; $changes{avatar} = $padid; } 287 # Setup various variables? 288 my $query = $c->req->params; 289 my $padid = Vee::Utils::pad($c->user->obj->id, 11); 290 my $user_limits = $c->site_opts->{user_limits}; 291 my $avmaxbytes = $user_limits->{avatarbytes}; 292 my $avmaxpixels = $user_limits->{avatarpixels}; 293 my $contacts = $user_limits->{contacts}; 294 295 # Working with avatars; to me, this seems oddly.. disorganized and messy. If anyone wants to recode it, please, be my guest. 296 if ($query->{avatardel}) { 297 # Compared to the rest, this is simple; delete the avatar? 298 unlink $c->path_to('root/images/avatars', $c->user->obj->avatar); 299 $changes{avatar} = ''; 300 push @success, "Deleted your avatar."; 301 302 } elsif (exists $query->{avatarfile} or exists $query->{avatarurl}) { 303 my $av; 304 305 # Check which method the user is trying to use for avatar: uploaded file, or URL? 306 if (exists $query->{avatarfile}) { 307 # This is for file (obviously); very straight forward, simply uploads the file. 308 $av = $c->request->upload('avatarfile'); 309 310 # Gets the height/width/filetype of the file 311 my ($width, $height, $type) = imgsize($av->tempname); 312 if ($avmaxbytes * 1024 < $av->size) { push @errors, 'Filesize for avatar is bigger than maximum of ' . $avmaxbytes . ' kibibytes.'; delete $changes{avatar}; } 313 if (not Vee::Utils::in(lc $type => qw/png gif jpg jpeg/)) { push @errors, 'Avatar is using an invalid filetype (' . lc $type . ').'; delete $changes{avatar}; } 314 if ($width > $avmaxpixels or $height > $avmaxpixels) { push @errors, 'The height and/or width of your avatar is too large.'; delete $changes{avatar}; } 315 316 my $target = "root/images/avatars/$padid"; 317 if ($changes{avatar}) { 318 unless ($av->link_to($target) || $av->copy_to($target) ) { $c->vee_abort("Failed to copy '" . $padid . "' to '" . $target . "': " . $!); } 319 push @success, "Updated your avatar from file $query->{avatarfile}"; 320 $changes{avatar} = $padid; 325 321 } 326 } 327 # Working with text data (sigs, title, etc) 328 # Title 329 if ((!exists $c->req->params->{customtitle}) and ($c->user->obj->customtitle)) { push @success, 'Deleted your custom title.'; $changes{customtitle} = ''; } 330 if ($changes{customtitle}) { 331 if (length $query->{customtitle} >= $user_limits->{customtitle}) { push @errors, 'Custom title is too long; please make a shorter one (max is ' . $user_limits->{customtitle} . ' characters)'; delete $changes{customtitle}; } 332 if ($changes{customtitle}) { push @success, 'Updated your custom title to "' . $changes{customtitle} . '".'; } 333 } 334 # Various contacts (AIM, MSN, ICQ, etc) 335 for my $k (split(' ', $contacts)) { 336 my $join = "contact_" . lc $k; 337 if ((!exists $c->req->params->{$join}) and ($c->user->obj->$join)) { push @success, 'Deleted your ' . $k . ' contact information.'; $changes{$join} = ''; } 338 if ($changes{$join}) { 339 # Validate email (and MSN!) to RFC822 340 if ((lc $k eq 'email') or (lc $k eq 'msn')) { if (($changes{$join}) and (!Email::Valid->address($query->{$join}))) { push @errors, 'The ' . $k . ' address ' . $changes{$join} . ' is invalid.'; delete $changes{$join}; } } 341 if (exists $changes{$join} and ($k ne 'homepage')) { push @success, 'Updated your ' . $k . ' contact information to ' . $changes{$join} . '.'; } 342 elsif (exists $changes{$join} and ($k eq 'homepage')) { push @success, 'Updated your homepage to: ' . $changes{contact_homepage}; } 343 } 344 } 345 # Signature 346 if ((!exists $c->req->params->{signature}) and ($c->user->obj->signature)) { push @success, 'Deleted your signature.'; $changes{signature} = ''; } 347 if ($changes{signature}) { 348 ($changes{signature}, my @bbcode_errors) = Vee::BBCode::validate_bbcode( $changes{signature} ); 349 if (@bbcode_errors) { push @errors, 'Your signature contains invalid bbcode; please go back and fix it.'; delete $changes{signature}; } 350 if (exists $changes{signature}) { push @success, 'Updated your signature.'; } 351 } 352 353 if (@success) { $s->{success_msg} = join('<br />', @success); } 354 if (@errors) { $s->{error_msg} = (join('<br/>', @errors)); } 355 $c->user->obj->update(\%changes); 356 } 357 $s->{userinfo} = $c->user->obj; 358 $s->{template} = 'users/edit.tt'; 322 323 } elsif (exists $query->{avatarurl}) { 324 # Check to see if the filesize of the remote avatar follows the restrictions of the max avatar size. I dunno how to explain it, really; I'm sure you who is reading this can understand? 325 my $ua = new LWP::UserAgent; 326 $ua->agent( $c->site_opts->{title} ); 327 $ua->env_proxy; 328 $ua->protocols_allowed([ 'http', 'https' ]); 329 $ua->timeout(10); # this is pretty low, but we don't want to keep the user waiting for too long 330 331 my $req = new HTTP::Request('HEAD' => $query->{avatarurl}); 332 $req->header('Accept' => 'text/html'); 333 334 my $response = $ua->request($req); 335 unless ($response->is_success) { $c->vee_abort('Remote file not found; maybe the server is down or you mistyped the URL?') } 336 my $header = $response->headers; 337 $req = HTTP::Request->new(GET => $query->{avatarurl}); 338 $av = $ua->request($req)->content; 339 340 # Do error checking 341 my ($width, $height, $type) = imgsize(\$av); 342 if ($width > $avmaxpixels or $height > $avmaxpixels) { push @errors, 'The height and/or width of your avatar is too large.'; delete $changes{avatar}; } 343 if (not Vee::Utils::in(lc $type => qw/png gif jpg jpeg/)) { push @errors, 'Avatar is using an invalid filetype (.' . lc $type . ').'; delete $changes{avatar}; } 344 if ($avmaxbytes * 1024 < $header->content_length) { push @errors, 'Filesize for avatar is bigger than ' . $avmaxbytes . ' kibibytes.'; delete $changes{avatar}; } 345 346 # Okay, we're good; copy the file to $padid (which is the user's id)! 347 if ($changes{avatar}) { open AVATAR, '>' . $c->path_to('root/images/avatars', $padid); binmode AVATAR; print AVATAR $av; close AVATAR; $changes{avatar} = $padid; } 348 } 349 } 350 351 # Working with text data (sigs, title, etc) 352 # Title 353 if ($changes{customtitle}) { 354 if (length $query->{customtitle} >= $user_limits->{customtitle}) { 355 push @errors, 'Custom title is longer than the maximum of ' . $user_limits->{customtitle} . ' characters.'; 356 delete $changes{customtitle}; 357 } 358 if ($changes{customtitle}) { push @success, 'Updated your custom title to "' . $changes{customtitle} . '".'; } 359 } elsif (exists $changes{customtitle} and $c->user->customtitle) { 360 push @success, 'Deleted your custom title.'; 361 } 362 363 # Various contacts (AIM, MSN, ICQ, etc) 364 for my $contact_row (@ContactTypes) { 365 my $k = $contact_row->{name}; 366 my $join = "contact_" . lc $k; 367 next unless exists $changes{$join}; 368 if (not $c->req->params->{$join} and $c->user->obj->$join) { 369 push @success, 'Deleted your ' . $k . ' contact information.'; 370 $changes{$join} = ''; 371 next; 372 } 373 if ($changes{$join}) { 374 # Validate email (and MSN!) to RFC822 375 if ((lc $k eq 'email' or lc $k eq 'msn') and not Email::Valid->address($changes{$join})) { 376 push @errors, 'The ' . $k . ' address ' . $changes{$join} . ' is invalid.'; 377 delete $changes{$join}; 378 next; 379 } 380 if ($k eq 'homepage') { 381 push @success, 'Updated your homepage to: ' . $changes{contact_homepage}; 382 } else { 383 push @success, 'Updated your ' . $k . ' contact information to ' . $changes{$join} . '.'; 384 } 385 } 386 } 387 388 # Signature 389 if ($changes{signature}) { 390 ($changes{signature}, my @bbcode_errors) = Vee::BBCode::validate_bbcode( $changes{signature} ); 391 if (@bbcode_errors) { 392 push @errors, 'Your signature contains invalid bbcode; please go back and fix it.'; 393 delete $changes{signature}; 394 next; 395 } 396 push @success, 'Updated your signature.'; 397 } elsif (exists $changes{signature} and $c->user->signature) { 398 push @success, 'Deleted your signature.'; 399 } 400 401 $s->{success_msg} = \@success if @success; 402 $s->{error_msg} = \@errors if @errors; 403 $c->user->obj->update(\%changes); 359 404 } 360 405 -
veekun/lib/Vee/View/TT.pm
r1 r13 29 29 # forum stuff... 30 30 post_width => \&Vee::Utils::post_width, 31 postrank => sub { Vee::Utils::postrank(shift, Vee->site_opts->{post_ranks}) }, 32 postbar_color => sub { Vee::Utils::hsv2rgb(shift, 192, 192) }, 31 33 32 34 # forum stuff... -
veekun/site_options.yml
r8 r13 66 66 avatarpixels: 100 67 67 customtitle: 30 68 contacts: AIM ICQ MSN YIM LJ Homepage email69 68 70 69 # Number of seconds before a user is considered inactive … … 72 71 73 72 # Number of posts => rank you get 74 post ranks:73 post_ranks: 75 74 0: Uninterested 76 75 12: Lurker -
veekun/templates/forum/common.tt
r1 r13 33 33 [% IF shorthand == 'email' OR shorthand == 'msn'; value = value | email_text; END %] 34 34 [% DEFAULT value = 'none' %] 35 [% IF url %]<a href="[% url.replace('%s', value) -%]">[% END %]<img src="/images/ icons/[% shorthand %].png" alt="[% name %]: [% value %]" title="[% name %]: [% value %]"[% IF value == 'none' %] class="disabled"[% END %]/>[% IF url %]</a>[% END %]35 [% IF url %]<a href="[% url.replace('%s', value) -%]">[% END %]<img src="/images/contact/icons/[% shorthand %].png" alt="[% name %]: [% value %]" title="[% name %]: [% value %]"[% IF value == 'none' %] class="disabled"[% END %]/>[% IF url %]</a>[% END %] 36 36 [% END %] 37 37 <img src="/images/icons/pm/[% user.pmicon %].png" alt="Send private message" title="Send private message" class="disabled"/> -
veekun/templates/users/edit.tt
r8 r13 5 5 <form action='/users/edit' method='post' enctype="multipart/form-data"> 6 6 <h3>Contact</h3> 7 <p> <label><img src="/images/icons/ aim.png" alt="AIM"/> <input type='text' size='32' name='contact_aim' value='[% userinfo.contact_aim %]'/> AOL Instant Messenger </p></label>8 <p> <label><img src="/images/icons/ icq.png" alt="ICQ"/> <input type='text' size='32' name='contact_icq' value='[% userinfo.contact_icq %]'/> ICQ </p></label>9 <p> <label><img src="/images/icons/ msn.png" alt="MSN"/> <input type='text' size='32' name='contact_msn' value='[% userinfo.contact_msn %]'/> MSN Messenger </p></label>10 <p> <label><img src="/images/icons/ yim.png" alt="YIM"/> <input type='text' size='32' name='contact_yim' value='[% userinfo.contact_yim %]'/> Yahoo! Instant Messenger </p></label>11 <p> <label><img src="/images/icons/ lj.png" alt="LJ"/> <input type='text' size='32' name='contact_lj' value='[% userinfo.contact_lj %]'/> LiveJournal username </p></label>12 <p> <label><img src="/images/icons/ homepage.png" alt=""/> <input type='text' size='32' name='contact_homepage' value='[% userinfo.contact_homepage %]'/> Website </p></label>13 <p> <label><img src="/images/icons/ email.png" alt=""/> <input type='text' size='32' name='contact_email' value='[% userinfo.contact_email %]'/> Email address </p></label>7 <p> <label><img src="/images/icons/contact/aim.png" alt="AIM"/> <input type='text' size='32' name='contact_aim' value='[% userinfo.contact_aim %]'/> AOL Instant Messenger </p></label> 8 <p> <label><img src="/images/icons/contact/icq.png" alt="ICQ"/> <input type='text' size='32' name='contact_icq' value='[% userinfo.contact_icq %]'/> ICQ </p></label> 9 <p> <label><img src="/images/icons/contact/msn.png" alt="MSN"/> <input type='text' size='32' name='contact_msn' value='[% userinfo.contact_msn %]'/> MSN Messenger </p></label> 10 <p> <label><img src="/images/icons/contact/yim.png" alt="YIM"/> <input type='text' size='32' name='contact_yim' value='[% userinfo.contact_yim %]'/> Yahoo! Instant Messenger </p></label> 11 <p> <label><img src="/images/icons/contact/lj.png" alt="LJ"/> <input type='text' size='32' name='contact_lj' value='[% userinfo.contact_lj %]'/> LiveJournal username </p></label> 12 <p> <label><img src="/images/icons/contact/homepage.png" alt=""/> <input type='text' size='32' name='contact_homepage' value='[% userinfo.contact_homepage %]'/> Website </p></label> 13 <p> <label><img src="/images/icons/contact/email.png" alt=""/> <input type='text' size='32' name='contact_email' value='[% userinfo.contact_email %]'/> Email address </p></label> 14 14 <h3>Title</h3> 15 15 <p> <label><input type='text' size='36' name='customtitle' value='[% userinfo.customtitle %]'/> Custom title</label> </p> -
veekun/templates/users/info.tt
r1 r13 24 24 [% IF shorthand == 'email' OR shorthand == 'msn'; value = value | email_text; END %] 25 25 [% DEFAULT value = 'none' %] 26 <p> [% IF url %]<a href="[% url.replace('%s', value) %]">[% END %]<img src="/images/ icons/[% shorthand %].png" alt="[% name %]: [% value %]" title="[% name %]: [% value %]"[% IF value == 'none' %] class="disabled"[% END %]/> [% name %]: [%+ value %] [%+ IF url %]</a> </p>[% END %]26 <p> [% IF url %]<a href="[% url.replace('%s', value) %]">[% END %]<img src="/images/contact/icons/[% shorthand %].png" alt="[% name %]: [% value %]" title="[% name %]: [% value %]"[% IF value == 'none' %] class="disabled"[% END %]/> [% name %]: [%+ value %] [%+ IF url %]</a> </p>[% END %] 27 27 [% END %] 28 28 <p> <img src="/images/icons/pm/[% user.pmicon %].png" alt="Send private message" title="Send private message" class="disabled"/> Private messages: not yet </p>
