2021-03-14 17:31:55 -04:00
< ? php
/* mysql_escape_mimic ( $inp )
* rand_string ( $length )
* get_time_ago ( $string )
* number_format_mod ( $number )
* format_filesize ( $bytes )
* reArrayFiles ( & $file_post )
* scrape_torrent ( $scraper , $external , $announce_url , $info_hash_array )
* decode_torrent ( $torrent , $torrent_hash )
* calc_total_transfer ( $completed , $size )
* update_stats ( $db , $s , $l , $c , $id )
*/
/*************************************
* General functions
*************************************/
function is_banned_asn ( $ip ) {
$ch = curl_init ();
// IMPORTANT: the below line is a security risk, read https://paragonie.com/blog/2017/10/certainty-automated-cacert-pem-management-for-php-software
// in most cases, you should set it to true
curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_URL , " https://api.iptoasn.com/v1/as/ip/ $ip " );
$result = curl_exec ( $ch );
curl_close ( $ch );
$obj = json_decode ( $result );
if ( in_array ( $obj -> as_number , BANNED_ASNS ))
return TRUE ;
else
return FALSE ;
}
function bayesian_average ( $ratings_array , $average_no_ratings_per_title , $average_rating , $site_average_rating ) {
$w = count ( $ratings_array ) / ( count ( $ratings_array ) + $average_no_ratings_per_title );
return $w * $average_rating + ( 1 - $w ) * $site_average_rating ;
}
function get_browser_lang ( $server ) {
$lang_header = $server [ 'HTTP_ACCEPT_LANGUAGE' ] ? ? 'en-GB' ;
if ( ! preg_match ( '#[a-zA-Z-_]+#' , $lang_header ))
$lang_header = 'en-GB' ;
$array = explode ( '-' , $lang_header );
return $array [ 0 ];
}
function get_country_code ( $ip = null ) {
if ( ! isset ( $ip ))
$ip = _IP ;
global $ipService ;
$locationRecord = $ipService -> getCountryRecord ( $ip );
if ( isset ( $locationRecord ) && is_object ( $locationRecord )) {
$countryCode = ( $locationRecord -> country ? ? $locationRecord -> registeredCountry ? ? $locationRecord -> representedCountry ) -> isoCode ? ? '??' ;
} else {
$countryCode = '??' ;
}
return strtolower ( $countryCode );
}
function get_continent_code ( $ip = null ) {
if ( ! isset ( $ip ))
$ip = _IP ;
global $ipService ;
$locationRecord = $ipService -> getCountryRecord ( $ip );
if ( isset ( $locationRecord ) && is_object ( $locationRecord )) {
$continentCode = $locationRecord -> continent -> code ? ? '??' ;
} else {
$continentCode = '??' ;
}
return strtolower ( $continentCode );
}
/**
* returns the server id for its code . codes are for example " eu " , " eu2 " , " na " , " na2 " , " na3 "
* @ param $code
* @ return int the server id that matches its code , - 1 if servercode was invalid
*/
function get_server_id_by_code ( $code ) {
$code = strtolower ( $code );
foreach ( IMAGE_SERVER_INFO AS $server_id => $server_info ) {
if ( $server_info [ 'server_code' ] === $code ) {
return $server_id ;
}
}
return - 1 ;
}
/**
* returns the closest image server id by the users location with a random fallback . keeps the selected server id sticky
* by hashing its with the ip .
* @ param null $continentCode
* @ param null $countryCode
* @ param null $serverContinentCode
* @ param null $selectedServerId
* @ return int always returns a valid server , even if region wasnt detected
*/
function get_server_id_by_geography ( $ip = null , & $continentCode = null , & $countryCode = null , & $serverContinentCode = null , & $selectedServerId = null ) {
if ( ! isset ( $ip ))
$ip = _IP ;
global $ipService ;
$locationRecord = $ipService -> getCountryRecord ( $ip );
if ( isset ( $locationRecord ) && is_object ( $locationRecord )) {
$continentCode = $locationRecord -> continent -> code ? ? '??' ;
$countryCode = ( $locationRecord -> country ? ? $locationRecord -> registeredCountry ? ? $locationRecord -> representedCountry ) -> isoCode ? ? '??' ;
} else {
$continentCode = '??' ;
$countryCode = '??' ;
}
$serverContinentCode = IMAGE_SERVER_CONTINENT_MAPPING [ strtolower ( $continentCode )] ? ? '??' ;
$possible_server_ids = [];
// Collect all image servers that belong to this continent
foreach ( IMAGE_SERVER_INFO AS $server_id => $server_info ) {
if ( $server_info [ 'continent_code' ] === strtolower ( $serverContinentCode ))
$possible_server_ids [] = $server_id ;
}
// Collect the numeric last part of the ip xxx.xxx.xxx.123, so 123 is our hash for the sticky random server selection
// if its ipv6, take the last bit and convert it from hex to int
if ( strpos ( _IP , ':' ) !== false ) {
$tmp = explode ( ':' , $ip );
$ip_hash = ( int ) hexdec ( end ( $tmp ));
} else {
$tmp = explode ( '.' , $ip );
$ip_hash = ( int ) end ( $tmp );
}
if ( empty ( $possible_server_ids )) {
// Not sure when this happens, but select one at random or we get into a zero division error below
$allServerIds = \array_keys ( IMAGE_SERVER_INFO );
return $allServerIds [ \array_rand ( $allServerIds )];
}
$index = $ip_hash % count ( $possible_server_ids ); // This returns a random sticky index for available server ids
$selectedServerId = $possible_server_ids [ $index ] ? ? 0 ;
return $selectedServerId ;
}
class Notify_Callback {
private $post_id ;
function __construct ( $post_id ) {
$this -> post_id = ( int ) $post_id ;
}
public function notify ( $matches ) {
global $sql , $user , $timestamp , $memcached ;
$username = substr ( $matches [ 0 ], 1 );
$user_id = $sql -> prep ( $matches [ 0 ], " SELECT user_id FROM mangadex_users WHERE username = ? " , [ $username ], 'fetchColumn' , '' );
if ( $user_id ) {
// Check if the user $user_id has the current user on his blocklist.
$mention_user = new User ( $user_id , 'user_id' );
$blockList = $mention_user -> get_blocked_user_ids ();
// Add the notification only if this user doesnt have the post author on his blocklist
if ( ! isset ( $blockList [ $user -> user_id ])) {
$sql -> modify ( 'add_notification' , " INSERT IGNORE INTO mangadex_notifications (notification_id, post_id, mentioner_user_id, mentionee_user_id, timestamp, is_read)
VALUES ( NULL , ? , ? , ? , ? , 0 ) " , [ $this->post_id , $user->user_id , $user_id , $timestamp ]);
$memcached -> delete ( " user_ { $user_id } _unread_notifications " );
$memcached -> delete ( " notifications_ $user_id " );
}
return " @[url= " . URL . " user/ $user_id ] { $username } [/url] " ;
}
else
return $matches [ 0 ];
}
}
function parse_template ( $templateName , $templateVar = [], $templateDir = 'bootstrap4' )
{
$absPath = ABSPATH . '/templates/' . $templateDir . '/' . str_replace ([ '../' , './' , '`' , '´ ' ], '' , $templateName ) . '.tpl.php' ;
if ( ! file_exists ( $absPath ))
throw new Exception ( " Template $templateName not found! " );
ob_start ();
include ( $absPath );
$content = ob_get_clean ();
return $content ;
}
function get_results_as_object ( $results , $id_name ) {
$obj = new \stdClass ();
foreach ( $results as $i => $row ) {
$obj -> { $i } = new \stdClass ();
foreach ( $row as $key => $value ) {
$obj -> { $i } -> $key = $value ;
}
$obj -> { $i } -> $id_name = $i ;
}
return $obj ;
}
function thread_label ( $name ) {
return str_replace ( array_keys ( THREAD_LABELS ), THREAD_LABELS , $name );
}
function make_links_clickable ( $text ) {
$res = preg_replace ( " !(^| \ s)((?:(?:f|ht)tp(?:s)?: \ / \ /)[-a-zA-Zа -яА-Я()0-9@:%_+.~#?&; \ / \ /=]+)( $ | \ s)!ui " , " $ 1<a href=' $ 2' target='_blank' rel='nofollow'> $ 2</a> $ 3 " , $text );
return $res ;
}
function hash_array ( $array ) {
return hash ( 'crc32b' , serialize ( $array ));
}
function validate_level ( $user , $type ) {
$levels = [
'guest' => 1 ,
'validating' => 2 ,
'member' => 3 ,
'contributor' => 4 ,
'gl' => 5 ,
'pu' => 6 ,
'pr' => 10 ,
'mod' => 11 ,
'gmod' => 12 ,
'admin' => 15
];
return isset ( $levels [ $type ]) && $user -> level_id >= $levels [ $type ];
}
function get_ip_bans ()
{
global $sql ;
$banlist = $sql -> prep ( 'ip_banlist' , " SELECT * FROM mangadex_ip_bans WHERE expires > UNIX_TIMESTAMP() ORDER BY expires ASC " , [], 'fetchAll' , PDO :: FETCH_ASSOC , 3600 );
$ips = [];
foreach ( $banlist AS $row ) {
if ( $row [ 'expires' ] > time ())
$ips [] = $row [ 'ip' ];
}
return $ips ;
}
function sanitizePostText ( $text ) {
// Strip excessive amount of space/tabs/newline
$text = preg_replace ( '#\s{5,}#' , " \n " , $text );
// break up long words
$match = [];
if ( preg_match_all ( " #[^ \ s] { 64,}# " , $text , $match , PREG_SET_ORDER )) {
foreach ( $match as $m ) {
$text = str_replace ( $m [ 0 ], implode ( ' ' , str_split ( $m [ 0 ], 64 )), $text );
}
}
return $text ;
}
function pagination ( $num_rows , $current_page , $limit , $sort = 0 ) {
$array [ 'num_rows' ] = $num_rows ;
$array [ 'current_page' ] = $current_page ;
$array [ 'limit' ] = $limit ;
$array [ 'sort' ] = $sort ;
$array [ 'offset' ] = $limit * $current_page - $limit ;
$array [ 'last_page' ] = ceil ( $num_rows / $limit );
if ( $current_page == 1 ) {
$array [ 'previous_page' ] = " - " ;
$array [ 'previous_class' ] = " disabled " ;
}
else {
$array [ 'previous_page' ] = $current_page - 1 ;
$array [ 'previous_class' ] = " paging " ;
}
if ( $current_page == $array [ 'last_page' ]) {
$array [ 'next_page' ] = " - " ;
$array [ 'next_class' ] = " disabled " ;
}
else {
$array [ 'next_page' ] = $current_page + 1 ;
$array [ 'next_class' ] = " paging " ;
}
return $array ;
}
function slugify ( $str ) {
$slugified = trim ( preg_replace ( '/\W+/' , '-' , strtolower ( html_entity_decode ( $str ))), " - " );
if ( empty ( $slugified )) {
$slugified = '-' ;
}
return $slugified ;
}
function prepare_in ( $array ) {
return count ( $array ) > 0 ? str_repeat ( " ?, " , count ( $array ) - 1 ) . " ? " : " " ;
}
function prepare_int ( $number ) {
if ( is_int ( $number ))
return $number ;
else
die ( " Error: Possible SQL injection. " );
}
function prepare_numeric ( $number ) {
if ( is_numeric ( $number ))
return $number ;
else
die ( " Error: Possible SQL injection. " );
}
function prepare_identifier ( $ident ) {
return " ` " . str_replace ( " ` " , " `` " , $ident ) . " ` " ;
}
function prepare_orderby ( $order , $allowed_orders ) {
$key = array_search ( $order , $allowed_orders ); // see if we have such a name
return $allowed_orders [ $key ]; //if not, first one will be set automatically. smart enuf :)
}
function read_dir ( $dir ) {
if ( $dir [ 0 ] !== '/' ) {
// make absolute if dir is relative
$dir = rtrim ( ABSPATH , '/' ) . '/' . $dir ;
}
return array_diff ( @ scandir ( $dir , SCANDIR_SORT_ASCENDING ), array ( '..' , '.' ));
}
function remove_padding ( $str ) {
if ( ltrim ( $str , '0' ) == '' || substr ( ltrim ( $str , '0' ), 0 , 1 ) == '.' ) {
return $str ;
} else {
return ltrim ( $str , '0' );
}
}
function strpos_recursive ( $haystack , $needle , $offset = 0 , & $results = []) {
$offset = strpos ( $haystack , $needle , $offset );
if ( $offset === false ) {
return $results ;
} else {
$results [] = $offset ;
return strpos_recursive ( $haystack , $needle , ( $offset + 1 ), $results );
}
}
function validate_image ( $file , $name = 'file' , $max_filesize = MAX_IMAGE_FILESIZE ) {
$arr = explode ( " . " , $file [ " name " ]);
$ext = strtolower ( end ( $arr ));
$validate_extention = in_array ( $ext , ALLOWED_IMG_EXT );
$validate_file_size = ( $file [ " size " ] <= $max_filesize ); //check file size
$validate_mime = in_array ( mime_content_type ( $file [ " tmp_name " ]), ALLOWED_MIME_TYPES );
$get_image_size = getimagesize ( $file [ " tmp_name " ]);
if ( $_FILES [ $name ][ " error " ])
return display_alert ( " danger " , " Failed " , " Error Code ( { $file [ 'error' ] } ). " );
elseif ( ! $validate_file_size )
return display_alert ( " danger " , " Failed " , " File size exceeds 1 MB. " );
elseif ( ! $validate_extention )
return display_alert ( " danger " , " Failed " , " A . $ext file, not an image. " );
elseif ( ! $validate_mime )
return display_alert ( " danger " , " Failed " , " Image failed validation. " );
elseif ( ! $get_image_size )
return display_alert ( " danger " , " Failed " , " Image cannot be processed. " );
else
return " " ;
}
function get_ext ( $filename , $type ) {
$value = explode ( " . " , $filename );
if ( $type )
return strtolower ( end ( $value ));
else
return current ( $value );
}
function isJson ( $string ) {
json_decode ( $string );
return ( json_last_error () == JSON_ERROR_NONE );
}
/* TODO : Remove this
function mysql_escape_mimic ( $inp ) {
if ( is_array ( $inp ))
return array_map ( __METHOD__ , $inp );
if ( ! empty ( $inp ) && is_string ( $inp )) {
return str_replace ( array ( '\\' , " \0 " , " \n " , " \r " , " ' " , '"' , " \x1a " ), array ( '\\\\' , '\\0' , '\\n' , '\\r' , " \\ ' " , '\\"' , '\\Z' ), $inp );
}
return $inp ;
}
*/
function sanitise_id ( $id ) {
if ( preg_match ( " /^-? \ d+ $ / " , $id ))
return $id ;
else
die ( " Error: Possible SQL injection. " );
}
function send_email ( $to , $subject , $body , $site = 2 ) {
$url = " https://mail.anidex.moe/ " ;
$data = [
'site' => $site ,
'to' => $to ,
'subject' => $subject ,
'body' => $body
];
$headers = [];
httpPost ( $url , $data , $headers );
}
/*
function send_email ( $to , $subject , $body ) {
require_once ( ABSPATH . " /scripts/phpmailer/src/PHPMailer.php " );
require_once ( ABSPATH . " /scripts/phpmailer/src/SMTP.php " );
require_once ( ABSPATH . " /scripts/phpmailer/src/Exception.php " );
$mail = new PHPMailer\PHPMailer\PHPMailer ;
$mail -> SMTPDebug = false ; //Enable SMTP debugging.
$mail -> isSMTP (); //Set PHPMailer to use SMTP.
$mail -> Host = SMTP_HOST ; //Set SMTP host name
$mail -> SMTPAuth = true ; //Set this to true if SMTP host requires authentication to send email
$mail -> Username = SMTP_USER ; //Provide username and password
$mail -> Password = SMTP_PASSWORD ;
$mail -> SMTPSecure = " tls " ; //If SMTP requires TLS encryption then set it
$mail -> Port = SMTP_PORT ; //Set TCP port to connect to
$mail -> From = SMTP_USER ;
$mail -> FromName = TITLE ; //From: sdbx.moe
$mail -> addBCC ( SMTP_BCC ); //bcc: holo@doki.co
$mail -> addReplyTo ( SMTP_USER ); //reply-to: mangadexstaff@gmail.com
$mail -> addAddress ( $to );
$mail -> Subject = $subject ;
$mail -> Body = $body ;
$mail -> send ();
}
*/
function rand_string ( $length ) {
$chars = " abcdefghkmnpqrstuvwxyzABCDEFGHKMNPQRSTUVWXYZ23456789 " ;
return substr ( str_shuffle ( $chars ), 0 , $length );
}
function rand_letter ( $length ) {
$chars = " abcdefghkmnqrstuvwxyzABCDEFGHKMNQRSTUVWXYZ " ;
return substr ( str_shuffle ( $chars ), 0 , $length );
}
function get_time_ago ( $ptime , $display_ago = TRUE , $maxAgeForNow = 1 ) {
$etime = abs ( time () - $ptime );
if ( ! $ptime )
return " Never " ;
elseif ( $etime < $maxAgeForNow )
return " Now " ;
$ago = ( $ptime < time () && $display_ago ) ? " <span class='d-none d-xl-inline'>ago</span> " : " " ;
$in = ( $ptime > time ()) ? " in " : " " ;
$a = array ( 365 * 24 * 60 * 60 => 'year' ,
30 * 24 * 60 * 60 => 'mo' ,
24 * 60 * 60 => 'day' ,
60 * 60 => 'hr' ,
60 => 'min' ,
1 => 'sec'
);
$a_plural = array ( 'year' => 'years' ,
'mo' => 'mo' ,
'day' => 'days' ,
'hr' => 'hrs' ,
'min' => 'mins' ,
'sec' => 'secs'
);
foreach ( $a as $secs => $str ) {
$d = $etime / $secs ;
if ( $d >= 1 ) {
$r = round ( $d );
return $in . $r . ' ' . ( $r > 1 ? $a_plural [ $str ] : $str ) . $ago ;
}
}
}
function number_format_mod ( $number ) {
if ( $number >= 100 )
return number_format ( $number , 0 );
else
return number_format ( $number , 1 );
}
function format_filesize ( $bytes ) {
if ( $bytes >= 1099511627776000 )
return number_format_mod ( $bytes / 1024 / 1024 / 1024 / 1024 / 1024 ) . " PB " ;
elseif ( $bytes >= 1073741824000 )
return number_format_mod ( $bytes / 1024 / 1024 / 1024 / 1024 ) . " TB " ;
elseif ( $bytes >= 1048576000 )
return number_format_mod ( $bytes / 1024 / 1024 / 1024 ) . " GB " ;
elseif ( $bytes >= 1024000 )
return number_format_mod ( $bytes / 1024 / 1024 ) . " MB " ;
elseif ( $bytes >= 1000 )
return number_format_mod ( $bytes / 1024 ) . " KB " ;
elseif ( $bytes >= 1 )
return $bytes . " B " ;
else
return " 0 B " ;
}
function reArrayFiles ( & $file_post ) {
$file_ary = [];
$file_count = count ( $file_post [ 'name' ]);
$file_keys = array_keys ( $file_post );
for ( $i = 0 ; $i < $file_count ; $i ++ ) {
foreach ( $file_keys as $key ) {
$file_ary [ $i ][ $key ] = $file_post [ $key ][ $i ];
}
}
return $file_ary ;
}
function strpos_arr ( $haystack , $needle ) {
if ( ! is_array ( $needle ))
$needle = array ( $needle );
foreach ( $needle as $what ) {
if (( $pos = strpos ( $haystack , $what )) !== false )
return $pos ;
}
return false ;
}
/* TODO : remove
function get_data ( $url ) {
$ch = curl_init ();
$timeout = 5 ;
curl_setopt ( $ch , CURLOPT_URL , $url );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , $timeout );
$data = curl_exec ( $ch );
curl_close ( $ch );
return $data ;
}
*/
/*
function download_file ( $url , $filepath ) {
set_time_limit ( 0 );
$file = fopen ( " $filepath " , " w+ " );
$curl = curl_init ( $url );
// Update as of PHP 5.4 [] can be written []
curl_setopt_array ( $curl , [
CURLOPT_URL => $url ,
CURLOPT_RETURNTRANSFER => 1 ,
CURLOPT_FILE => $file ,
CURLOPT_TIMEOUT => 50 ,
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'
]);
curl_exec ( $curl );
curl_close ( $curl );
}
*/
function httpPost ( $url , $data , $headers ) {
$curl = curl_init ( $url );
curl_setopt ( $curl , CURLOPT_HTTPHEADER , $headers );
curl_setopt ( $curl , CURLOPT_POST , true );
curl_setopt ( $curl , CURLOPT_POSTFIELDS , $data );
curl_setopt ( $curl , CURLOPT_RETURNTRANSFER , true );
$r = curl_exec ( $curl );
curl_close ( $curl );
return $r ;
}
function httpGet ( $url , $str ) {
$curl = curl_init ( $url );
curl_setopt ( $curl , CURLOPT_URL , $url . $str );
curl_setopt ( $curl , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $curl , CURLOPT_TIMEOUT , 3 );
$r = curl_exec ( $curl );
curl_close ( $curl );
return $r ;
}
function rrmdir ( $dir ) { //recursive delete folder
if ( is_dir ( $dir )) {
$objects = scandir ( $dir );
foreach ( $objects as $object ) {
if ( $object != " . " && $object != " .. " ) {
if ( is_dir ( $dir . " / " . $object ))
rrmdir ( $dir . " / " . $object );
else
@ unlink ( $dir . " / " . $object );
}
}
rmdir ( $dir );
}
}
/*************************************
* MangaDex functions
*************************************/
function remove_blocked_groups ( $chapters_array , $blocked_group_ids ) {
foreach ( $chapters_array as $key => $chapter ) {
if ( in_array ( $chapter [ 'group_id' ], array_keys ( $blocked_group_ids )))
unset ( $chapters_array [ $key ]);
}
return $chapters_array ;
}
function get_og_tags ( $page , $id ) {
global $sql , $parser ;
$id = ( int ) $id ;
$array [ 'keywords' ] = 'MangaDex, Manga Dex, Manga, Read Manga, Manga Online, Read Manga Free, Manga Scans, Free Manga, Read Manga Online' ;
$array [ 'image' ] = URL . " images/misc/default_brand.png?1 " ;
$array [ 'description' ] = DESCRIPTION ;
$array [ 'title' ] = TITLE ;
$array [ 'canonical' ] = '' ;
switch ( $page ) {
case " main " :
$array [ 'title' ] = " Latest updates - " . TITLE ;
$array [ 'canonical' ] = " <link rel='canonical' href=' " . URL . " ' /> " ;
break ;
case " search " :
$array [ 'title' ] = " Search - " . TITLE ;
$array [ 'canonical' ] = " <link rel='canonical' href=' " . URL . " search' /> " ;
break ;
case " chapter " :
$chapter = $sql -> prep ( " og_chapter_ $id " , '
SELECT mangas . manga_name , mangas . manga_id , mangas . manga_image , mangas . manga_description , chapters . volume , chapters . chapter , chapters . title
FROM mangadex_chapters AS chapters
LEFT JOIN mangadex_mangas AS mangas
ON chapters . manga_id = mangas . manga_id
WHERE chapters . chapter_id = ?
LIMIT 1 ', [$id], ' fetch ' , PDO :: FETCH_OBJ , 3600 );
if ( $chapter ) {
$parser -> parse ( $chapter -> manga_description );
$array [ 'keywords' ] = " $chapter->manga_name Chapter $chapter->chapter , $chapter->manga_name Volume $chapter->volume , $chapter->manga_name , $chapter->manga_name Manga, Read $chapter->manga_name online, $chapter->manga_name online For Free, Read $chapter->manga_name chapters for free, $chapter->manga_name chapters, $chapter->manga_name scans, $chapter->manga_name mangadex " ;
$array [ 'title' ] = (( $chapter -> volume ) ? " Vol. $chapter->volume " : " " ) . (( $chapter -> chapter ) ? " Ch. $chapter->chapter " : " " ) . (( ! $chapter -> volume && ! $chapter -> chapter ) ? " $chapter->title " : " " ) . " ( $chapter->manga_name ) - " . TITLE ;
$array [ 'image' ] = URL . " images/manga/ $chapter->manga_id .thumb.jpg " ;
$array [ 'description' ] = $parser -> getAsText ();
$array [ 'canonical' ] = " <link rel='canonical' href=' " . URL . " chapter/ $id ' /> " ;
}
break ;
case " genre " :
$genre = $sql -> prep ( " og_genre_ $id " , ' SELECT * FROM mangadex_genres WHERE genre_id = ? LIMIT 1 ' , [ $id ], 'fetch' , PDO :: FETCH_OBJ , 3600 );
if ( isset ( $genre -> genre_id )) {
$array [ 'title' ] = " $genre->genre_name (Genre) - " . TITLE ;
$array [ 'description' ] = $genre -> genre_description ;
$array [ 'canonical' ] = " <link rel='canonical' href=' " . URL . " genre/ $genre->genre_id / " . slugify ( $genre -> genre_name ) . " ' /> " ;
}
break ;
case " manga " :
case " title " :
$manga = $sql -> prep ( " og_manga_ $id " , ' SELECT manga_name, manga_id, manga_description FROM mangadex_mangas WHERE manga_id = ? LIMIT 1 ' , [ $id ], 'fetch' , PDO :: FETCH_OBJ , 3600 );
if ( isset ( $manga -> manga_id )) {
$parser -> parse ( $manga -> manga_description );
$array [ 'keywords' ] = " $manga->manga_name , $manga->manga_name Manga, Read $manga->manga_name online, $manga->manga_name online, $manga->manga_name online For Free, Read $manga->manga_name chapters for free, $manga->manga_name series, $manga->manga_name chapters, $manga->manga_name scans, $manga->manga_name mangadex " ;
$array [ 'title' ] = " $manga->manga_name (Title) - " . TITLE ;
$array [ 'image' ] = URL . " images/manga/ $manga->manga_id .thumb.jpg " ;
$array [ 'description' ] = $parser -> getAsText ();
$array [ 'canonical' ] = " <link rel='canonical' href=' " . URL . " title/ $manga->manga_id / " . slugify ( $manga -> manga_name ) . " ' /> " ;
}
break ;
case " user " :
$user = $sql -> prep ( " og_user_ $id " , ' SELECT user_id, username, avatar FROM mangadex_users WHERE user_id = ? LIMIT 1 ' , [ $id ], 'fetch' , PDO :: FETCH_OBJ , 3600 );
if ( isset ( $user -> user_id )) {
$array [ 'title' ] = " $user->username (User) - " . TITLE ;
$array [ 'image' ] = ( $user -> avatar ) ? URL . " images/avatars/ $user->user_id . $user->avatar " : URL . 'images/avatars/xmas' . (( $id % 2 ) + 1 ) . '.png' ;
$array [ 'canonical' ] = " <link rel='canonical' href=' " . URL . " user/ $user->user_id / " . slugify ( $user -> username ) . " ' /> " ;
}
break ;
case " list " :
$user = $sql -> prep ( " og_list_user_ $id " , ' SELECT user_id, username, avatar FROM mangadex_users WHERE user_id = ? LIMIT 1 ' , [ $id ], 'fetch' , PDO :: FETCH_OBJ , 3600 );
$array [ 'title' ] = " $user->username 's MDList - " . TITLE ;
$array [ 'image' ] = ( $user -> avatar ) ? URL . " images/avatars/ $user->user_id . $user->avatar " : URL . 'images/avatars/' . rand ( 1 , 3 ) . '.jpg' ;
$array [ 'canonical' ] = " <link rel='canonical' href=' " . URL . " list/ $user->user_id /' /> " ;
break ;
case " group " :
$group = $sql -> prep ( " og_group_ $id " , ' SELECT group_id, group_name FROM mangadex_groups WHERE group_id = ? LIMIT 1 ' , [ $id ], 'fetch' , PDO :: FETCH_OBJ , 3600 );
if ( isset ( $group -> group_id )) {
$array [ 'title' ] = " $group->group_name (Group) - " . TITLE ;
$array [ 'canonical' ] = " <link rel='canonical' href=' " . URL . " group/ $group->group_id / " . slugify ( $group -> group_name ) . " ' /> " ;
} else {
$array [ 'title' ] = 'Group not found' ;
}
break ;
case " forum " :
$forum_name = $sql -> prep ( " og_forum_ $id " , ' SELECT forum_name FROM mangadex_forums WHERE forum_id = ? LIMIT 1 ' , [ $id ], 'fetchColumn' , '' , 3600 );
$array [ 'title' ] = " $forum_name (Forum) - " . TITLE ;
break ;
case " thread " :
$thread_name = $sql -> prep ( " og_thread_ $id " , ' SELECT thread_name FROM mangadex_threads WHERE thread_id = ? LIMIT 1 ' , [ $id ], 'fetchColumn' , '' , 3600 );
$array [ 'title' ] = " $thread_name (Thread) - " . TITLE ;
break ;
case " titles " :
$array [ 'title' ] = " Manga titles - " . TITLE ;
break ;
default :
$array [ 'title' ] = ( $page ) ? ucfirst ( str_replace ( " _ " , " " , $page )) . " - " . TITLE : TITLE ;
break ;
}
return $array ;
}
function generate_thumbnail ( $file , $large ) {
if ( file_exists ( $file )) {
$thumbFile = preg_replace ( '/\\.[^.\\s]{3,4}$/' , '' , $file );
//$thumbFile = pathinfo($file, PATHINFO_FILENAME);
$thumbFile .= '.thumb.jpg' ;
// Setting the resize parameters
list ( $width , $height ) = getimagesize ( $file );
// Some broken images may return an invalid height/width. return, so we dont run into a division-by-zero error
if ( $width < 1 || $height < 1 || $width + $height > 10000 )
return ;
$modwidth = 100 ;
$modheight = $modwidth / $width * $height ;
// Creating the Canvas
$tn = imagecreatetruecolor ( $modwidth , $modheight );
$type = exif_imagetype ( $file );
switch ( $type ) {
case IMAGETYPE_JPEG :
$image = ImageCreateFromJPEG ( $file );
break ;
case IMAGETYPE_PNG :
$image = ImageCreateFromPNG ( $file );
break ;
case IMAGETYPE_GIF :
$image = ImageCreateFromGIF ( $file );
break ;
default :
exit ;
break ;
}
if ( $image ) {
// Resizing our image to fit the canvas
@ imagecopyresampled ( $tn , $image , 0 , 0 , 0 , 0 , $modwidth , $modheight , $width , $height );
// Save to file
@ imagejpeg ( $tn , $thumbFile , 85 );
//Free memory
@ imagedestroy ( $tn );
}
if ( $large ) {
$thumbFile = preg_replace ( '/\\.[^.\\s]{3,4}$/' , '' , $file );
if ( $large == 1 )
$thumbFile .= '.large.jpg' ;
else
$thumbFile .= " . $large .jpg " ;
// Setting the resize parameters
list ( $width , $height ) = getimagesize ( $file );
if ( $large == 1 )
$modwidth = 150 ;
else
$modwidth = $large ;
$modheight = $modwidth / $width * $height ;
// Creating the Canvas
$tn = imagecreatetruecolor ( $modwidth , $modheight );
$type = exif_imagetype ( $file );
switch ( $type ) {
case IMAGETYPE_JPEG :
$image = ImageCreateFromJPEG ( $file );
break ;
case IMAGETYPE_PNG :
$image = ImageCreateFromPNG ( $file );
break ;
case IMAGETYPE_GIF :
$image = ImageCreateFromGIF ( $file );
break ;
default :
exit ;
break ;
}
if ( $image ) {
// Resizing our image to fit the canvas
@ imagecopyresampled ( $tn , $image , 0 , 0 , 0 , 0 , $modwidth , $modheight , $width , $height );
// Save to file
@ imagejpeg ( $tn , $thumbFile , 85 );
//Free memory
@ imagedestroy ( $tn );
}
}
}
}
function redirect_url ( $target , $httpcode = 303 )
{
if ( $target { 0 } !== '/' && ! stripos ( $target , DOMAIN )) {
die ( 'Possible XSS Attack: Invalid redirection URL! Follow at your own risk: ' . $target );
}
http_response_code ( $httpcode );
header ( 'location: ' . $target );
die ();
}
/*************************************
* Update database
*************************************/
function update_cron_logs ( $type , $result ) {
global $sql ;
$sql -> modify ( 'update_cron_logs' , " INSERT INTO mangadex_logs_cron (id, timestamp, type, result) VALUES (NULL, UNIX_TIMESTAMP(), ?, ?) " , [ $type , $result ]);
}
function visit_log_cumulative ( $ip , $table = " visit " ) {
global $sql ;
$field = prepare_identifier ( " log_ $table " );
$sql -> modify ( 'visit_log_cumulative' , " INSERT INTO mangadex_logs (log_ip, log_visit, log_dl, log_rss, log_timestamp) VALUES (?, 0, 0, 0, UNIX_TIMESTAMP())
ON DUPLICATE KEY UPDATE $field = $field + 1 " , [ $ip ]);
}
function condenseUA ( $ua_str ) {
$user_agents = [ 'AhrefsBot' , 'bingbot' , 'Googlebot' , 'YandexBot' , 'Android' , 'iPad' , 'iPhone' , 'Macintosh' , 'Windows' , 'RSS' , 'Linux' , 'CrOS' ];
foreach ( $user_agents as $ua ) {
if ( strpos ( $ua_str , $ua ) !== false )
$string = $ua ;
}
$string = $string ? ? $ua_str ;
return $string ;
}
function visit_log ( $server , $ip , $user_id , $hentai_toggle = 0 , $table = " visits " ) {
global $sql ;
$timestamp = time ();
$query_string = ( isset ( $server [ 'QUERY_STRING' ])) ? substr ( str_replace ([ 'page=' , '&id=' , '&p=' , '&mode=' , '&type=' ], [ '/' , '/' , '/' , '/' , '/' ], $server [ 'QUERY_STRING' ]), 0 , 255 ) : " " ;
$referer = ( isset ( $server [ 'HTTP_REFERER' ])) ? substr ( str_replace ([ 'https://mangadex.org' , 'https://www.mangadex.org' ], [ '' , '' ], $server [ 'HTTP_REFERER' ]), 0 , 255 ) : " " ;
$user_agent = ( isset ( $server [ 'HTTP_USER_AGENT' ])) ? substr ( $server [ 'HTTP_USER_AGENT' ], 0 , 255 ) : " " ;
$user_agent_string = condenseUA ( $user_agent );
$sql -> modify ( 'visit_log' , " INSERT INTO mangadex_logs_ $table (visit_id, visit_ip, visit_user_id, visit_user_agent, visit_referrer, visit_timestamp, visit_page, visit_h_toggle)
VALUES ( NULL , ? , ? , ? , ? , UNIX_TIMESTAMP (), ? , ? ) " , [ $ip , $user_id , $user_agent_string , $referer , $query_string , $hentai_toggle ]);
global $memcached ;
$cache = $memcached -> get ( $ip );
if ( $cache === FALSE || $timestamp - $cache [ 1 ] > 600 ) {
$memcached -> set ( $ip , [ 1 , $timestamp ]);
}
else {
$memcached -> set ( $ip , [ $cache [ 0 ] + 1 , $cache [ 1 ]]);
}
}
function visit_log_api ( $server , $ip , $user_id , $hentai_toggle = 0 ) {
global $sql ;
$query_string = ( isset ( $server [ 'QUERY_STRING' ])) ? substr ( str_replace ([ 'page=' , '&id=' , '&p=' , '&mode=' , '&type=' ], [ '/' , '/' , '/' , '/' , '/' ], $server [ 'QUERY_STRING' ]), 0 , 255 ) : " " ;
$referer = ( isset ( $server [ 'HTTP_REFERER' ])) ? substr ( str_replace ([ 'https://mangadex.org' , 'https://mangadex.com' ], [ '' , '' ], $server [ 'HTTP_REFERER' ]), 0 , 255 ) : " " ;
$user_agent = ( isset ( $server [ 'HTTP_USER_AGENT' ])) ? substr ( $server [ 'HTTP_USER_AGENT' ], 0 , 255 ) : " " ;
$user_agent_string = condenseUA ( $user_agent );
$sql -> modify ( 'visit_log_api' , " INSERT INTO mangadex_logs_api (visit_id, visit_ip, visit_user_id, visit_user_agent, visit_referrer, visit_timestamp, visit_page, visit_h_toggle)
VALUES ( NULL , ? , ? , ? , ? , UNIX_TIMESTAMP (), ? , ? ) " , [ $ip , $user_id , $user_agent_string , $referer , $query_string , $hentai_toggle ]);
}
function update_views_v2 ( $type , $id , $ip , $user_id = 0 ) {
global $memcached , $sql ;
$name = " { $type } _ { $id } _ $ip " ;
$cache = $memcached -> get ( $name );
if ( $cache === FALSE ) {
$memcached -> set ( $name , TRUE , 3600 );
$table = prepare_identifier ( " mangadex_ { $type } s " );
$field = prepare_identifier ( " { $type } _views " );
$field_id = prepare_identifier ( " { $type } _id " );
$sql -> modify ( 'update_views_v2' , " UPDATE $table SET $field = $field + 1 WHERE $field_id = ? LIMIT 1 " , [ $id ]);
if ( $type == " chapter " ) {
$sql -> modify ( 'update_views_v2' , " INSERT INTO mangadex_chapter_live_views (timestamp, chapter_id, ip) VALUES (UNIX_TIMESTAMP(), ?, ?) " , [ $id , $ip ]);
if ( $user_id )
$sql -> modify ( 'update_views_v2' , " UPDATE mangadex_user_stats SET chapters_read = chapters_read + 1 WHERE user_id = ? " , [ $user_id ]);
}
}
}
function process_user_limit ( $limit = 600 , $prefix = '' , $reset_seconds = 600 , $expire_seconds = 86400 )
{
global $memcached ;
if ( isset ( $_SERVER [ 'HTTP_USER_AGENT' ]) && strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], 'Googlebot' ) !== FALSE ) {
// Perform a dns lookup
try {
$hostname = gethostbyaddr ( _IP );
if ( stripos ( $hostname , '.googlebot.com' ) === false && stripos ( $hostname , '.google.com' ) === false ) {
throw new \RuntimeException ( sprintf ( 'Possible googlebot useragent faking. Please check if IP "%s" and host "%s" are legit for the useragent "%s"' , _IP , $hostname , $_SERVER [ 'HTTP_USER_AGENT' ]), E_USER_ERROR );
}
} catch ( \RuntimeException $e ) {
die ();
} catch ( \Throwable $e ) {
trigger_error ( sprintf ( 'Exception thrown during googlebot reverse dns lookup: %s' , $e -> getMessage ()), E_USER_WARNING );
}
} else {
// limit everyone else
$ip = _IP ;
$visit_count = $memcached -> get ( $prefix . $ip );
if ( ! ( defined ( 'DISABLE_HITCOUNTER' ) && DISABLE_HITCOUNTER ) && $visit_count !== FALSE && $visit_count [ 0 ] > $limit ) {
return false ;
}
// Update limits
if ( $visit_count === false || time () - $visit_count [ 1 ] > $reset_seconds ) {
$memcached -> set ( $prefix . $ip , [ 1 , time ()], $expire_seconds );
} else {
$memcached -> set ( $prefix . $ip , [ $visit_count [ 0 ] + 1 , $visit_count [ 1 ]], $expire_seconds );
}
}
return true ;
}
function get_zip_originalsize ( $filename ) {
$size = 0 ;
$resource = zip_open ( $filename );
while ( $dir_resource = zip_read ( $resource )) {
$size += zip_entry_filesize ( $dir_resource );
}
zip_close ( $resource );
return $size ;
}
2021-03-19 16:06:32 -04:00
function get_banners ( $enabledOnly = true ){
global $sql ;
$query = "
SELECT banner_id , banners . user_id , username , ext , is_enabled , is_anonymous , levels . level_name , levels . level_colour
FROM mangadex_banners banners
JOIN mangadex_users users
ON banners . user_id = users . user_id
JOIN mangadex_user_levels levels
ON users . level_id = levels . level_id
" ;
if ( $enabledOnly ){
$query .= " WHERE is_enabled = 1 " ;
}
$banners = $sql -> prep ( " banners_ " . ( $enabledOnly ? " enabled " : " all " ), $query , [], 'fetchAll' , PDO :: FETCH_ASSOC , 600 );
return $banners ;
}
2021-03-14 17:31:55 -04:00
/*************************************
* Discord webhook
*************************************/
function post_on_discord ( $webhookUrl , $hookObject ) {
if ( $webhookUrl ) {
// Convert to json
$hookObject = json_encode ( $hookObject , JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
// Prepare
$ch = curl_init ();
curl_setopt_array ( $ch , [
CURLOPT_URL => $webhookUrl ,
CURLOPT_POST => true ,
CURLOPT_POSTFIELDS => $hookObject ,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json'
],
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_FAILONERROR => true
]);
// Post
try {
curl_exec ( $ch );
if ( curl_errno ( $ch )) {
trigger_error ( curl_error ( $ch ), E_USER_WARNING );
}
curl_close ( $ch );
} catch ( \Throwable $e ) {
// just consume the error
}
}
}