4chan status checker source

Feel free to download the files to host your own script.
These scripts use the bootstrap 4 framework. The source code viewer will not run without the Bootstrap JavaScript files, the online checker will but tooltips will not be there.
Do not forget to also download 4chan.js and lib.js for the checker to work.

[Go Back]

include.php

[Download]

<?php
    
/*
    LICENSE:
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
    The full license text can be found here: http://creativecommons.org/licenses/by-nc-sa/4.0/
    The link has an easy to understand version of the license and the full license text.

    DISCLAIMER:
    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    THE POSSIBILITY OF SUCH DAMAGE.
    */
    
    //Configuration =============================================

    //Script version (Format is YYYY-MM-DD-COUNTER but you can chose for yourself)
    
define('VERSION','2020-09-05-01');
    
    
//Address of script to get your servers public IP address.
    //Delete completely or set to FALSE to not show this to the end user
    
define('IP_ADDR','https://ip.ayra.ch/');
    
    
//4chan domains. We only allow users to query these
    
define('FOURCHAN','boards.4channel.org,sys.4chan.org,a.4cdn.org,i.4cdn.org,t.4cdn.org,s.4cdn.org,www.4chan.org');
    
//Descriptions for the individual domains
    
define('FOURCHAN_DESC','Boards (View),Boards (Post),JSON API,Images,Thumbnails,Static Resources,Front Page');
    
//Servers that no longer serve the proper file for the status checker.
    
define('INVALIDS','boards.4chan.org,i.4cdn.org,t.4cdn.org');
    
    
//Number of seconds to wait for a socket connection to be made
    
define('CONNECT_TIMEOUT',5);
    
//Number of seconds to wait for a response
    
define('READ_TIMEOUT',5);
    
//Number of seconds to execute this script total. Used in case the HTTP server response is very slow
    
define('TOTAL_RUNTIME',CONNECT_TIMEOUT*2+READ_TIMEOUT*2);
    
    
//No changes below ==========================================
    
    //Basic sanity checks
    
cAssert(count(explode(',',FOURCHAN))==count(explode(',',FOURCHAN_DESC)),'FOURCHAN has not as many elements as FOURCHAN_DESC.');
    
cAssert(TOTAL_RUNTIME>=max(CONNECT_TIMEOUT,READ_TIMEOUT),'TOTAL_RUNTIME must be at least '.max(CONNECT_TIMEOUT,READ_TIMEOUT));
    
    
define('API_ERR_SUCCESS',0);
    
define('API_ERR_DOWN',API_ERR_SUCCESS+1);
    
define('API_ERR_WRITE',API_ERR_DOWN+1);
    
define('API_ERR_CONNECT',API_ERR_WRITE+1);
    
define('API_ERR_READ',API_ERR_CONNECT+1);
    
define('API_ERR_NAME',API_ERR_READ+1);
    
define('API_ERR_NOT4CHAN',API_ERR_NAME+1);
    
define('API_ERR_PROBABLYFINE',API_ERR_NOT4CHAN+1);

    
//Custom assert that actually works
    
function cAssert($cond,$msg){
        if(!
$cond){
            
//header('HTTP 500 Internal Server Error');
            
header('Content-Type: text/plain');
            die(
"Assert failed: $msg");
        }
    }
    
    
//API Codes and their messages
    
function getApiCodes(){
        return array(
            
API_ERR_SUCCESS=>'Service is running',
            
API_ERR_DOWN=>'Service is down or unstable. Got a response but it did not contain expected data.',
            
API_ERR_WRITE=>'Service unreachable. Connection was dropped while we were sending our request',
            
API_ERR_CONNECT=>'Service unreachable. Unable to connect to the destination',
            
API_ERR_READ=>'Service overloaded. Timeout while reading the server response',
            
API_ERR_NAME=>'DNS name not available. The given domain name is invalid',
            
API_ERR_NOT4CHAN=>'DNS name not available. This is not a 4chan domain',
            
API_ERR_PROBABLYFINE=>'Server not setup properly. It\'s probably working'
        
);
    }
    
    
