Go Back   vb.org Archive > vBulletin Modifications > Archive > vB.org Archives > vBulletin 3.0 > vBulletin 3.0 Beta Releases
FAQ Community Calendar Today's Posts Search

Reply
 
Thread Tools
Secure Login by IP (bit matching with masks) Details »»
Secure Login by IP (bit matching with masks)
Version: .1, by Tekton Tekton is offline
Developer Last Online: Jun 2009 Show Printable Version Email this Page

Version: 3.0.6 Rating:
Released: 02-12-2005 Last Update: Never Installs: 2
DB Changes
Is in Beta Stage  
No support by the author.

___________
PRE DISCLAIMER: This beta hack has been tested and DOES work; however it IS beta so use at your own risk. (I'm not responsible, etc etc)

???????????
Apparently someone was making a much cooler Draft hack than me (although they've vanished for almost a month now), so I decided to do this in some of my free time. I did a little searching and found no hacks like this, but if there is: please tell me.

Estimated Install Time: ???? [Any questions? This thread only please ]

What is it: This hack allows you the possibility to limit your account login to certain IP addresses (or IP ranges). This would stop people that find out your password if you enable secure login on certain IP addresses (users DON'T have to specify any or do anything and it will work just like it would normally). This is mainly for people concerned with security I guess, plus it's kinda cool as long as you're careful and if you want to restrict access. If someone aquires your password, this would prevent them from using it possibly.

Why is it beta: I haven't had much time to test it out, and I'm not sure how well the checkbit-masking works even though I coded it to be honest ^^;; -- so that's why. It'd be great if you guys/girls could help out. (and the code is kinda sloppy at the moment)

Images:::::::::::::::::::::::::::::::::::

// ###### INSTALLATION ######
First: Using PHPMYADMIN, or your preferred SQL tool, run this query in your vB database.
[sql]ALTER TABLE `user` ADD `secure_ip` VARCHAR( 150 ) DEFAULT '0.0.0.0~0.0.0.0~0!0.0.0.0~0.0.0.0~0!0.0.0.0~0.0.0 .0~0' NOT NULL ;[/sql]
NOTE: Add your table prefix if you have one!
??????????????????????
IN profile.php FIND:
PHP Code:
if ($_REQUEST['do'] == 'editpassword')

BELOW, ADD:
PHP Code:
//======= VE SECURE-LOGIN START -->

$ve_a=0$ve_b=0$ve_c=0$ve_construct=""$ve_secure_login=""$ve_sec_group=array(); $ve_sub_s=array(); $ve_sub_ip=array(); $ve_sub_check=array(); // inits

$ve_sec_group=explode("!"$bbuserinfo[secure_ip]);

while(
$ve_b<3){ $ve_a++;
$ve_sub_s=explode("~"$ve_sec_group[$ve_b]);
$ve_sub_ip=explode("."$ve_sub_s[0]);
$ve_sub_check=explode("."$ve_sub_s[1]);
if(
$ve_sub_s[2]==1){$ve_ischeck="checked";}else{$ve_ischeck="";}

$ve_construct.="
<tr><td nowrap='nowrap'><div>
<input type='text' class='bginput' name='ves_i"
.$ve_a."1' value='".$ve_sub_ip[0]."' size='3' maxlength='3'/> .
<input type='text' class='bginput' name='ves_i"
.$ve_a."2' value='".$ve_sub_ip[1]."' size='3' maxlength='3'/> .
<input type='text' class='bginput' name='ves_i"
.$ve_a."3' value='".$ve_sub_ip[2]."' size='3' maxlength='3'/> .
<input type='text' class='bginput' name='ves_i"
.$ve_a."4' value='".$ve_sub_ip[3]."' size='3' maxlength='3'/>
</div></td><td nowrap='nowrap' width='6'>|</td><td nowrap='nowrap'><div>
<input type='text' class='bginput' name='ves_c"
.$ve_a."1' value='".$ve_sub_check[0]."' size='3' maxlength='3'/> .
<input type='text' class='bginput' name='ves_c"
.$ve_a."2' value='".$ve_sub_check[1]."' size='3' maxlength='3'/> .
<input type='text' class='bginput' name='ves_c"
.$ve_a."3' value='".$ve_sub_check[2]."' size='3' maxlength='3'/> .
<input type='text' class='bginput' name='ves_c"
.$ve_a."4' value='".$ve_sub_check[3]."' size='3' maxlength='3'/>
</div></td><td nowrap='nowrap'><input type='checkbox' "
.$ve_ischeck." name='ves_u".$ve_a."' value='1'> Use This Set</td></tr>"$ve_b++;}

$ve_secure_login="<fieldset class='fieldset'><legend>VE SECURE-LOGIN</legend>
<table cellpadding='0' cellspacing='
$stylevar[formspacer]' border='0'>
<tr><td colspan='4' style='border-color: #000000; border-style: solid; border-width: 0px 0px 1px 0px;'>Secure your account by only allowing the IP addresses below to login.  
The 'Check Bits' field allows you to specify how much of the IP address to check.  
It's values are binary represented by a decimal number. ('255.255.0.0' will check the 
first two octets of your entered IP.</td></tr><tr><td><div>IP Address:</div></td><td></td><td><div>Check Bits:</div></td></tr>"
.$ve_construct."<tr><td colspan='3'>
CAUTION: Do not set these values if you do not know what you're 
doing as it could cause you to lock yourself out of your account!</td></tr></table></fieldset>"
;

//======= <-- VE SECURE-LOGIN END 
NEXT, FIND:
PHP Code:
            eval(print_standard_error('passwordhistory'));
        }

    } 
BELOW, ADD:
PHP Code:
//======= VE SECURE-LOGIN UPDATE START -->

// grab values => int 'em
$ve_new_i1[0]=intval($_POST['ves_i11']);$ve_new_i1[1]=intval($_POST['ves_i12']);$ve_new_i1[2]=intval($_POST['ves_i13']);$ve_new_i1[3]=intval($_POST['ves_i14']);
$ve_new_i2[0]=intval($_POST['ves_i21']);$ve_new_i2[1]=intval($_POST['ves_i22']);$ve_new_i2[2]=intval($_POST['ves_i23']);$ve_new_i2[3]=intval($_POST['ves_i24']);
$ve_new_i3[0]=intval($_POST['ves_i31']);$ve_new_i3[1]=intval($_POST['ves_i32']);$ve_new_i3[2]=intval($_POST['ves_i33']);$ve_new_i3[3]=intval($_POST['ves_i34']);
$ve_new_c1[0]=intval($_POST['ves_c11']);$ve_new_c1[1]=intval($_POST['ves_c12']);$ve_new_c1[2]=intval($_POST['ves_c13']);$ve_new_c1[3]=intval($_POST['ves_c14']);
$ve_new_c2[0]=intval($_POST['ves_c21']);$ve_new_c2[1]=intval($_POST['ves_c22']);$ve_new_c2[2]=intval($_POST['ves_c23']);$ve_new_c2[3]=intval($_POST['ves_c24']);
$ve_new_c3[0]=intval($_POST['ves_c31']);$ve_new_c3[1]=intval($_POST['ves_c32']);$ve_new_c3[2]=intval($_POST['ves_c33']);$ve_new_c3[3]=intval($_POST['ves_c34']);
$ve_use[0]=$_POST['ves_u1'];$ve_use[1]=$_POST['ves_u2'];$ve_use[2]=$_POST['ves_u3']; $ve_sec_string="";

// make sure they are good vals else set to zero~
$ve_wh=0;while($ve_wh<4){
if(
$ve_new_i1[$ve_wh]>255||$ve_new_i1[$ve_wh]<0){$ve_new_i1[$ve_wh]=0;}
if(
$ve_new_c1[$ve_wh]>255||$ve_new_c1[$ve_wh]<0){$ve_new_c1[$ve_wh]=0;}
if(
$ve_use[$ve_wh]!=1){$ve_use[$ve_wh]=0;}
$ve_wh++;}

// combine into a settable value and UPDATE!
$ve_sec_string=
implode("."$ve_new_i1)."~".implode("."$ve_new_c1)."~".$ve_use[0]."!".
implode("."$ve_new_i2)."~".implode("."$ve_new_c2)."~".$ve_use[1]."!".
implode("."$ve_new_i3)."~".implode("."$ve_new_c3)."~".$ve_use[2];
$DB_site->query("UPDATE ".TABLE_PREFIX."user SET secure_ip = '$ve_sec_string' WHERE userid = '$bbuserinfo[userid]'");

//======= <-- VE SECURE-LOGIN UPDATE END 

??????????????????????
IN includes/functions_login.php FIND:
PHP Code:
function verify_authentication($username$password$md5password$md5password_utf$send_cookies)
{
    global 
$DB_site$bbuserinfo$_REQUEST$_COOKIE;

    
$username strip_blank_ascii($username' '); 
BELOW, ADD:
PHP Code:
//======= VE SECURE-LOGIN CHECK START -->
$ve_secure_check $DB_site->query_first("SELECT userid, username, secure_ip FROM ".TABLE_PREFIX."user WHERE username = '".addslashes(htmlspecialchars_uni($username))."'");

$ve_a=0$ve_c=0$ve_construct=""$ve_secure_login=""$ve_ip IPADDRESS$ve_can_login=array();
$ve_can_login[0]=0$ve_can_login[1]=0$ve_can_login[2]=0;
$ve_sec_group=array(); $ve_sub_s=array(); $ve_sub_ip=array(); $ve_sub_check=array();
$ve_sec_group=explode("!"$ve_secure_check[secure_ip]);
$ve_sub1=explode("~"$ve_sec_group[0]);$ve_ip1=explode("."$ve_sub1[0]);$ve_check1=explode("."$ve_sub1[1]);
$ve_sub2=explode("~"$ve_sec_group[1]);$ve_ip2=explode("."$ve_sub2[0]);$ve_check2=explode("."$ve_sub2[1]);
$ve_sub3=explode("~"$ve_sec_group[2]);$ve_ip3=explode("."$ve_sub3[0]);$ve_check3=explode("."$ve_sub3[1]);

$ve_ip1[0]=base_convert($ve_ip1[0], 102);$ve_ip1[1]=base_convert($ve_ip1[1], 102);$ve_ip1[2]=base_convert($ve_ip1[2], 102);$ve_ip1[3]=base_convert($ve_ip1[3], 102);
$ve_check1[0]=base_convert($ve_check1[0], 102);$ve_check1[1]=base_convert($ve_check1[1], 102);$ve_check1[2]=base_convert($ve_check1[2], 102);$ve_check1[3]=base_convert($ve_check1[3], 102);
$ve_ip2[0]=base_convert($ve_ip2[0], 102);$ve_ip2[1]=base_convert($ve_ip2[1], 102);$ve_ip2[2]=base_convert($ve_ip2[2], 102);$ve_ip2[3]=base_convert($ve_ip2[3], 102);
$ve_check2[0]=base_convert($ve_check2[0], 102);$ve_check2[1]=base_convert($ve_check2[1], 102);$ve_check2[2]=base_convert($ve_check2[2], 102);$ve_check2[3]=base_convert($ve_check2[3], 102);
$ve_ip3[0]=base_convert($ve_ip3[0], 102);$ve_ip3[1]=base_convert($ve_ip3[1], 102);$ve_ip3[2]=base_convert($ve_ip3[2], 102);$ve_ip3[3]=base_convert($ve_ip3[3], 102);
$ve_check3[0]=base_convert($ve_check3[0], 102);$ve_check3[1]=base_convert($ve_check3[1], 102);$ve_check3[2]=base_convert($ve_check3[2], 102);$ve_check3[3]=base_convert($ve_check3[3], 102);

// pad the real IP
$ve_ips=explode("."$ve_ip);
$ve_ips[0]=base_convert($ve_ips[0], 102);$ve_ips[1]=base_convert($ve_ips[1], 102);
$ve_ips[2]=base_convert($ve_ips[2], 102);$ve_ips[3]=base_convert($ve_ips[3], 102);
$ve_ips[0]=str_pad($ve_ips[0], 8"0"STR_PAD_LEFT);
$ve_ips[1]=str_pad($ve_ips[1], 8"0"STR_PAD_LEFT);
$ve_ips[2]=str_pad($ve_ips[2], 8"0"STR_PAD_LEFT);
$ve_ips[3]=str_pad($ve_ips[3], 8"0"STR_PAD_LEFT);


// first_IP
$ve_b=0; while($ve_b<4){
$ve_check1[$ve_b]=str_pad($ve_check1[$ve_b], 8"0"STR_PAD_LEFT);
$ve_ip1[$ve_b]=str_pad($ve_ip1[$ve_b], 8"0"STR_PAD_LEFT);
$ve_d=0; while($ve_d<8){
if(
$ve_check1[$ve_b]{$ve_d}==1&&$ve_ips[$ve_b]{$ve_d}!=$ve_ip1[$ve_b]{$ve_d}){$ve_can_login[0]+=1;}
$ve_d++;}$ve_b++;}

// second_IP
$ve_b=0; while($ve_b<4){
$ve_check2[$ve_b]=str_pad($ve_check2[$ve_b], 8"0"STR_PAD_LEFT);
$ve_ip2[$ve_b]=str_pad($ve_ip2[$ve_b], 8"0"STR_PAD_LEFT);
$ve_d=0; while($ve_d<8){
if(
$ve_check2[$ve_b]{$ve_d}==1&&$ve_ips[$ve_b]{$ve_d}!=$ve_ip2[$ve_b]{$ve_d}){$ve_can_login[1]+=1;}
$ve_d++;}$ve_b++;}

// third_IP
$ve_b=0; while($ve_b<4){
$ve_check3[$ve_b]=str_pad($ve_check3[$ve_b], 8"0"STR_PAD_LEFT);
$ve_ip3[$ve_b]=str_pad($ve_ip3[$ve_b], 8"0"STR_PAD_LEFT);
$ve_d=0; while($ve_d<8){
if(
$ve_check3[$ve_b]{$ve_d}==1&&$ve_ips[$ve_b]{$ve_d}!=$ve_ip3[$ve_b]{$ve_d}){$ve_can_login[2]+=1;}
$ve_d++;}$ve_b++;}

// Make sure they don't count if they are disabled
if($ve_sub1[2]==0){$ve_can_login[0]=0;}
if(
$ve_sub2[2]==0){$ve_can_login[1]=0;}
if(
$ve_sub3[2]==0){$ve_can_login[2]=0;}

//======= <-- VE SECURE-LOGIN CHECK END 
NEXT, FIND:
PHP Code:
if (
            
$bbuserinfo['password'] != iif($password AND !$md5passwordmd5(md5($password) . $bbuserinfo['salt']), '') AND
            
$bbuserinfo['password'] != md5($md5password $bbuserinfo['salt']) AND
            
$bbuserinfo['password'] != iif($md5password_utfmd5($md5password_utf $bbuserinfo['salt']), '')
        ){return 
false;} 
BELOW, ADD:
PHP Code:
//======= VE SECURE-LOGIN DENY START -->
if ($ve_can_login[0]>0||$ve_can_login[1]>0||$ve_can_login[2]>0){return false;}
//======= <-- VE SECURE-LOGIN DENY END 
??????????????????????
IN "Modify User Option Templates" modifypassword TEMPLATE FIND:
HTML Code:
<div><input type="text" class="bginput" name="emailconfirm" value="$bbuserinfo[email]" size="50" maxlength="50" /></div>
				</td>
			</tr>
			</table>
		</fieldset>
BELOW, ADD:
HTML Code:
$ve_secure_login
// ###### END INSTALLATION ######
DONE! PLEASE let me know what you think and help me find the bugs; I KNOW they're in there!

Explanation:
Setting an IP to "12.14.x.x" with the check bits "255.255.0.0" will check the first two octets ("12.14") of the IP address.
x=any value from 0-255

It matches up the bits in the user's IP address to the ones stored for each bit, like so:
11110000.00000100.00000000.00000010 (240.0.4.2) <-- user's IP
11110000.00000100.00000000.00000001 (240.0.4.1) <-- IP stored
11111111.11111111.11111111.00000000 (255.255.255.0) <-- Check Bits

It will only check the bits you have enabled in the "Check Bits" field, so the above example would allow the IP "204.0.4.2" INTO THE ACCOUNT even though it is set to 204.0.4.1 because of the check bits.

There IS some limitation to this method.

___________
POST DISCLAIMER: This beta hack has been tested and DOES work; however it IS beta so use at your own risk. (I'm not responsible, etc etc)

???????????

Show Your Support

  • This modification may not be copied, reproduced or published elsewhere without author's permission.

Comments
  #12  
Old 02-14-2005, 06:20 PM
MrNase MrNase is offline
 
Join Date: May 2003
Location: Germany
Posts: 670
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

A VERY nice idea.. But that could cause problems when you are on holiday and you try to login from a different country/PC *g*
Reply With Quote
  #13  
Old 02-15-2005, 09:19 AM
hoai dung hoai dung is offline
 
Join Date: Jul 2003
Posts: 6
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Tekton can hack this mod in AdminCP (admincp/user.php?do=modify) !? I should think have one button chose Yes/No in Usergroup for SECURE-LOGIN UPDATE, if chose YES then have Menu in "user.php?do=modify" agree choose IP SECURE-LOGIN in appear new line after IP address (Example : IP SECURE......).
Reply With Quote
  #14  
Old 02-15-2005, 04:04 PM
Tekton Tekton is offline
 
Join Date: Jun 2004
Location: Wisconsin
Posts: 362
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by hoai dung
Tekton can hack this mod in AdminCP (admincp/user.php?do=modify) !? I should think have one button chose Yes/No in Usergroup for SECURE-LOGIN UPDATE, if chose YES then have Menu in "user.php?do=modify" agree choose IP SECURE-LOGIN in appear new line after IP address (Example : IP SECURE......).
I'm not exactly sure what you just said...
Reply With Quote
  #15  
Old 02-16-2005, 02:33 AM
rookie7 rookie7 is offline
 
Join Date: Apr 2004
Posts: 33
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Can an admin edit other people's IP settings via admincp?

Like someone suggested, I don't think it's a good idea to let users themselves have access to it via usercp. I mean...someone can steal your account and set their IP ranges, hence locking you out.
Reply With Quote
  #16  
Old 02-16-2005, 05:14 AM
hoai dung hoai dung is offline
 
Join Date: Jul 2003
Posts: 6
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Thanks ^^
Reply With Quote
  #17  
Old 02-26-2005, 06:38 PM
untold4you's Avatar
untold4you untold4you is offline
 
Join Date: Feb 2005
Location: In Tyranny
Posts: 25
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Thanks for this one Installed and will check this one !
Reply With Quote
  #18  
Old 03-09-2005, 08:29 PM
Scerina Scerina is offline
 
Join Date: Mar 2004
Posts: 84
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

I got this error message after tryin to change my password:

Database error in vBulletin 3.0.6:

Invalid SQL: UPDATE vb3user SET secure_ip = '0.0.0.0~0.0.0.0~0!0.0.0.0~0.0.0.0~0!0.0.0.0~0.0.0 .0~0' WHERE userid = '1'
mysql error: Unknown column 'secure_ip' in 'field list'

mysql error number: 1054

Date: Wednesday 09th of March 2005 05:27:53 PM


Can someone help me PLEEAAZZEEE????
Reply With Quote
  #19  
Old 03-09-2005, 08:31 PM
Scerina Scerina is offline
 
Join Date: Mar 2004
Posts: 84
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

HELP ME!!! I CAN'T LOGIN MY OWN FORUM CUZ OF THIS HACK!!! I FOLLOWED THE INSTRUCTIONS TO A "T" AND THERE IS A FREAKIN PROBLEM WITH THAT QUERY YOU TOLD US TO RUN IN OUR MYSQL DATABASES!!! AND NOW NO ONE CAN ACCESS MY FORUM!!!

WHAT SHOULD I DO?!


Man, this is a HACK THAT HAS SERIOUSLY GONE WRONG!!!!
Reply With Quote
  #20  
Old 03-09-2005, 08:41 PM
Scerina Scerina is offline
 
Join Date: Mar 2004
Posts: 84
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

I got it...plz disregard my last few postings
Reply With Quote
  #21  
Old 03-13-2005, 11:25 PM
Tekton Tekton is offline
 
Join Date: Jun 2004
Location: Wisconsin
Posts: 362
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Ok. Sorry, I was out of the loop for the past week or so -- very busy.

I was planning to do an admin-able reset, and have it reset when you do the forgot-password thing through email, I just haven't gotten around to it yet.
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 03:47 PM.


Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2024, vBulletin Solutions Inc.
X vBulletin 3.8.12 by vBS Debug Information
  • Page Generation 0.05851 seconds
  • Memory Usage 2,460KB
  • Queries Executed 25 (?)
More Information
Template Usage:
  • (1)SHOWTHREAD
  • (1)ad_footer_end
  • (1)ad_footer_start
  • (1)ad_header_end
  • (1)ad_header_logo
  • (1)ad_navbar_below
  • (1)ad_showthread_beforeqr
  • (2)bbcode_html
  • (8)bbcode_php
  • (1)bbcode_quote
  • (1)footer
  • (1)forumjump
  • (1)forumrules
  • (1)gobutton
  • (1)header
  • (1)headinclude
  • (1)modsystem_post
  • (1)navbar
  • (6)navbar_link
  • (120)option
  • (1)pagenav
  • (1)pagenav_curpage
  • (2)pagenav_pagelink
  • (11)post_thanks_box
  • (11)post_thanks_button
  • (1)post_thanks_javascript
  • (1)post_thanks_navbar_search
  • (11)post_thanks_postbit_info
  • (10)postbit
  • (11)postbit_onlinestatus
  • (11)postbit_wrapper
  • (1)spacer_close
  • (1)spacer_open
  • (1)tagbit_wrapper 

Phrase Groups Available:
  • global
  • inlinemod
  • postbit
  • posting
  • reputationlevel
  • showthread
Included Files:
  • ./showthread.php
  • ./global.php
  • ./includes/init.php
  • ./includes/class_core.php
  • ./includes/config.php
  • ./includes/functions.php
  • ./includes/class_hook.php
  • ./includes/modsystem_functions.php
  • ./includes/functions_bigthree.php
  • ./includes/class_postbit.php
  • ./includes/class_bbcode.php
  • ./includes/functions_reputation.php
  • ./includes/functions_post_thanks.php 

Hooks Called:
  • init_startup
  • init_startup_session_setup_start
  • init_startup_session_setup_complete
  • cache_permissions
  • fetch_threadinfo_query
  • fetch_threadinfo
  • fetch_foruminfo
  • style_fetch
  • cache_templates
  • global_start
  • parse_templates
  • global_setup_complete
  • showthread_start
  • showthread_getinfo
  • forumjump
  • showthread_post_start
  • showthread_query_postids
  • showthread_query
  • bbcode_fetch_tags
  • bbcode_create
  • showthread_postbit_create
  • postbit_factory
  • postbit_display_start
  • post_thanks_function_post_thanks_off_start
  • post_thanks_function_post_thanks_off_end
  • post_thanks_function_fetch_thanks_start
  • post_thanks_function_fetch_thanks_end
  • post_thanks_function_thanked_already_start
  • post_thanks_function_thanked_already_end
  • fetch_musername
  • postbit_imicons
  • bbcode_parse_start
  • bbcode_parse_complete_precache
  • bbcode_parse_complete
  • postbit_display_complete
  • post_thanks_function_can_thank_this_post_start
  • pagenav_page
  • pagenav_complete
  • tag_fetchbit_complete
  • forumrules
  • navbits
  • navbits_complete
  • showthread_complete