1############################################################################### 2# ExtendedProfiles.pm # 3# $Date: 12.02.14 $ # 4############################################################################### 5# YaBB: Yet another Bulletin Board # 6# Version: YaBB 2.6.11 # 7# Packaged: December 2, 2014 # 8# Distributed by: http://www.yabbforum.com # 9# =========================================================================== # 10# Copyright (c) 2000-2014 YaBB (www.yabbforum.com) - All Rights Reserved. # 11# Software by: The YaBB Development Team # 12# with assistance from the YaBB community. # 13############################################################################### 14# This file was part of the Extended Profiles Mod which has been created by # 15# Michael Prager. Last modification by him: 15.11.07 # 16# Added to the YaBB default code on 07. September 2008 # 17############################################################################### 18our $VERSION = '2.6.11'; 19 20$extendedprofilespmver = 'YaBB 2.6.11 $Revision: 1611 $'; 21if ( $action eq 'detailedversion' ) { return 1; } 22 23LoadLanguage('ExtendedProfiles'); 24 25$ext_spacer_hr = q~<hr class="hr" />~; 26$ext_spacer_br = q~<br />~; 27$ext_max_email_length = 60; 28$ext_max_url_length = 100; 29$ext_max_image_length = 100; 30 31my %field; 32 33# outputs the value of a user's extended profile field 34## USAGE: $value = ext_get("admin","my_custom_fieldname"); 35## or $value_raw = ext_get("admin","my_custom_fieldname",1); 36## pass the third argument if you want to get the raw content e.g. an unformatted date 37sub ext_get { 38 my ( 39 $pusername, $fieldname, $no_parse, @ext_profile, 40 @options, $field, $id, $value, 41 $width, $height, @allowed_extensions, $extension, 42 $match 43 ) = ( shift, shift, shift ); 44 ext_get_profile($pusername); 45 $id = ext_get_field_id($fieldname); 46 $value = ${ $uid . $pusername }{ 'ext_' . $id }; 47 if ( $no_parse eq q{} || $no_parse == 0 ) { 48 $field = ext_get_field($id); 49 if ( $field{'type'} eq 'text' ) { 50 @options = split /\^/xsm, $field{'options'}; 51 if ( $options[3] ne q{} && $value eq q{} ) { $value = $options[3]; } 52 if ( $options[4] == 1 ) { 53 $value = ext_parse_ubbc( $value, $pusername ); 54 } 55 56 } 57 elsif ( $field{'type'} eq 'text_multi' && $value ne q{} ) { 58 @options = split /\^/xsm, $field{'options'}; 59 if ( $options[3] == 1 ) { 60 $value = ext_parse_ubbc( $value, $pusername ); 61 } 62 63 } 64 elsif ( $field{'type'} eq 'select' ) { 65 @options = split /\^/xsm, $field{'options'}; 66 if ( $value > $#options || $value eq q{} ) { $value = 0; } 67 $value = $options[$value]; 68 69 } 70 elsif ( $field{'type'} eq 'radiobuttons' ) { 71 @options = split /\^/xsm, $field{'options'}; 72 if ( $value > $#options ) { $value = 0; } 73 if ( !$field{'radiounselect'} && $value eq q{} ) { $value = 0; } 74 if ( $value ne q{} ) { $value = $options[$value]; } 75 76 } 77 elsif ( $field{'type'} eq 'date' && $value ne q{} ) { 78 @mytime = split /\//xsm, $value; 79 $mytime = timelocal(0,0,0, $mytime[1],$mytime[0]-1,$mytime[2]); 80 $mytime = timeformatcal($mytime); 81 $value = dtonly ($mytime); 82 } 83 elsif ( $field{'type'} eq 'checkbox' ) { 84 if ( $value == 1 ) { $value = $lang_ext{'true'} } 85 else { $value = $lang_ext{'false'} } 86 87 } 88 elsif ( $field{'type'} eq 'spacer' ) { 89 @options = split /\^/xsm, $field{'options'}; 90 if ( $options[0] == 1 ) { $value = qq~$ext_spacer_br~; } 91 else { $value = qq~$ext_spacer_hr~; } 92 93 } 94 elsif ( $field{'type'} eq 'url' && $value ne q{} ) { 95 if ( $value !~ m{\Ahttp://}sm ) { $value = "http://$value"; } 96 97 } 98 elsif ( $field{'type'} eq 'image' && $value ne q{} ) { 99 @options = split /\^/xsm, $field{'options'}; 100 if ( $options[2] ne q{} ) { 101 @allowed_extensions = split /\ /xsm, $options[2]; 102 $match = 0; 103 foreach my $extension (@allowed_extensions) { 104 if ( grep { /$extension$/ism } $value ) { 105 $match = 1; 106 last; 107 } 108 } 109 if ( $match == 0 ) { return q{}; } 110 } 111 if ( $options[0] ne q{} && $options[0] != 0 ) { 112 $width = q~ width="~ . ( $options[0] + 0 ) . q~"~; 113 } 114 else { $width = q{}; } 115 if ( $options[1] ne q{} && $options[1] != 0 ) { 116 $height = q~ height="~ . ( $options[1] + 0 ) . q~"~; 117 } 118 else { $height = q{}; } 119 if ( $value !~ m{\Ahttp://}sm ) { $value = "http://$value"; } 120 $value = qq~<img src="$value" class="vtop"$width$height alt=q{} />~; 121 } 122 } 123 124 return $value; 125} 126 127# loads the (extended) profile of a user 128sub ext_get_profile { 129 LoadUser(shift); 130 return; 131} 132 133# returns an array of the form qw(ext_0 ext_1 ext_2 ...) 134sub ext_get_fields_array { 135 my ( $count, @result ) = (0); 136 foreach (@ext_prof_fields) { 137 push @result, "ext_$count"; 138 $count++; 139 } 140 return @result; 141} 142 143# returns the id of a field through the fieldname 144sub ext_get_field_id { 145 my ( $fieldname, $count, $id, $current, $currentname, $dummy ) = 146 ( shift, 0 ); 147 foreach my $current (@ext_prof_fields) { 148 ( $currentname, $dummy ) = split /\|/xsm, $current; 149 if ( $currentname eq $fieldname ) { $id = $count; last; } 150 $count++; 151 } 152 return $id; 153} 154 155# returns all settings of a specific field 156sub ext_get_field { 157 $field{'id'} = shift; 158 159 ( 160 $field{'name'}, $field{'type'}, 161 $field{'options'}, $field{'active'}, 162 $field{'comment'}, $field{'required_on_reg'}, 163 $field{'visible_in_viewprofile'}, $field{'v_users'}, 164 $field{'v_groups'}, $field{'visible_in_posts'}, 165 $field{'p_users'}, $field{'p_groups'}, 166 $field{'p_displayfieldname'}, $field{'visible_in_memberlist'}, 167 $field{'m_users'}, $field{'m_groups'}, 168 $field{'editable_by_user'}, $field{'visible_in_posts_popup'}, 169 $field{'pp_users'}, $field{'pp_groups'}, 170 $field{'pp_displayfieldname'}, $field{'radiounselect'}, 171 undef 172 ) = split /\|/xsm, $ext_prof_fields[ $field{'id'} ]; 173 return; 174} 175 176# returns whenever the current user is allowed to view a field or not 177sub ext_has_access { 178 my ( 179 $allowed_users, $allowed_groups, $access, $usergroup, 180 $useraddgroup, $postcount, $user, @users, 181 $group, @groups, $groupid, $postamount 182 ) 183 = ( 184 shift, shift, 0, 185 ${ $uid . $username }{'position'}, 186 ${ $uid . $username }{'addgroups'}, 187 ${ $uid . $username }{'postcount'}, undef, 188 ); 189 190 if ( ( $allowed_users ne q{} ) || ( $allowed_groups ne q{} ) ) { 191 if ( $allowed_users ne q{} ) { 192 @users = split /\,/xsm, $allowed_users; 193 foreach my $user (@users) { 194 if ( $user eq $username ) { $access = 1; return $access; } 195 } 196 } 197 if ( $allowed_groups ne q{} ) { 198 199# generate list of allowed groups 200# example: @groups = ('Administrator', 'Moderator', 'Global Moderator', 'Post{-1}', 'NoPost{1}'); 201 @groups = split /\s*\,\s*/xsm, $allowed_groups; 202 for my $group (@groups) { 203 204 # check if user is in one of these groups 205 if ( $group eq 'Administrator' 206 || $group eq 'Moderator' 207 || $group eq 'Mid Moderator' 208 || $group eq 'Global Moderator' ) 209 { 210 if ( $group eq $usergroup ) { $access = 1; return $access; } 211 } 212 elsif ( $group =~ m/^NoPost{(\d+)}$/sm ) { 213 214 # check if user is on a post-independent group 215 $groupid = $1; 216 217 # check if group exists at all 218 if ( exists $NoPost{$groupid} && $groupid ne q{} ) { 219 220 # check if group id is in user position or addgroup field 221 if ( $usergroup eq $groupid ) { 222 $access = 1; 223 return $access; 224 } 225 foreach my $group ( split /,/xsm, $useraddgroup ) { 226 if ( $group eq $groupid ) { 227 $access = 1; 228 return $access; 229 } 230 } 231 } 232 } 233 elsif ( $group =~ m/^Post{(\d+)}$/sm ) { 234 235 # check if user is in one of the post-depending groups... 236 $groupid = $1; 237 foreach my $postamount ( reverse sort { $a <=> $b } keys %Post ) { 238 if ( $postcount > $postamount ) { 239 240 # found the group the user is in 241 if ( $postamount eq $groupid ) { 242 $access = 1; 243 return $access; 244 } 245 } 246 } 247 } 248 } 249 } 250 } 251 else { $access = 1; } 252 253 return $access; 254} 255 256# applies UBBC code to a string 257sub ext_parse_ubbc { 258 my ( $source, $displayname ) = @_; 259 my $temp = $message; 260 $message = $source; 261 require Sources::YaBBC; 262 $displayname = $pusername; # must be set for /me tag 263 DoUBBC(); 264 ToChars($message); 265 $source = $message; 266 $message = $temp; 267 return $source; 268} 269 270# returns the output for the viewprofile page 271sub ext_viewprofile { 272 my ( 273 $pusername, @ext_profile, $field, $id, 274 $output, $fieldname, @options, $value, 275 $previous, $count, $last_field_id, $pre_output 276 ) = (shift); 277 278 if ( $#ext_prof_order > 0 ) { 279 $last_field_id = ext_get_field_id( $ext_prof_order[-1] ); 280 } 281 282 foreach my $fieldname (@ext_prof_order) { 283 $id = ext_get_field_id($fieldname); 284 ext_get_field($id); 285 $value = ext_get( $pusername, $fieldname ); 286 287 # make sure the field is visible and the user allowed to view the current field 288 if ( $field{'visible_in_viewprofile'} == 1 289 && $field{'active'} == 1 290 && ext_has_access( $field{'v_users'}, $field{'v_groups'} ) ) 291 { 292 if ( $output eq q{} && $previous != 1 ) { 293 $pre_output = $ext_pre_output; 294 $previous = 1; 295 } 296 297 # format the output dependend of the field type 298 if ( ( $field{'type'} eq 'text' && $value ne q{} ) 299 || ( $field{'type'} eq 'text_multi' && $value ne q{} ) 300 || ( $field{'type'} eq 'select' && $value ne q{ } ) 301 || ( $field{'type'} eq 'radiobuttons' && $value ne q{} ) 302 || ( $field{'type'} eq 'date' && $value ne q{} ) 303 || $field{'type'} eq 'checkbox' ) 304 { 305 $output .= qq~ 306 <div class="ext_lft"> 307 <b>$field{'name'}:</b> 308 </div> 309 <div class="ext_rgt"> 310 $value 311 </div>~; 312 $previous = 0; 313 314 } 315 elsif ( $field{'type'} eq 'spacer' ) { 316 317# only print spacer if the previous entry was no spacer of the same type and if this is not the last entry 318 if ( ( $previous == 0 || $field{'comment'} ne q{} ) 319 && $id ne $last_field_id ) 320 { 321 if ( $value eq $ext_spacer_br ) { 322 $output .= qq~ 323 <div class="ext_100"> 324 $ext_spacer_br 325 </div>~; 326 $previous = 0; 327 } 328 else { 329 $output .= $ext_output_a; 330 if ( $field{'comment'} ne q{} ) { 331 $output .= $ext_output_c; 332 } 333 else { 334 $output .= $ext_output_b; 335 } 336 $previous = 1; 337 } 338 } 339 340 } 341 elsif ( $field{'type'} eq 'email' && $value ne q{} ) { 342 $output .= qq~ 343 <div class="ext_lft"> 344 <b>$field{'name'}:</b> 345 </div> 346 <div class="ext_rgt"> 347 ~ . enc_eMail( $img_txt{'69'}, $value, q{}, q{} ) . q~ 348 </div>~; 349 $previous = 0; 350 351 } 352 elsif ( $field{'type'} eq 'url' && $value ne q{} ) { 353 $output .= qq~ 354 <div class="ext_lft"> 355 <b>$field{'name'}:</b> 356 </div> 357 <div class="ext_rgt"> 358 <a href="$value" target="_blank">$value</a> 359 </div>~; 360 $previous = 0; 361 362 } 363 elsif ( $field{'type'} eq 'image' && $value ne q{} ) { 364 $output .= qq~ 365 <div class="ext_lft"> 366 <b>$field{'name'}:</b> 367 </div> 368 <div class="ext_rgt"> 369 $value 370 </div>~; 371 $previous = 0; 372 } 373 } 374 } 375 376 # only add spacer if there there is at least one field displayed 377 if ( $output ne q{} ) { 378 $output = $pre_output . $output . q~ 379 </td> 380 </tr>~; 381 } 382 return $output; 383} 384 385# returns the output for the post page 386sub ext_viewinposts { 387 my ( 388 $pusername, $popup, @ext_profile, $field, 389 $id, $output, $fieldname, @options, 390 $value, $previous, $pre_output, $visible, 391 $users, $groups, $displayfieldname 392 ) = ( shift, shift ); 393 394 if ( $pusername ne 'Guest' ) { 395 foreach my $fieldname (@ext_prof_order) { 396 $id = ext_get_field_id($fieldname); 397 $field = ext_get_field($id); 398 $value = ext_get( $pusername, $fieldname ); 399 400 if ( $popup ne q{} ) { 401 $visible = $field{'visible_in_posts_popup'}; 402 $users = $field{'pp_users'}; 403 $groups = $field{'pp_groups'}; 404 $displayfieldname = $field{'pp_displayfieldname'}; 405 } 406 else { 407 $visible = $field{'visible_in_posts'}; 408 $users = $field{'p_users'}; 409 $groups = $field{'p_groups'}; 410 $displayfieldname = $field{'p_displayfieldname'}; 411 } 412 413 # make sure the field is visible and the user allowed to view the current field 414 if ( $visible == 1 415 && $field{'active'} == 1 416 && ext_has_access( $users, $groups ) ) 417 { 418 if ( $displayfieldname == 1 ) { 419 $displayedfieldname = "$field{'name'}: "; 420 } 421 else { $displayedfieldname = q{}; } 422 if ( $output eq q{} ) { $output = qq~$ext_spacer_br\n~; } 423 424 # format the output depending on the field type 425 if ( ( $field{'type'} eq 'text' && $value ne q{} ) 426 || ( $field{'type'} eq 'text_multi' && $value ne q{} ) 427 || ( $field{'type'} eq 'select' && $value ne q{ } ) 428 || ( $field{'type'} eq 'radiobuttons' && $value ne q{} ) 429 || ( $field{'type'} eq 'date' && $value ne q{} ) 430 || $field{'type'} eq 'checkbox' ) 431 { 432 $output .= qq~$displayedfieldname$value<br />\n~; 433 $previous = q{}; 434 } 435 elsif ( $field{'type'} eq 'spacer' ) { 436 437 # those tags are required to keep the doc XHTML 1.0 valid 438 if ( $previous ne "</small>$value<small>" ) { 439 $previous = qq~</small>$value<small>~; 440 $output .= $previous; 441 } 442 } 443 elsif ( $field{'type'} eq 'email' && $value ne q{} ) { 444 $output .= 445 $displayedfieldname 446 . enc_eMail( $img_txt{'69'}, $value, q{}, q{} ) 447 . qq~<br />\n~; 448 $previous = q{}; 449 } 450 elsif ( $field{'type'} eq 'url' && $value ne q{} ) { 451 $output .= 452qq~$displayedfieldname<a href="$value" target="_blank">$value</a><br />\n~; 453 $previous = q{}; 454 } 455 elsif ( $field{'type'} eq 'image' && $value ne q{} ) { 456 $output .= qq~$displayedfieldname$value<br />\n~; 457 $previous = q{}; 458 } 459 } 460 } 461 } 462 463# check if there we have any output (except spacers) at all. If so, return empty output 464 $pre_output = $output; 465 $pre_output =~ 466s/(?:\<\/small>(?:(?:$ext_spacer_hr)|(?:$ext_spacer_br))<small>)|\n|(?:\<br(?: \/)?>)//igsm; 467 if ( $pre_output eq q{} ) { $output = q{}; } 468 469 return $output; 470} 471 472{ 473 474 # we need a "static" variable to produce unique element ids 475 my $ext_usercount = 0; 476 477 # returns the output for the post page (popup box) 478 sub ext_viewinposts_popup { 479 my ( $pusername, $link, $output ) = ( shift, shift ); 480 $output = ext_viewinposts( $pusername, 'popup' ); 481 $output =~ s/^$ext_spacer_br\n//igxsm; 482 if ( $output ne q{} ) { 483 $link =~ 484s/<a /<a onmouseover="document.getElementById('ext_$ext_usercount').style.visibility = 'visible'" onmouseout="document.getElementById('ext_$ext_usercount').style.visibility = 'hidden'" /igsm; 485 $output = 486qq~$link<div id="ext_$ext_usercount" class="code" style="visibility:hidden; position:absolute; z-index:1; width:auto;">$output</div>~; 487 $ext_usercount++; 488 } 489 else { 490 $output = $link; 491 } 492 493 return $output; 494 } 495} 496 497# returns the output for the table header in memberlist 498sub ext_memberlist_tableheader { 499 my ( $output, $fieldname ); 500 501 foreach my $fieldname (@ext_prof_order) { 502 $field = ext_get_field( ext_get_field_id($fieldname) ); 503 504 # make sure the field is visible and the user allowed to view the current field 505 if ( $field{'visible_in_memberlist'} == 1 506 && $field{'active'} == 1 507 && ext_has_access( $field{'m_users'}, $field{'m_groups'} ) ) 508 { 509 $output .= $ext_memberlist_tableheader; 510 $output =~ s/{yabb ext_fieldname}/$field{'name'}/sm; 511 } 512 } 513 514 return $output; 515} 516 517# returns the number of additional fields showed in memberlist 518sub ext_memberlist_get_headercount { 519 520# count the linebreaks to get the number of additional <td>s for the memberlist table 521 my ( $headers, $headercount ) = ( shift, 0 ); 522 $headers =~ s/(\n)/ $headercount++ /egm; 523 return $headercount; 524} 525 526# returns the output for the table tds in memberlist 527sub ext_memberlist_tds { 528 my ( 529 $pusername, $usergroup, @ext_profile, $field, 530 $id, $output, $access, @users, 531 $user, @groups, $group, $fieldname, 532 @options, $count, $color, $value 533 ) = ( shift, ${ $uid . $username }{'position'} ); 534 535 $count = 0; 536 foreach my $fieldname (@ext_prof_order) { 537 $id = ext_get_field_id($fieldname); 538 $field = ext_get_field($id); 539 $value = ext_get( $pusername, $fieldname ); 540 541 # make sure the field is visible and the user allowed to view the current field 542 if ( $field{'visible_in_memberlist'} == 1 543 && $field{'active'} == 1 544 && ext_has_access( $field{'m_users'}, $field{'m_groups'} ) == 1 ) 545 { 546 $color = $count % 2 == 1 ? 'windowbg' : 'windowbg2'; 547 548 $td_attributs = qq~class="$color"~; 549 550 #} 551 if ( $field{'type'} eq 'email' ) { 552 if ( $value ne q{} ) { 553 $value = enc_eMail( $img_txt{'69'}, $value, q{}, q{} ); 554 } 555 } 556 elsif ( $field{'type'} eq 'url' ) { 557 if ( $value ne q{} ) { 558 $value = qq~<a href="$value" target="_blank">$value</a>~; 559 } 560 } 561 if ( $value eq q{} ) { $value .= ' '; } 562 $output .= $ext_memberlist_td; 563 $output =~ s/{yabb ext_td_attributs}/$td_attributs/sm; 564 $output =~ s/{yabb ext_value}/$value/sm; 565 $count++; 566 } 567 } 568 return $output; 569} 570 571# returns the edit mask of a field (used on registration and edit profile page) 572sub ext_gen_editfield { 573 my ( 574 $id, $pusername, @ext_profile, $output, 575 $field, @options, $selected, $count, 576 $required_prefix, $dayormonth, $dayormonthd, $dayormonthm, 577 $value, $template1, $template2 578 ) = ( shift, shift ); 579 580 LoadLanguage('Profile'); 581 if ( $action eq 'register' ) { 582 get_template('Register'); 583 } 584 else { 585 get_template('MyProfile'); 586 } 587 588 $field = ext_get_field($id); 589 590 # if username is omitted, we'll generate the code for the registration page 591 if ( $pusername ne q{} ) { 592 $value = ext_get( $pusername, $field{'name'}, 1 ); 593 } 594 595 FromHTML( $field{'comment'} ); 596 597 $template1 = $ext_template1; 598 $template1 =~ s/{yabb fieldname}/$field{'name'}/sm; 599 $template1 =~ s/{yabb fieldcomment}/$field{'comment'}/sm; 600 601 if ( $field{'required_on_reg'} == 1 ) { $template2 = $myreg_req; } 602 $template2 .= $ext_endrow; 603 604 # format the output depending on field type 605 my $name_id = "ext_$id"; 606 if ( $field{'type'} eq 'text' ) { 607 @options = split /\^/xsm, $field{'options'}; 608 if ( $options[0] ne q{} ) { 609 $options[0] = qq~ maxlength="$options[0]"~; 610 } 611 if ( $options[1] ne q{} ) { $options[1] = qq~ size="$options[1]"~; } 612 if ( $options[3] ne q{} && $value eq q{} ) { 613 $options[3] = qq~ value="$options[3]"~; 614 } 615 else { $options[3] = qq~ value="$value"~; } 616 $output .= 617 $template1 618 . qq~<input type="text"$options[0] name="ext_$id" id="ext_$id"$options[1] $options[3] />~ 619 . $template2; 620 621 } 622 elsif ( $field{'type'} eq 'text_multi' ) { 623 @options = split /\^/xsm, $field{'options'}; 624 if ( $options[0] ) { 625 $field{'options'} = qq~ 626 <br /><span class="small">$lang_ext{'max_chars1'}$options[0]$lang_ext{'max_chars2'} <input value="$options[0]" size="~ 627 . length( $options[0] ) 628 . q~" name="ext_~ 629 . $id 630 . qq~_msgCL" readonly="readonly" disabled="disabled"$ext_msgCL /></span> 631 <script type="text/javascript"> 632 var ext_~ . $id . q~_supportsKeys = false; 633 function ext_~ . $id . q~_tick() { 634 ext_~ . $id . q~_calcCharLeft(document.forms[0]) 635 if (!ext_~ 636 . $id 637 . q~_supportsKeys) timerID = setTimeout("ext_~ 638 . $id 639 . qq~_tick()",$options[0]) 640 } 641 642 function ext_~ . $id . qq~_calcCharLeft(sig) { 643 clipped = false; 644 maxLength = $options[0]; 645 if (document.creator.ext_~ . $id . q~.value.length > maxLength) { 646 document.creator.ext_~ 647 . $id 648 . q~.value = document.creator.ext_~ 649 . $id 650 . q~.value.substring(0,maxLength); 651 charleft = 0; 652 clipped = true; 653 } else { 654 charleft = maxLength - document.creator.ext_~ . $id . q~.value.length; 655 } 656 document.creator.ext_~ . $id . q~_msgCL.value = charleft; 657 return clipped; 658 } 659 ext_~ . $id . q~_tick(); 660 </script>~; 661 } 662 else { $field{'options'} = q{}; } 663 if ( $options[1] ne q{} ) { $options[1] = qq~ rows="$options[1]"~; } 664 else { $options[1] = q~ rows="4"~; } 665 if ( $options[2] ne q{} ) { $options[2] = qq~ cols="$options[2]"~; } 666 else { $options[2] = q~ cols="50"~; } 667 $value =~ s/<br(?: ?\/)?>/\n/gm; 668 $output .= 669 $template1 670 . qq~<textarea name="ext_$id" id="ext_$id"$options[1]$options[2]>$value</textarea>$field{'options'}~ 671 . $template2; 672 673 } 674 elsif ( $field{'type'} eq 'select' ) { 675 $output .= 676 $template1 . qq~<select name="ext_$id" id="ext_$id" size="1">\n~; 677 @options = split /\^/xsm, $field{'options'}; 678 if ( $value > $#options || $value eq q{} ) { $ext_profile[$id] = 0; } 679 $count = 0; 680 foreach (@options) { 681 if ( $count == $value ) { $selected = ' selected="selected"'; } 682 else { $selected = q{}; } 683 $output .= qq~<option value="$count"$selected>$_</option>\n~; 684 $count++; 685 } 686 $output .= q~</select>~ . $template2; 687 688 } 689 elsif ( $field{'type'} eq 'radiobuttons' ) { 690 $output .= $template1; 691 @options = split /\^/xsm, $field{'options'}; 692 if ( $value > $#options ) { $value = 0; } 693 if ( !$field{'radiounselect'} && $value eq q{} ) { $value = 0; } 694 $count = 0; 695 foreach (@options) { 696 if ( $value ne q{} && $count == $value ) { 697 $selected = qq~ id="ext_$id" checked="checked"~; 698 } 699 else { $selected = q{}; } 700 $output .= 701qq~<input type="radio" name="ext_$id" value="$count"$selected />$_\n~; 702 $count++; 703 } 704 $output .= $template2; 705 706 } 707 elsif ( $field{'type'} eq 'date' ) { 708 if ( $value !~ /[0-9\/]/sm ) { $value = q{}; } 709 @options = split /\//xsm, $value; 710 $dayormonthm = 711qq~ $profile_txt{'564'} <input type="text" name="ext_$id\_month" id="ext_$id\_month" size="2" maxlength="2" value="$options[0]" />~; 712 $dayormonthd = 713qq~ $profile_txt{'565'} <input type="text" name="ext_$id\_day" id="ext_$id\_day" size="2" maxlength="2" value="$options[1]" />~; 714 if ( 715 ( 716 ${ $uid . $pusername }{'timeselect'} == 2 717 || ${ $uid . $pusername }{'timeselect'} == 3 718 || ${ $uid . $pusername }{'timeselect'} == 6 719 ) 720 || ( $timeselected == 2 721 || $timeselected == 3 722 || $timeselected == 6 ) 723 ) 724 { 725 $dayormonth = $dayormonthd . $dayormonthm; 726 $name_id = "ext_$id\_day"; 727 } 728 else { 729 $dayormonth = $dayormonthm . $dayormonthd; 730 $name_id = "ext_$id\_month"; 731 } 732 $output .= 733 $template1 734 . qq~<span class="small">$dayormonth $profile_txt{'566'} <input type="text" name="ext_$id\_year" size="4" maxlength="4" value="$options[2]" /></span>~ 735 . $template2; 736 737 } 738 elsif ( $field{'type'} eq 'checkbox' ) { 739 if ( $value == 1 ) { $value = ' checked="checked"'; } 740 else { $value = q{}; } 741 742# we have to use a little trick here to get a value from a checkbox if it has been unchecked by adding a hidden <input value=""> before it 743 $output .= 744 $template1 745 . qq~<input type="hidden" name="ext_$id" value="" /><input type="checkbox" name="ext_$id" id="ext_$id"$value />~ 746 . $template2; 747 748 } 749 elsif ( $field{'type'} eq 'spacer' ) { 750 @options = split /\^/xsm, $field{'options'}; 751 if ( $options[1] == 1 ) { 752 753 $output .= $ext_spacer; 754 $output =~ s/{yabb fieldcomment}/$field{'comment'}/sm; 755 } 756 757 } 758 elsif ( $field{'type'} eq 'email' ) { 759 $output .= 760 $template1 761 . qq~<input type="text" name="ext_$id" id="ext_$id" maxlength="$ext_max_email_length" size="30" value="$value" />~ 762 . $template2; 763 764 } 765 elsif ( $field{'type'} eq 'url' ) { 766 $output .= 767 $template1 768 . qq~<input type="text" name="ext_$id" id="ext_$id" maxlength="$ext_max_url_length" size="50" value="$value" />~ 769 . $template2; 770 771 } 772 elsif ( $field{'type'} eq 'image' ) { 773 if ( $value eq q{} ) { $value = 'http://'; } 774 $output .= 775 $template1 776 . qq~<input type="text" name="ext_$id" id="ext_$id" maxlength="$ext_max_image_length" size="50" value="$value" />~ 777 . $template2; 778 } 779 $output =~ s/<label for="">/<label for="$name_id">/gsm; 780 781 return $output; 782} 783 784# returns the output for the edit profile page 785## USAGE: $value = ext_editprofile("admin","required"); 786sub ext_editprofile { 787 my ( 788 $pusername, $part, $usergroup, $field, $id, 789 $output, $fieldname, @options, $selected, $count 790 ) = ( shift, shift, ${ $uid . $username }{'position'} ); 791 792 get_gmod(); 793 foreach my $fieldname (@ext_prof_order) { 794 $id = ext_get_field_id($fieldname); 795 ext_get_field($id); 796 797# make sure the field is visible, the user allowed to edit the current field and only the requested fields are returned 798 if ( 799 $field{'active'} == 1 800 && ( $field{'editable_by_user'} != 0 801 || $iamadmin 802 || $iamgmod && $allow_gmod_profile ) 803 && ( 804 ( $part eq 'required' && $field{'required_on_reg'} == 1 ) 805 || # show all required fields 806 ( $part eq 'additional' && $field{'required_on_reg'} != 1 ) 807 || # show all additional fields 808 ( $part eq 'admin' && $field{'editable_by_user'} == 0 ) 809 || # all fields for "admin edits" page 810 ( $part eq 'edit' && $field{'editable_by_user'} == 1 ) 811 || # all fields for "edit profile" page 812 ( $part eq 'contact' && $field{'editable_by_user'} == 2 ) 813 || # contact information page 814 ( $part eq 'options' && $field{'editable_by_user'} == 3 ) 815 || # options page 816 ( $part eq 'im' && $field{'editable_by_user'} == 4 ) 817 ) 818 ) 819 { # im prefs page 820 $output .= ext_gen_editfield( $id, $pusername ); 821 } 822 } 823 824 return $output; 825} 826 827# returns the output for the registration page 828sub ext_register { 829 my ( $id, $output, $fieldname, @options ); 830 831 foreach my $fieldname (@ext_prof_order) { 832 $id = ext_get_field_id($fieldname); 833 ext_get_field($id); 834 if ( $field{'active'} == 1 && $field{'required_on_reg'} != 0 ) { 835 $output .= ext_gen_editfield($id); 836 } 837 } 838 839 return $output; 840} 841 842# returns if the submitted profile is valid, if not, return error messages 843sub ext_validate_submition { 844 my ( 845 $username, $pusername, $usergroup, %newprofile, 846 @oldprofile, $output, $key, $value, 847 $id, $field, @options 848 ) = ( shift, shift, ${ $uid . $username }{'position'}, %FORM ); 849 850 get_gmod(); 851 852 while ( ( $key, $value ) = each %newprofile ) { 853 854 # only validate fields with prefix "ext_" 855 if ( $key =~ /^ext_(\d+)/xsm ) { 856 $id = $1; 857 ext_get_field($id); 858 859 if ( !$field{'name'} ) { 860 $output .= 861 $lang_ext{'field_not_existing1'} 862 . $id 863 . $lang_ext{'field_not_existing2'} 864 . "<br />\n"; 865 } 866 867 # check if user is allowed to modify this setting 868 if ( $action eq 'register2' ) { 869 870# if we're on registration page, ignore the 'editable_by_user' setting in case that 'required_on_reg' is set 871 if ( $field{'editable_by_user'} == 0 872 && $field{'required_on_reg'} == 0 ) 873 { 874 $output .= 875 $field{'name'} . q{: } 876 . $lang_ext{'not_allowed_to_modify'} 877 . "<br />\n"; 878 } 879 } 880 elsif ( 881 ( $field{'editable_by_user'} == 0 || $username ne $pusername ) 882 && !$iamadmin 883 && ( !$iamgmod || !$allow_gmod_profile ) ) 884 { 885 $output .= 886 $field{'name'} . q{: } 887 . $lang_ext{'not_allowed_to_modify'} 888 . "<br />\n"; 889 } 890 891 # check if setting is valid 892 if ( $field{'type'} ne 'text_multi' && $value =~ /[\n\r]/xsm ) { 893 $output .= 894 $field{'name'} . q{: } 895 . $lang_ext{'invalid_char'} 896 . "<br />\n"; 897 } 898 899 if ( $field{'type'} eq 'text' ) { 900 @options = split /\^/xsm, $field{'options'}; 901 902# don't fill it with default value yet, it might be required on registration 903# if ($options[3] ne q{} && $value eq "") { $value = $options[3]; $newprofile{'ext_'.$id} = $value; } 904 if ( $options[0] + 0 > 0 && length($value) > $options[0] ) { 905 $output .= 906 $field{'name'} . q{: } 907 . $lang_ext{'too_long'} 908 . "<br />\n"; 909 } 910 if ( $options[2] == 1 911 && $value !~ /[0-9\.,]+/xsm 912 && $value ne q{} ) 913 { 914 $output .= 915 $field{'name'} . q{: } 916 . $lang_ext{'not_numeric'} 917 . "<br />\n"; 918 } 919 FromChars($value); 920 ToHTML($value); 921 ToChars($value); 922 923 } 924 elsif ( $field{'type'} eq 'text_multi' ) { 925 @options = split /\^/xsm, $field{'options'}; 926 if ( $options[0] + 0 > 0 && length($value) > $options[0] ) { 927 $output .= 928 $field{'name'} . q{: } 929 . $lang_ext{'too_long'} 930 . "<br />\n"; 931 } 932 FromChars($value); 933 ToHTML($value); 934 ToChars($value); 935 $value =~ s/\n/<br \/>/gxsm; 936 $value =~ s/\r//gxsm; 937 938 } 939 elsif ($field{'type'} eq 'select' 940 || $field{'type'} eq 'radiobuttons' ) 941 { 942 @options = split /\^/xsm, $field{'options'}; 943 if ( $value !~ /[0-9]/xsm ) { 944 $output .= 945 $field{'name'} . q{: } 946 . $lang_ext{'not_numeric'} 947 . "<br />\n"; 948 } 949 if ( $value < 0 ) { 950 $output .= 951 $field{'name'} . q{: } 952 . $lang_ext{'too_small'} 953 . "<br />\n"; 954 } 955 if ( $value > $#options ) { 956 $output .= 957 $field{'name'} . q{: } 958 . $lang_ext{'option_does_not_exist'} 959 . "<br />\n"; 960 } 961 next; 962 963 } 964 elsif ( $field{'type'} eq 'date' && $value ne q{} ) { 965 if ( $value !~ /[0-9]/xsm ) { 966 $output .= 967 $field{'name'} . q{: } 968 . $lang_ext{'not_numeric'} 969 . "<br />\n"; 970 } 971 if ( $key eq 'ext_' . $id . '_day' ) { 972 if ( $value < 1 ) { 973 $output .= 974 $field{'name'} . q{: } 975 . $lang_ext{'too_small'} 976 . "<br />\n"; 977 } 978 if ( $value > 31 ) { 979 $output .= 980 $field{'name'} . q{: } 981 . $lang_ext{'too_big'} 982 . "<br />\n"; 983 } 984 if ( length($value) == 1 ) { 985 $newprofile{ 'ext_' . $id . '_day' } = '0' . $value; 986 } 987 } 988 elsif ( $key eq 'ext_' . $id . '_month' ) { 989 if ( $value < 1 ) { 990 $output .= 991 $field{'name'} . q{: } 992 . $lang_ext{'too_small'} 993 . "<br />\n"; 994 } 995 if ( $value > 12 ) { 996 $output .= 997 $field{'name'} . q{: } 998 . $lang_ext{'too_big'} 999 . "<br />\n"; 1000 } 1001 if ( length($value) == 1 ) { 1002 $newprofile{ 'ext_' . $id . '_month' } = '0' . $value; 1003 } 1004 } 1005 elsif ( $key eq 'ext_' . $id . '_year' ) { 1006 if ( length($value) != 4 ) { 1007 $output .= 1008 $field{'name'} . q{: } 1009 . $lang_ext{'invalid_year'} 1010 . "<br />\n"; 1011 } 1012 } 1013 $newprofile{ 'ext_' . $id } = 1014 $newprofile{ 'ext_' . $id . '_month' } . q{/} 1015 . $newprofile{ 'ext_' . $id . '_day' } . q{/} 1016 . $newprofile{ 'ext_' . $id . '_year' }; 1017 if ( $newprofile{ 'ext_' . $id } !~ /^\d\d\/\d\d\/\d\d\d\d$/sm ) 1018 { 1019 $newprofile{ 'ext_' . $id } = q{}; 1020 } 1021 next; 1022 1023 } 1024 elsif ( $field{'type'} eq 'checkbox' ) { 1025 if ( $value ne q{} ) { $newprofile{ 'ext_' . $id } = 1; } 1026 else { $newprofile{ 'ext_' . $id } = 0; } 1027 next; 1028 1029 } 1030 elsif ( $field{'type'} eq 'email' && $value ne q{} ) { 1031 $value = substr $value, 0, $ext_max_email_length; 1032 1033 # uses the code from Profile.pm without further checking... 1034 if ( $value !~ /[\w\-\.\+]+\@[\w\-\.\+]+\.(\w{2,4}$)/sm ) { 1035 $output .= 1036 $field{'name'} . q{: } 1037 . $lang_ext{'invalid_char'} 1038 . "<br />\n"; 1039 } 1040 if ( 1041 ( $value =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)|(\.$)/sm ) 1042 || ( $value !~ 1043 /^.+@\[?(\w|[-.])+\.[a-zA-Z]{2,4}|[0-9]{1,4}\]?$/sm ) 1044 ) 1045 { 1046 $output .= 1047 $field{'name'} . q{: } 1048 . $lang_ext{'invalid_char'} 1049 . "<br />\n"; 1050 } 1051 1052 } 1053 elsif ( $field{'type'} eq 'url' && $value ne q{} ) { 1054 $value = substr $value, 0, $ext_max_url_length; 1055 1056 } 1057 elsif ($field{'type'} eq 'image' 1058 && $value ne q{} 1059 && $value ne 'http://' ) 1060 { 1061 $value = substr $value, 0, $ext_max_image_length; 1062 @options = split /\^/xsm, $field{'options'}; 1063 if ( $options[2] ne q{} ) { 1064 @allowed_extensions = split / /sm, $options[2]; 1065 $match = 0; 1066 foreach my $extension (@allowed_extensions) { 1067 if ( grep { /$extension$/ism } $value ) { 1068 $match = 1; 1069 last; 1070 } 1071 } 1072 if ( $match == 0 ) { 1073 $output .= 1074 $field{'name'} . q{: } 1075 . $lang_ext{'invalid_extension'} 1076 . "<br />\n"; 1077 } 1078 } 1079 1080 # filename check from Profile.pm: 1081 if ( $value !~ 1082 m{\A[0-9a-zA-Z_\.\#\%\-\:\+\?\$\&\~\.\,\@/]+\Z}sm ) 1083 { 1084 $output .= 1085 $field{'name'} . q{: } 1086 . $lang_ext{'invalid_char'} 1087 . "<br />\n"; 1088 } 1089 } 1090 $newprofile{ 'ext_' . $id } = $value; 1091 } 1092 } 1093 1094# check if required fields are filled and add missing fields to $newprofile, just to be on the safe side 1095 $id = 0; 1096 foreach (@ext_prof_fields) { 1097 ext_get_field($id); 1098 $value = ext_get( $pusername, $field{'name'}, 1 ); 1099 if ( defined $newprofile{ 'ext_' . $id } ) { 1100 if ( $field{'type'} eq 'checkbox' 1101 || $field{'type'} eq 'radiobuttons' ) { 1102 if ( $newprofile{ 'ext_' . $id } eq q{} ) { 1103 $newprofile{ 'ext_' . $id } = 0; 1104 } 1105 } 1106 elsif ( $field{'type'} eq 'select' ) { 1107 if ( $newprofile{ 'ext_' . $id } eq q{} ) { 1108 $newprofile{ 'ext_' . $id } = 0; 1109 } 1110 @options = split /\^/xsm, $field{'options'}; 1111 if ( $options[ $newprofile{ 'ext_' . $id } ] eq q{ } ) { 1112 $newprofile{ 'ext_' . $id } = q{}; 1113 } 1114 } 1115 elsif ( $field{'type'} eq 'image' ) { 1116 if ( $newprofile{ 'ext_' . $id } eq 'http://' ) { 1117 $newprofile{ 'ext_' . $id } = q{}; 1118 } 1119 } 1120 } 1121 1122 # load old settings which where invisible/restricted 1123 if ( $action eq 'register2' ) { 1124 if ( $field{'editable_by_user'} == 0 1125 && $field{'required_on_reg'} == 0 ) 1126 { 1127 $newprofile{ 'ext_' . $id } = $value; 1128 } 1129 } 1130 else { 1131 if ( $field{'editable_by_user'} == 0 1132 && !$iamadmin 1133 && ( !$iamgmod || !$allow_gmod_profile ) ) 1134 { 1135 $newprofile{ 'ext_' . $id } = $value; 1136 } 1137 } 1138 1139 # if setting didn't get submitted or field is disabled, load old value 1140 if ( !defined $newprofile{ 'ext_' . $id } 1141 && $field{'active'} == 0 1142 && $action eq 'register2' ) 1143 { 1144 $newprofile{ 'ext_' . $id } = 0; 1145 } 1146 elsif ( !defined $newprofile{ 'ext_' . $id } || $field{'active'} == 0 ) 1147 { 1148 $newprofile{ 'ext_' . $id } = $value; 1149 } 1150 1151# if (!defined $newprofile{'ext_'.$id} || $field{'active'} == 0) { $newprofile{'ext_'.$id} = $value; } 1152 if ( $field{'required_on_reg'} == 1 1153 && $newprofile{ 'ext_' . $id } eq q{} 1154 && $action eq 'register2' ) 1155 { 1156 $output .= 1157 $field{'name'} . q{: } . $lang_ext{'required'} . "<br />\n"; 1158 } 1159 1160 # only fill with default value AFTER check of requirement 1161 if ( $field{'type'} eq 'text' && $newprofile{ 'ext_' . $id } eq q{} ) { 1162 @options = split /\^/xsm, $field{'options'}; 1163 if ( $options[3] ne q{} ) { 1164 $newprofile{ 'ext_' . $id } = $options[3]; 1165 } 1166 } 1167 elsif ( $field{'type'} eq 'spacer' ) { 1168 $newprofile{ 'ext_' . $id } = q{}; 1169 } 1170 elsif ($field{'type'} eq 'select' 1171 && $newprofile{ 'ext_' . $id } eq q{} ) 1172 { 1173 $newprofile{ 'ext_' . $id } = 0; 1174 } 1175 $id++; 1176 } 1177 1178# write our now validated profile information back into the usually used variable 1179 %FORM = %newprofile; 1180 1181 return $output; 1182} 1183 1184# stores the submitted profile on disk 1185sub ext_saveprofile { 1186 my ( $pusername, $id, %newprofile, @fields ) = ( shift, 0, %FORM ); 1187 1188 # note: we expect the new profile to be complete and validated already 1189 1190 foreach (@ext_prof_fields) { 1191 ${ $uid . $pusername }{ 'ext_' . $id } = $newprofile{ 'ext_' . $id }; 1192 $id++; 1193 } 1194 return; 1195} 1196 11971; 1198 1199# file formats used by this code: 1200# 1201# username.vars - contains the additional user profile information. Number is field-id 1202# ------------- 1203# ... 1204# 'ext_0',"value" 1205# 'ext_1',"value" 1206# 'ext_2',"value" 1207# ... 1208# 1209# @ext_prof_order - contains the order in which the fields will be displayed 1210# --------------------------- 1211# ("name","name","name",....) 1212# 1213# extended_profiles_fields.txt - defines the new profile fields. Uses line number as field-id 1214# ---------------------------- 1215# ("name|type|options|active|comment|required_on_reg|visible_in_viewprofile|v_users|v_groups|visible_in_posts|p_users|p_groups|p_displayfieldname|visible_in_memberlist|m_users|m_groups|editable_by_user|visible_in_posts_popup|pp_users|pp_groups|pp_displayfieldname","name|type|options|active|comment|required_on_reg|visible_in_viewprofile|v_users|v_groups|visible_in_posts|p_users|p_groups|p_displayfieldname|visible_in_memberlist|m_users|m_groups|editable_by_user|visible_in_posts_popup|pp_users|pp_groups|pp_displayfieldname","name|type|options|active|comment|required_on_reg|visible_in_viewprofile|v_users|v_groups|visible_in_posts|p_users|p_groups|p_displayfieldname|visible_in_memberlist|m_users|m_groups|editable_by_user|visible_in_posts_popup|pp_users|pp_groups|pp_displayfieldname",....) 1216# 1217# Here are all types with their possible type-specific options. If options contain multiple entries, separated by ^ 1218# - text limit_len^width^is_numberic^default_value^allow_ubbc 1219# - text_multi limit_len^rows^cols^allow_ubbc 1220# - select option1^option2^option3... (first option is default) 1221# - radiobuttons option1^option2^option3... (first option is default) 1222# - spacer br_or_hr^visible_in_editprofile 1223# - checkbox - 1224# - date - 1225# - emial - 1226# - url - 1227# - image width^height^allowed_extensions 1228# 1229# required_on_reg can have value 0 (disabled), 1 (required on registration) and 2 (not req. but display on reg. page anyway) 1230# editable_by_user can have value 0 (will only show on the "admin edits" page), 1 ("edit profile" page), 2 ("contact information" page), 3 ("Options" page) and 4 ("PM Preferences" page) 1231# allowed_extensions is a space-seperated list of file extensions, example: "jpg jpeg gif bmp png" 1232# v_groups, p_groups, m_groups, pp_groups format: "Administrator" or "Moderator" or "Global Moderator" or NoPost{...} or Post{...} 1233# 1234# NOTE: use prefix "ext_" in sub-, variable- and formnames to prevent conflicts with other mods 1235# 1236# easy mod integration: use &ext_get($username,"fieldname") go get user's field value 1237# 1238############################################################################### 1239