//Validates DNS names
    
function checkNameFormat($name){
        
$regex='/^(?:_?(?>[a-z\d][a-z\d-]{0,61}[a-z\d]|[a-z\d])\.)*(?:_?(?>[a-z\d][a-z\d-]{0,61}[a-z\d]|[a-z\d]))\.?$/i';
        return !!
preg_match($regex,$name);
    }
    
    
//Checks if the name is from 4chan
    
function is4c($name){
        return 
in_array(strtolower($name),explode(',',FOURCHAN));
    }
    
    
//Checks a 4chan host via HTTP
    
function check4c($domain){
        
$ret=false;
        if(!
checkNameFormat($domain)){
            return 
API_ERR_NAME;
        }
        if(
is4c($domain)){
            
$t=time();
            
$errno=0;
            
$errstr=null;
            
//Connect to HTTPS
            
$fp=fsockopen("tls://$domain",443,$errno,$errstr,CONNECT_TIMEOUT);
            if(
$fp){
                
stream_set_timeout($fp,READ_TIMEOUT);
                
//Send HTTP Headers
                
$res=fwrite($fp,implode("\r\n",array(
                    
"GET /ping.js?$t HTTP/1.1",
                    
"Host: $domain",
                    
'Connection: Close',
                    
'Referrer: https://blog.4chan.org/',
                    
'User-Agent: Up-Checker/0.9'//If you change the behavior of the HTTP reader, increase the version.
                    
'DNT: 1'))."\r\n\r\n");
                if(
$res && $res>0){
                    
//Retrieve HTTP Content
                    
$data=getHTTP($fp);
                    if(
$data['data']!==null){
                        if(
preg_match('/fourchan_up/',$data['data'])){
                            
$ret=API_ERR_SUCCESS;
                        }
                        else{
                            if(
in_array($domain,explode(',',INVALIDS))){
                                
$ret=API_ERR_PROBABLYFINE;
                            }
                            else{
                                
$ret=API_ERR_DOWN;
                            }
                        }
                    }
                    else{
                        
$ret=API_ERR_READ;
                    }
                }
                else{
                    
$ret=API_ERR_WRITE;
                }
                
fclose($fp);
            }
            else{
                
$ret=API_ERR_CONNECT;
            }
        }
        else{
            
$ret=API_ERR_NOT4CHAN;
        }
        return 
$ret;
    }
    
    
//Gets A and AAAA record from DNS
    
function getRecord($domain){
        
$addr=array('v4'=>array(),'v6'=>array());
        if(
$data=dns_get_record($domain,DNS_A)){
            foreach(
$data as $entry){
                if(isset(
$entry['ip'])){
                    
$addr['v4'][]=$entry['ip'];
                }
            }
        }
        if(
$data=dns_get_record($domain,DNS_AAAA)){
            foreach(
$data as $entry){
                if(isset(
$entry['ipv6'])){
                    
$addr['v6'][]=$entry['ipv6'];
                }
            }
        }
        
sort($addr['v4']);
        
sort($addr['v6']);
        return 
$addr;
    }
    
    
//Reads a HTTP response (Header+Data)
    
