<?php
/**
*
* @author Benjamin Gillissen <hide@address.com>
*
* **************************************************************
Copyright (C) 2009 Benjamin Gillissen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details at:
http://www.gnu.org/copyleft/gpl.html
* **************************************************************
*/
class nb_fetch {
private static $isconn; //bool to know if curl is available
private static $cookfile; //path to session cookfile
private static $sesslifetime = 600; //10minutes in secondes
private static $curl; //the curl resource.
private static $islogged; //bool to know if login was ok
//check if curl is ok, init curl ressource, set some curl options
private static function connect(){
if ( ! CORE::isphpModLoaded('curl') ){
if ( ! CORE::LoadphpMod('curl') ){
errors::raise('NewzBin.com Fetcher (nb_fetch) require PHP Curl extension, please contact your system adminsitrator.', CORE_LOG_ALERT, 'NB_FETCH');
}
}
if ( isset(self::$isconn) ){ return self::$isconn; }
if ( !chrono::isinit('nb_fetch') ){ chrono::init('nb_fetch'); }
self::$cookfile = realpath(PATH_CACHE).'/newzbin_cooky.txt';
$hdl = @fopen(self::$cookfile, 'a+');
if ( FALSE === $hdl ){
errors::raise('Connection to NewzBin.com aborded, cooky file could not be created at '.self::$cookfile, CORE_LOG_ERROR, 'NB_FETCH');
self::$isconn = FALSE;return FALSE;
}
self::$curl = curl_init();
curl_setopt(self::$curl, CURLOPT_USERAGENT, 'swun');
curl_setopt(self::$curl, CURLOPT_COOKIEFILE, self::$cookfile);
curl_setopt(self::$curl, CURLOPT_COOKIEJAR, self::$cookfile);
curl_setopt(self::$curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt(self::$curl, CURLOPT_ENCODING , "gzip");
self::$isconn = TRUE;return TRUE;
}
//do a post query on login form page
public static function login($force=FALSE){
if ( ! self::connect() ){ return FALSE; }
if ( $force === FALSE ){
if ( self::is_loged() ){ return TRUE; }
if ( isset(self::$islogged) ){ return FALSE; }
}
$chr = chrono::start('nb_fetch');
$post['username'] = configs::get('newzbinv2', 'user');
$post['password'] = configs::get('newzbinv2', 'pass');
//recode postvar
$o="";
foreach ($post as $k=>$v){ $o.= "$k=".utf8_encode($v)."&"; }
$post=substr($o,0,-1);
curl_setopt(self::$curl, CURLOPT_POST, 1);
curl_setopt(self::$curl, CURLOPT_HEADER, 0);
curl_setopt(self::$curl, CURLOPT_REFERER, search_nbrid::base_url.'account/login/');
curl_setopt(self::$curl, CURLOPT_URL, search_nbrid::base_url.'account/login/');
curl_setopt(self::$curl, CURLOPT_POSTFIELDS, $post);
curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, 1);
$file = CORE::tempfile();
$dst = fopen($file, 'w');
if ( FALSE === $dst ){
errors::raise('NewzBin.com destination file could not be created, probably no valid temp folder detected by core::tempfile()', CORE_LOG_ERROR, 'NB_FETCH');
chrono::pause('nb_fetch', $chr);
return FALSE;
}
curl_setopt(self::$curl, CURLOPT_FILE, $dst);
$result = @curl_exec(self::$curl);
if ( 0 != curl_errno(self::$curl) ){
errors::raise('Login to NewzBin.com failed : curl error, '.curl_error(self::$curl), CORE_LOG_ERROR, 'NB_FETCH');
self::$islogged = FALSE;
chrono::pause('nb_fetch', $chr);
return FALSE;
}
$err = self::check_parse_error($file);
if ( $err !== TRUE ){
errors::raise('Login to Newzbin.com Failed : '.$err, CORE_LOG_ERROR, 'NB_FETCH');
unlink($file);
self::$islogged = FALSE;
chrono::pause('nb_fetch', $chr);
return FALSE;
}
unlink($file);
errors::raise('Login success to NewzBin.com', CORE_LOG_NOTICE, 'NB_FETCH');
self::$islogged = TRUE;
chrono::pause('nb_fetch', $chr);
return TRUE;
}
//tell if the loged session on newzbin.com is still
public static function is_loged(){
if ( isset(self::$islogged) ){ return self::$islogged; }
if ( !file_exists(self::$cookfile) ){ return FALSE; }
return ( filemtime(self::$cookfile) >= (time()-self::$sesslifetime) );
}
public static function normalize_report(&$data){
$data['gotdetails'] = TRUE;
$data['imdbid'] = '';
if ( isset($data['moreinfo']) ){
if ( ereg('imdb.com', $data['moreinfo']) ){
$tmp = split('imdb.com/title/tt', $data['moreinfo']);
if ( isset($tmp[1]) ){ $data['imdbid'] = str_replace('/', '', $tmp[1]); }
unset($tmp);
}
$data['moreinfo'] = str_replace("&", "&", $data['moreinfo']);
//$data['moreinfo'] = str_replace('http://', '', $data['moreinfo']);
//$data['moreinfo'] = 'http://'.rawurlencode($data['moreinfo']);
} else {
$data['moreinfo'] = '';
}
if ( isset($data['progress']) ){
if ( $data['progress'] == 'Report is complete' ){ $data['status'] = 'complete';
} elseif ( $data['progress'] == 'Report is still uploading' ){ $data['status'] = 'uploading';
} elseif ( $data['progress'] == 'Report is incomplete' ){ $data['status'] = 'incomplet';
} else { $data['status'] = 'unknow'; }
} else {
$data['status'] = 'notset';
}
if ( isset($data['postdate']) ){
$month = Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
$buf = split(' ', $data['postdate']);
$data['date'] = mktime( 0, 0, 0, (array_search($buf[2], $month)+1), $buf[1], $buf[3]);
unset($buf, $data['postdate']);
}
if ( is_array($data['groups']) ){
foreach($data['groups'] as $k => &$grp){
$grp = str_replace('alt.binaries.', 'a.b.', $grp);
}
}
if ( is_array($data['attributes']) ){
foreach($data['attributes'] as $k => &$attribs){
foreach($attribs as $n => &$attr){ $attr = htmlentities($attr, ENT_QUOTES); }
}
}
return $data;
}
//do a http authed request on RSS Feed and store result into a file, return tmp filename, or FALSE
public static function request($url, $auth=FALSE){
if ( $auth ){
if ( ! self::login(FALSE) ){
errors::raise('We are not loged to NewzBin.com, and request need auth, we keep going but without attributes', CORE_LOG_WARNING, 'NB_FETCH');
}
} elseif ( ! self::connect() ){
errors::raise('Connection Failure, trouble with curl ?', CORE_LOG_ERROR, 'NB_FETCH');
return FALSE;
}
$chr = chrono::start('nb_fetch');
$file = CORE::tempfile();
$dst = fopen($file, 'w');
if ( FALSE === $dst ){
errors::raise('NewzBin.com search destination file could not be created, probably no valid temp folder detected by core::tempfile()', CORE_LOG_ERROR, 'NB_FETCH');
chrono::pause('nb_fetch', $chr);
curl_close(self::$curl);
return FALSE;
}
curl_setopt(self::$curl, CURLOPT_REFERER, '');
curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, 0);
curl_setopt(self::$curl, CURLOPT_POST, 0);
curl_setopt(self::$curl, CURLOPT_HEADER, 0);
curl_setopt(self::$curl, CURLOPT_URL, $url);
curl_setopt(self::$curl, CURLOPT_FILE, $dst);
$result = @curl_exec(self::$curl);
if ( 0 != curl_errno(self::$curl) ){
errors::raise('Newzbin.com RSS Feed Request Failed : curl error, '.curl_error(self::$curl), CORE_LOG_ERROR, 'NB_FETCH');
curl_close(self::$curl);
chrono::pause('nb_fetch', $chr);
return FALSE;
}
curl_setopt(self::$curl, CURLOPT_REFERER, $url);
fclose($dst);
$err = self::check_parse_error($file);
if ( $err !== TRUE ){
errors::raise('Newzbin.com RSS Feed Request Failed : '.$err, CORE_LOG_ERROR, 'NB_FETCH');
unlink($file);
chrono::pause('fetch', $chr);
return FALSE;
}
chrono::pause('nb_fetch', $chr);
return $file;
}
private static function check_parse_error($file){
$c = file_get_contents($file);
if ( ! ereg("Error", $c) ){ return TRUE; }
$XML = new XMLReader();
if ( FALSE === $XML->open( $file ) ){
unset($XML);
$buf = split('><span>Error:</span>', $c);
if ( !isset($buf[1]) ){ file_put_contents(PATH_CACHE.'/nb_reply.html', $c); }
$err = split("</li>", $buf[1]);
} else {
$XML->setParserProperty(XMLReader::LOADDTD, FALSE);
$XML->setParserProperty(XMLReader::VALIDATE, FALSE);
$err = '?';
while ( $XML->read() ){
if ( $XML->nodeType == XMLReader::CDATA ){ $err = $XML->value;break; }
}
$XML->close();
unset($XML);
}
return $err;
}
//to dload a nzb file from nb.
public static function getnfo($txtid, $filename='truc'){
if ( ! self::login() ){ return FALSE; }
$chr = chrono::start('nb_fetch');
$post['n_filename'] = $filename;
$post['save_nfo_as'] = 'Save NFO As..';
curl_setopt(self::$curl, CURLOPT_REFERER, '');
curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt(self::$curl, CURLOPT_POST, 1);
curl_setopt(self::$curl, CURLOPT_HEADER, 0);
curl_setopt(self::$curl, CURLOPT_URL, search_nbrid::base_url.'nfo/view/png/'. $txtid . '/');
curl_setopt(self::$curl, CURLOPT_POSTFIELDS, $post);
$result = curl_exec(self::$curl);
if ( 0 != curl_errno(self::$curl) ){
errors::raise('NewzBin.com NFO Request Failed : curl error, '.curl_error(self::$curl), CORE_LOG_ERROR, 'NB_FETCH');
chrono::pause('nb_fetch', $chr);
return FALSE;
}
curl_close(self::$curl);
chrono::pause('nb_fetch', $chr);
return $result;
}
//to dload a nzb file from nb directID
public static function get_nzb($nbrid, $fileids=NULL){
$file = CORE::tempfile();
$dst = fopen($file, 'w');
if ( FALSE === $dst ){
errors::raise('NewzBin.org nzb destination file could not be created, probably no valid temp folder detected by core::tempfile()', CORE_LOG_ERROR, 'NB_FETCH');
curl_close(self::$curl);
return FALSE;
}
if ( $fileids !== NULL ){
$post['fileid'] = implode(',', $fileids);
} else {
$post['reportid'] = $nbrid;
}
errors::raise('DirectID call with : '.print_r($post, TRUE), CORE_LOG_NOTICE, 'NB_FETCH');
$post['username'] = configs::get('newzbinv2', 'user');
$post['password'] = configs::get('newzbinv2', 'pass');
$curl = curl_init();
curl_setopt($curl, CURLOPT_USERAGENT, 'swun');
curl_setopt($curl, CURLOPT_REFERER, '');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_URL, 'http://v3.newzbin.com/api/dnzb/');
@curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
curl_setopt($curl, CURLOPT_FILE, $dst);
$result = @curl_exec($curl);
if ( 0 != curl_errno($curl) ){
errors::raise('Curl error for NZB Request on NewzBin.org : '.curl_error($curl), CORE_LOG_ERROR, 'NB_FETCH');
curl_close($curl);
return FALSE;
}
$hsize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
curl_close($curl);
fclose($dst);
$src = fopen($file, 'r');
$headers = fread($src, $hsize);
$headers = split("\n", $headers);
foreach($headers as $k => &$header){
if ( ereg('X-DNZB-RCode: 200', $header) ){
$nfile = CORE::tempfile();
$dst = fopen($nfile, 'w');
while( FALSE !== ($line = fgets($src)) ){ fputs($dst, $line); }
fclose($src);unlink($file);
fclose($dst);
return $nfile;
}
if ( ereg('X-DNZB-RCode: 400', $header) ){ errors::raise("Newzbin.com : missing parameters", CORE_LOG_ERROR, 'NB_FETCH');break; }
if ( ereg('X-DNZB-RCode: 401', $header) ){ errors::raise("Newzbin.com : auth failure", CORE_LOG_ERROR, 'NB_FETCH');break; }
if ( ereg('X-DNZB-RCode: 402', $header) ){ errors::raise("Newzbin.com : payment required", CORE_LOG_ERROR, 'NB_FETCH');break; }
if ( ereg('X-DNZB-RCode: 404', $header) ){ errors::raise("Newzbin.com : DirectID returned no result", CORE_LOG_NOTICE, 'NB_FETCH');break; }
if ( ereg('X-DNZB-RCode: 450', $header) ){ errors::raise("Newzbin.com : max rate reached", CORE_LOG_NOTICE, 'NB_FETCH');break; }
if ( ereg('X-DNZB-RCode: 500', $header) ){ errors::raise("Newzbin.com : DirectID is down !", CORE_LOG_ERROR, 'NB_FETCH');break; }
if ( ereg('X-DNZB-RCode: 503', $header) ){ errors::raise("Newzbin.com : down for maintenance!", CORE_LOG_ERROR, 'NB_FETCH');break; }
}
unlink($file);
return FALSE;
}
}
return TRUE;