function getHTTP($fp){
        
$regex='/^([^:]+): (.*)$/';
        
$http=array('headers'=>array(),'data'=>null);
        if(
$fp){
            do{
                
$matches=null;
                
$data=stream_get_line($fp,1024*8,"\r\n");
                if(
$data && preg_match($regex,$data,$matches)){
                    
$http['headers'][strtolower($matches[1])]=$matches[2];
                }
                elseif(
$data===false){
                    
//Abort if data is set to false (error)
                    
return $http;
                }
            }while(
$data);
            
$chunked=isset($http['headers']['transfer-encoding']) && preg_match('/chunked/',$http['headers']['transfer-encoding']);
            
$len=isset($http['headers']['content-length'])?+$http['headers']['content-length']:-1;
            
            if(
$chunked){
                do{
                    
$len=hexdec(stream_get_line($fp,1024,"\r\n"));
                    if(
$len>&& $len===$len){
                        
$data='';
                        while(
strlen($data)<$len){
                            
$data.=fread($fp,$len-strlen($data));
                        }
                        
//skip CRLF
                        
fread($fp,2);
                        
$http['data'].=$data;
                    }
                    else{
                        
//end of stream
                        
break;
                    }
                }while(
$len>0);
            }
            elseif(
$len>0){
                
$data='';
                while(
strlen($data)<$len){
                    
$temp=fread($fp,$len-strlen($data));
                    if(
$temp!==false){
                        
$data.=$temp;
                    }
                    else{
                        
//Abort on read error
                        
return $http;
                    }
                }
                
$http['data']=$data;
            }
            else{
                
//No length specified and not chunked encoding. Unable to get real content length.
            
}
            
            if(isset(
$http['headers']['transfer-encoding']) && preg_match('/gzip/',$http['headers']['transfer-encoding'])){
                
$http['data']=gzdecode($http['data']);
            }
        }
        return 
$http;
    }
    
set_time_limit(TOTAL_RUNTIME);
?>

info.php

[Download]

<?php
    
/*
    LICENSE:
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
    The full license text can be found here: http://creativecommons.org/licenses/by-nc-sa/4.0/
    The link has an easy to understand version of the license and the full license text.

    DISCLAIMER:
    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    THE POSSIBILITY OF SUCH DAMAGE.
    */

    
require('include.php');
    
header('Content-Type: application/json');
    
$res=array(
        
'names'  => explode(',',FOURCHAN),
        
'descs'  => explode(',',FOURCHAN_DESC),
        
'codes'  => getApiCodes(),
        
'status' => array('ok'=>array(0),'warn'=>array(7)),
        
'version'=> VERSION);
    echo 
json_encode($res);
?>

dns.php

[Download]

<?php
    
/*
    LICENSE:
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
    The full license text can be found here: http://creativecommons.org/licenses/by-nc-sa/4.0/
    The link has an easy to understand version of the license and the full license text.

    DISCLAIMER:
    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    THE POSSIBILITY OF SUCH DAMAGE.
    */

    
require('include.php');
    
header('Content-Type: application/json');
    
$result=array('success'=>false);
    if(!empty(
$_GET['name'])){
        if(
checkNameFormat($_GET['name'])){
            if(
is4c($_GET['name'])){
                
$result['data']=getRecord($_GET['name']);
                
$result['success']=true;
            }
            else{
                
$result['data']='This is not a 4chan domain';
            }
        }
        else{
            
$result['data']='Invalid DNS name format';
        }
    }
    else{
        
$result['data']='DNS name not supplied';
    }
    echo 
json_encode($result);
    exit(
0);
?>

http.php

[Download]

<?php
    
/*
    LICENSE:
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
    The full license text can be found here: http://creativecommons.org/licenses/by-nc-sa/4.0/
    The link has an easy to understand version of the license and the full license text.

    DISCLAIMER:
    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    THE POSSIBILITY OF SUCH DAMAGE.
    */

    
require('include.php');
    
header('Content-Type: application/json');
    
$result=array('success'=>false);
    if(!empty(
$_GET['name'])){
        
$result['data']=check4c($_GET['name']);
        
$result['success']=true;
    }
    echo 
json_encode($result);
    exit(
0);
?>

index.php

[Download]

<?php
    
/*
    LICENSE:
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
    The full license text can be found here: http://creativecommons.org/licenses/by-nc-sa/4.0/
    The link has an easy to understand version of the license and the full license text.

    DISCLAIMER:
    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    THE POSSIBILITY OF SUCH DAMAGE.
    */
    
    // =====================================
    // Note: You can delete these lines  ===
    // when hosting the script yourself. ===
    
require('../tools/lib.php'); //      ===
    
handleCache(glob('*.php'));  //      ===
    // =====================================
    
    
require('include.php');
?><!DOCTYPE html>
<html lang="en">
    <head>
        <?php
            
//Bootstrap4 framework. You can copy the generated code from the HTML source
            
echo bs4(TRUE,TRUE);
        
?>
        <script defer src="4chan.js"></script>
        <title>4chan status checker</title>
        <style>
            code{
                background-color:#EEE;
                display:inline-block;
                padding:1px 10px;
                border-radius:3px;
            }
            .ok{
                color:#090;
            }
            .warn{
                color:#F80;
            }
            .error{
                color:#F00;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>4chan status checker</h1>
            <div class="alert alert-warning">
                4chan image and thumbnail servers have had some issues for a long time now.
                They seem to work but haven't been set up properly for the detection scripts.
                This happened at the time where they added IPv6 support to the two domains.
            </div>
            <p><i>If you are here for the 4chan filter extension, <a href="/tampermonkey/view.php?script=4chan.user.js">click here</a></i></p>
            <table class="table">
                <thead><tr><th>Name</th><th>IP addresses</th><th>Status</th></tr></thead>
                <tbody></tbody>
            </table>
            <p>
                <button class="btn btn-primary" type="button" id="again">Check again</button>
                <label>
                    <input type="checkbox" id="auto" />
                    <b>Auto</b> (<span id="autoTimer">0</span>)
                </label>
            </p>
            <p>
                Version <code><?php echo VERSION?></code><br />
                [<a href="source.php">Source Code</a>]<br />
                <?php if(defined('IP_ADDR') && constant('IP_ADDR')!==FALSE){
                    echo 
'Tests are performed from <code>'.htmlspecialchars(file_get_contents(IP_ADDR)).'</code>';
                } 
?>
            </p>
        </div>
    </body>
</html>

source.php

[Download]

<?php
    
/*
    LICENSE:
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
    The full license text can be found here: http://creativecommons.org/licenses/by-nc-sa/4.0/
    The link has an easy to understand version of the license and the full license text.

    DISCLAIMER:
    THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    THE POSSIBILITY OF SUCH DAMAGE.
    */
?><!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta http-equiv="pragma" content="no-cache" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>4chan status checker source code</title>
        <link rel="stylesheet" type="text/css" href="/bootstrap4/bootstrap.min.css" />
        <script defer src="/bootstrap4/jquery.slim.min.js"></script>
        <script defer src="/bootstrap4/popper.min.js"></script>
        <script defer src="/bootstrap4/bootstrap.min.js"></script>
    </head>
    <body>
        <div class="container-fluid">
            <h1>4chan status checker source</h1>
            <p>
                Feel free to download the files to host your own script.<br />
                These scripts use the bootstrap 4 framework.
                The source code viewer will not run without the Bootstrap JavaScript files, the online checker will
                but tooltips will not be there.<br />
                Do not forget to also download
                <a href="4chan.js" download>4chan.js</a> and
                <a href="lib.js" download>lib.js</a> for the checker to work.
            </p>
            <p>[<a href="./">Go Back</a>]</p>
            <?php
                
//List of PHP files we allow source viewing
                
$sources=array(
                    
'include.php',
                    
'info.php',
                    
'dns.php',
                    
'http.php',
                    
'index.php',
                    
'source.php'
                
);
            
?>
            <ul class="nav nav-pills">
            <?php
                
foreach($sources as $k=>$source){
                    echo 
'<li class="nav-item"><a class="nav-link'.($k==0?' active':'')."\" data-toggle=\"pill\" href=\"#cat$k\">$source</a></li>";
                }
            
?>
            </ul>
            <div class="tab-content">
                <?php
                    
foreach($sources as $k=>$source){
                        echo 
'<div class="tab-pane'.($k==0?' active':'')."\" id=\"cat$k\"><h2>$source</h2>";
                        echo 
'<p>[<a href="data:text/plain;base64,'.base64_encode(file_get_contents($source))."\" download=\"$source\">Download</a>]</p>";
                        
highlight_file($source);
                        echo 
'</div>';
                    }
                
?>
            </div>
        </div>
    </body>
</html>