544 lines
36 KiB
PHP
Executable File
544 lines
36 KiB
PHP
Executable File
<?php
|
|
|
|
class JapScan
|
|
{
|
|
const HTTP = 'http://';
|
|
const JAPSCAN_DOMAIN = 'japscan.com';
|
|
const READ_PATH = 'lecture-en-ligne';
|
|
const CACHE_FOLDER = 'cache/';
|
|
|
|
public $asMangas; // safe manga => manga
|
|
|
|
public function __construct()
|
|
{
|
|
$this->asMangas = array();
|
|
}
|
|
|
|
public function getInitParameters()
|
|
{
|
|
$asMangas = $this->getMangas();
|
|
return json_encode(array( 'asConsts' => array('domain'=>self::JAPSCAN_DOMAIN, 'read_path'=>self::READ_PATH),
|
|
'asMangas' => $asMangas['mangas'],
|
|
'asMangaIds' => $asMangas['mangaids']));
|
|
}
|
|
|
|
public function getMangas()
|
|
{
|
|
//TODO delete
|
|
//return json_decode('{"mangas":[{"short":"3-gatsu-no-lion","long":"3 Gatsu No Lion"},{"short":"a-bout","long":"A Bout"},{"short":"a-fairytale-for-the-demon-lord","long":"A Fairytale For The Demon Lord"},{"short":"abide-in-the-wind","long":"Abide In The Wind"},{"short":"ability","long":"Ability"},{"short":"abnormal-kei-joshi","long":"Abnormal Kei Joshi"},{"short":"absolute-duo","long":"Absolute Duo"},{"short":"ace-of-diamond","long":"Ace Of Diamond"},{"short":"again","long":"Again"},{"short":"aiki","long":"Aiki"},{"short":"aiki-s","long":"Aiki S"},{"short":"aimane","long":"Aimane"},{"short":"air-gear","long":"Air Gear"},{"short":"aiyoku-no-eustia","long":"Aiyoku No Eustia"},{"short":"ajin","long":"Ajin"},{"short":"akame-ga-kiru","long":"Akame Ga Kiru"},{"short":"all-you-need-is-kill","long":"All You Need Is Kill"},{"short":"amagoi","long":"Amagoi"},{"short":"amilova","long":"Amilova"},{"short":"anagle-mole","long":"Anagle Mole"},{"short":"ane-log","long":"Ane Log"},{"short":"angel-beats","long":"Angel Beats"},{"short":"apocalypse-no-toride","long":"Apocalypse No Toride"},{"short":"arachnid","long":"Arachnid"},{"short":"arago","long":"Arago"},{"short":"area-d","long":"Area D"},{"short":"area-no-kishi","long":"Area No Kishi"},{"short":"ares","long":"Ares"},{"short":"arslan-senki","long":"Arslan Senki"},{"short":"assassination-classroom","long":"Assassination Classroom"},{"short":"ayu-mayu","long":"Ayu Mayu"},{"short":"b-ichi","long":"B Ichi"},{"short":"bad-company","long":"Bad Company"},{"short":"bakudan","long":"Bakudan"},{"short":"bakuman","long":"Bakuman"},{"short":"bamboo-blade-b","long":"Bamboo Blade B"},{"short":"beelzebub","long":"Beelzebub"},{"short":"beelzebub-side-story","long":"Beelzebub Side Story"},{"short":"birdmen","long":"Birdmen"},{"short":"black-bullet","long":"Black Bullet"},{"short":"black-butler","long":"Black Butler"},{"short":"black-haze","long":"Black Haze"},{"short":"black-wind","long":"Black Wind"},{"short":"blast","long":"Blast"},{"short":"bleach","long":"Bleach"},{"short":"blind-faith-descent","long":"Blind Faith Descent"},{"short":"blood-parade","long":"Blood Parade"},{"short":"bocchiman","long":"Bocchiman"},{"short":"bonnouji","long":"Bonnouji"},{"short":"bowling-king","long":"Bowling King"},{"short":"broken-blade","long":"Broken Blade"},{"short":"btooom","long":"Btooom"},{"short":"buyuden","long":"Buyuden"},{"short":"cavalier-of-the-abyss","long":"Cavalier Of The Abyss"},{"short":"cerberus","long":"Cerberus"},{"short":"chaos-head","long":"Chaos Head"},{"short":"chaser","long":"Chaser"},{"short":"cherry-x-cherry","long":"Cherry X Cherry"},{"short":"choukakou","long":"Choukakou"},{"short":"chrome-shelled-regios-missing-mail","long":"Chrome Shelled Regios Missing Mail"},{"short":"chronos-deep","long":"Chronos Deep"},{"short":"city-of-darkness","long":"City Of Darkness"},{"short":"city-of-dead-sorcerer","long":"City of Dead Sorcerer"},{"short":"classmate-kamimura-yuuka-wa-kou-itta","long":"Classmate Kamimura Yuuka Wa Kou Itta"},{"short":"claymore","long":"Claymore"},{"short":"clockwork-planet","long":"Clockwork Planet"},{"short":"clover","long":"Clover"},{"short":"code-breaker","long":"Code Breaker"},{"short":"countrouble","long":"Countrouble"},{"short":"crepuscule","long":"Crepuscule"},{"short":"cromartie-high-school","long":"Cromartie High School"},{"short":"cross-manage","long":"Cross Manage"},{"short":"crows","long":"Crows"},{"short":"crows-zero-ii","long":"Crows Zero II"},{"short":"d-gray-man","long":"D Gray Man"},{"short":"d-fragments","long":"D-Fragments"},{"short":"dice","long":"D.I.C.E"},{"short":"dagasy","long":"Dagasy"},{"short":"darker-than-black-shikkoku-no-hana","long":"Darker Than Black - Shikkoku No Hana"},{"short":"deadman-wonderland","long":"Deadman Wonderland"},{"short":"death-note","long":"Death Note"},{"short":"deathtopia","long":"Deathtopia"},{"short":"dendrobates","long":"Dendrobates"},{"short":"denpa-kyoushi","long":"Denpa Kyoushi"},{"short":"densetsu-no-yuusha-no-densetsu","long":"Densetsu no Yuusha no Densetsu"},{"short":"dimension-w","long":"Dimension W"},{"short":"donten-prism-solar-car","long":"Donten Prism Solar Car"},{"short":"donyatsu","long":"Donyatsu"},{"short":"dragon-recipe","long":"Dragon Recipe"},{"short":"dragons-rioting","long":"Dragons Rioting"},{"short":"drop","long":"Drop"},{"short":"drop-og","long":"Drop OG"},{"short":"durarara","long":"Durarara!!"},{"short":"eden-no-ori","long":"Eden No Ori"},{"short":"eternal-sonata","long":"Eternal Sonata"},{"short":"fable","long":"Fable"},{"short":"fairy-tail","long":"Fairy Tail"},{"short":"fairy-tail-ice-trail","long":"Fairy Tail Ice Trail"},{"short":"fairy-tail-zero","long":"Fairy Tail Zero"},{"short":"feng-shen-ji","long":"Feng Shen Ji"},{"short":"flags","long":"Flags"},{"short":"fullmetal-alchemist","long":"Fullmetal Alchemist"},{"short":"fuuka","long":"Fuuka"},{"short":"gamaran","long":"Gamaran"},{"short":"gamble-fish","long":"Gamble Fish"},{"short":"gepetto","long":"Gepetto"},{"short":"giant-killing","long":"Giant Killing"},{"short":"gigantomakhia","long":"Gigantomakhia"},{"short":"gintama","long":"Gintama"},{"short":"girls-of-the-wilds","long":"Girls of the Wild\'s"},{"short":"good-robot","long":"Good Robot"},{"short":"green-blood","long":"Green Blood"},{"short":"green-boy","long":"Green Boy"},{"short":"gto","long":"GTO"},{"short":"gto-paradise-lost","long":"GTO Paradise Lost"},{"short":"hachi","long":"Hachi"},{"short":"haikyuu","long":"Haikyuu"},{"short":"hajime-no-ippo","long":"Hajime No Ippo"},{"short":"half-and-half","long":"Half & Half"},{"short":"half-prince","long":"Half Prince"},{"short":"hidan-no-aria","long":"Hidan No Aria"},{"short":"hinomaru-zumou","long":"Hinomaru Zumou"},{"short":"historie","long":"Historie"},{"short":"hitogatana","long":"Hitogatana"},{"short":"holyland","long":"Holyland"},{"short":"hungry-joker","long":"Hungry Joker"},{"short":"hunter-x-hunter","long":"Hunter X Hunter"},{"short":"ichiban-ushiro-no-daimaou","long":"Ichiban Ushiro No Daimaou"},{"short":"ichiro-heian","long":"Ichiro Heian"},{"short":"id","long":"Id"},{"short":"illegal-rare","long":"Illegal Rare"},{"short":"immortal-hounds","long":"Immortal Hounds"},{"short":"inu-yashiki","long":"Inu Yashiki"},{"short":"iron-knight","long":"Iron Knight"},{"short":"jaco","long":"Jaco"},{"short":"ko","long":"K.O"},{"short":"kamen-teacher","long":"Kamen Teacher"},{"short":"kamisama-ga-uso-o-tsuku","long":"Kamisama Ga Uso o Tsuku"},{"short":"kansen-rettou","long":"Kansen Rettou"},{"short":"kanshikan-tsunemori-akane","long":"Kanshikan Tsunemori Akane"},{"short":"karate-shoukoushi-kohinata-minoru","long":"Karate Shoukoushi Kohinata Minoru"},{"short":"kenichi","long":"Kenichi"},{"short":"keyman","long":"Keyman"},{"short":"kiku","long":"Kiku"},{"short":"kill-me-baby","long":"Kill Me Baby"},{"short":"killer-stall","long":"Killer Stall"},{"short":"kimi-no-iru-machi","long":"Kimi No Iru Machi"},{"short":"kingdom","long":"Kingdom"},{"short":"kingdom-game","long":"Kingdom Game"},{"short":"kiriwo-terrible","long":"Kiriwo Terrible"},{"short":"kiss-wood","long":"Kiss Wood"},{"short":"kubera","long":"Kubera"},{"short":"kurogane","long":"Kurogane"},{"short":"kuroko-no-basket","long":"Kuroko No Basket"},{"short":"kyuupi","long":"Kyuupi"},{"short":"last-ranker","long":"Last Ranker"},{"short":"layers","long":"Layers"},{"short":"legend-of-tyr","long":"Legend Of Tyr"},{"short":"les-aventures-de-sinbad","long":"Les Aventures De Sinbad"},{"short":"lessa","long":"Lessa"},{"short":"loveplus-rinko-days","long":"Loveplus Rinko Days"},{"short":"maga-tsuki","long":"Maga Tsuki"},{"short":"magi","long":"Magi"},{"short":"magician","long":"Magician"},{"short":"mahou-tsukai-no-yome","long":"Mahou Tsukai No Yome"},{"short":"mahouka-koukou-no-rettousei","long":"Mahouka Koukou No Rettousei"},{"short":"major","long":"Major"},{"short":"marchs-rabbit","long":"March\'s Rabbit"},{"short":"marionette","long":"Marionette"},{"short":"metallica-metalluca","long":"Metallica Metalluca"},{"short":"mother-keeper","long":"Mother Keeper"},{"short":"muvLuv-alternative","long":"Muvluv Alternative"},{"short":"muvluv-unlimited","long":"Muvluv Unlimited"},{"short":"my-hero-academia","long":"My Hero Academia"},{"short":"nanatsu-no-taizai","long":"Nanatsu No Taizai"},{"short":"naruto","long":"Naruto"},{"short":"natsu-no-arashi","long":"Natsu No Arashi"},{"short":"nisekoi","long":"Nisekoi"},{"short":"no-6","long":"No 6"},{"short":"noblesse","long":"Noblesse"},{"short":"nobunaga-no-chef","long":"Nobunaga No Chef"},{"short":"noragami","long":"Noragami"},{"short":"noragami-shuuishuu","long":"Noragami Shuuishuu"},{"short":"one-piece","long":"One Piece"},{"short":"one-punch-man","long":"One Punch Man"},{"short":"over-image","long":"Over Image"},{"short":"over-steam","long":"Over Steam"},{"short":"owari-no-seraph","long":"Owari No Seraph"},{"short":"pandora-hearts","long":"Pandora Hearts"},{"short":"papi-nyang","long":"Papi Nyang"},{"short":"pastel","long":"Pastel"},{"short":"pokemon-festival-of-champions","long":"Pokemon Festival Of Champions"},{"short":"psyren","long":"Psyren"},{"short":"rakshasa-street","long":"Rakshasa Street"},{"short":"ran-to-haiiro-no-sekai","long":"Ran To Haiiro No Sekai"},{"short":"real-pg","long":"Real PG"},{"short":"rebirth-knight","long":"Rebirth Knight"},{"short":"regarding-death","long":"Regarding Death"},{"short":"rin","long":"Rin"},{"short":"rising-x-rydeen","long":"Rising X Rydeen"},{"short":"rock-lee","long":"Rock Lee"},{"short":"rose-guns-days-saison-1","long":"Rose Guns Days Saison 1"},{"short":"rrr","long":"RRR!"},{"short":"saijou-no-meii","long":"Saijou No Meii"},{"short":"samurai-high-school","long":"Samurai High School"},{"short":"seitokai-yakuindomo","long":"Seitokai Yakuindomo"},{"short":"sengoku-strays","long":"Sengoku Strays"},{"short":"sensei-no-bulge","long":"Sensei No Bulge"},{"short":"shingeki-no-kyojin","long":"Shingeki No Kyojin"},{"short":"shingeki-no-kyojin-before-the-fall","long":"Shingeki No Kyojin Before The Fall"},{"short":"shinmai-fukei-kiruko-san","long":"Shinmai Fukei Kiruko-San"},{"short":"shokugeki-no-soma","long":"Shokugeki No Soma"},{"short":"silver-spoon","long":"Silver Spoon"},{"short":"soul-cartel","long":"Soul Cartel"},{"short":"soul-eater","long":"Soul Eater"},{"short":"spiral-alive","long":"Spiral Alive"},{"short":"spirit-circle","long":"Spirit Circle"},{"short":"sporting-salt","long":"Sporting Salt"},{"short":"stealth-symphony","long":"Stealth Symphony"},{"short":"sugarless","long":"Sugarless"},{"short":"superior-day","long":"Superior Day"},{"short":"tail-star","long":"Tail Star"},{"short":"tal","long":"Tal"},{"short":"tales-of-graces-f","long":"Tales Of Graces F"},{"short":"te-to-kuchi","long":"Te To Kuchi"},{"short":"tears-to-tiara","long":"Tears To Tiara"},{"short":"the-breaker","long":"The Breaker"},{"short":"the-breaker-new-waves","long":"The Breaker New Waves"},{"short":"the-devil-king-is-bored","long":"The Devil King Is Bored"},{"short":"the-gamer","long":"The Gamer"},{"short":"the-god-of-high-school","long":"The God Of High School"},{"short":"the-shape-of-voice","long":"The Shape Of Voice"},{"short":"threads-of-time","long":"Threads Of Time"},{"short":"to-aru-kagaku-no-accelerator","long":"To Aru Kagaku No Accelerator"},{"short":"to-aru-kagaku-no-railgun","long":"To Aru Kagaku No Railgun"},{"short":"tokage","long":"Tokage"},{"short":"tokko","long":"Tokko"},{"short":"tokyo-ghoul","long":"Tokyo Ghoul"},{"short":"toriko","long":"Toriko"},{"short":"tower-of-god","long":"Tower Of God"},{"short":"trace-15","long":"Trace 1.5"},{"short":"trace-20","long":"Trace 2.0"},{"short":"transfer-student-storm-bringer","long":"Transfer Student Storm Bringer"},{"short":"trump","long":"Trump"},{"short":"twin-star-exorcists","long":"Twin Star Exorcists"},{"short":"ultimate-legend","long":"Ultimate Legend"},{"short":"ultraduck","long":"Ultraduck"},{"short":"umineko-episode-1","long":"Umineko Episode 1"},{"short":"umineko-episode-2","long":"Umineko Episode 2"},{"short":"umineko-episode-3","long":"Umineko Episode 3"},{"short":"under-prin","long":"Under Prin"},{"short":"uq-holder","long":"UQ Holder"},{"short":"usogui","long":"Usogui"},{"short":"vagabond","long":"Vagabond"},{"short":"vampire-knight","long":"Vampire Knight"},{"short":"ws","long":"W\'s"},{"short":"wa","long":"Wa!"},{"short":"wake-up-deadman","long":"Wake Up Deadman"},{"short":"watamote","long":"Watamote"},{"short":"weiss","long":"Weiss"},{"short":"welcome-to-the-el-palacio","long":"Welcome To The El Palacio"},{"short":"wild-life","long":"Wild Life"},{"short":"wolfs-castle","long":"Wolf\'s Castle"},{"short":"wolfs-rain","long":"Wolf\u2019s Rain"},{"short":"working","long":"Working"},{"short":"world-trigger","long":"World Trigger"},{"short":"worst","long":"Worst"},{"short":"yamada-kun-to-7-nin-no-majo","long":"Yamada-kun To 7 Nin No Majo"},{"short":"yandere-kanojo","long":"Yandere Kanojo"},{"short":"yasashii-sekai-no-tsukurikata","long":"Yasashii Sekai No Tsukurikata"},{"short":"yellow-dragon-ga-arawareta","long":"Yellow Dragon Ga Arawareta"},{"short":"zettai-joousei","long":"Zettai Joousei"},{"short":"zodiac-game","long":"Zodiac Game"},{"short":"zusun","long":"Zusun"}],"mangaids":{"3-gatsu-no-lion":0,"a-bout":1,"a-fairytale-for-the-demon-lord":2,"abide-in-the-wind":3,"ability":4,"abnormal-kei-joshi":5,"absolute-duo":6,"ace-of-diamond":7,"again":8,"aiki":9,"aiki-s":10,"aimane":11,"air-gear":12,"aiyoku-no-eustia":13,"ajin":14,"akame-ga-kiru":15,"all-you-need-is-kill":16,"amagoi":17,"amilova":18,"anagle-mole":19,"ane-log":20,"angel-beats":21,"apocalypse-no-toride":22,"arachnid":23,"arago":24,"area-d":25,"area-no-kishi":26,"ares":27,"arslan-senki":28,"assassination-classroom":29,"ayu-mayu":30,"b-ichi":31,"bad-company":32,"bakudan":33,"bakuman":34,"bamboo-blade-b":35,"beelzebub":36,"beelzebub-side-story":37,"birdmen":38,"black-bullet":39,"black-butler":40,"black-haze":41,"black-wind":42,"blast":43,"bleach":44,"blind-faith-descent":45,"blood-parade":46,"bocchiman":47,"bonnouji":48,"bowling-king":49,"broken-blade":50,"btooom":51,"buyuden":52,"cavalier-of-the-abyss":53,"cerberus":54,"chaos-head":55,"chaser":56,"cherry-x-cherry":57,"choukakou":58,"chrome-shelled-regios-missing-mail":59,"chronos-deep":60,"city-of-darkness":61,"city-of-dead-sorcerer":62,"classmate-kamimura-yuuka-wa-kou-itta":63,"claymore":64,"clockwork-planet":65,"clover":66,"code-breaker":67,"countrouble":68,"crepuscule":69,"cromartie-high-school":70,"cross-manage":71,"crows":72,"crows-zero-ii":73,"d-gray-man":74,"d-fragments":75,"dice":76,"dagasy":77,"darker-than-black-shikkoku-no-hana":78,"deadman-wonderland":79,"death-note":80,"deathtopia":81,"dendrobates":82,"denpa-kyoushi":83,"densetsu-no-yuusha-no-densetsu":84,"dimension-w":85,"donten-prism-solar-car":86,"donyatsu":87,"dragon-recipe":88,"dragons-rioting":89,"drop":90,"drop-og":91,"durarara":92,"eden-no-ori":93,"eternal-sonata":94,"fable":95,"fairy-tail":96,"fairy-tail-ice-trail":97,"fairy-tail-zero":98,"feng-shen-ji":99,"flags":100,"fullmetal-alchemist":101,"fuuka":102,"gamaran":103,"gamble-fish":104,"gepetto":105,"giant-killing":106,"gigantomakhia":107,"gintama":108,"girls-of-the-wilds":109,"good-robot":110,"green-blood":111,"green-boy":112,"gto":113,"gto-paradise-lost":114,"hachi":115,"haikyuu":116,"hajime-no-ippo":117,"half-and-half":118,"half-prince":119,"hidan-no-aria":120,"hinomaru-zumou":121,"historie":122,"hitogatana":123,"holyland":124,"hungry-joker":125,"hunter-x-hunter":126,"ichiban-ushiro-no-daimaou":127,"ichiro-heian":128,"id":129,"illegal-rare":130,"immortal-hounds":131,"inu-yashiki":132,"iron-knight":133,"jaco":134,"ko":135,"kamen-teacher":136,"kamisama-ga-uso-o-tsuku":137,"kansen-rettou":138,"kanshikan-tsunemori-akane":139,"karate-shoukoushi-kohinata-minoru":140,"kenichi":141,"keyman":142,"kiku":143,"kill-me-baby":144,"killer-stall":145,"kimi-no-iru-machi":146,"kingdom":147,"kingdom-game":148,"kiriwo-terrible":149,"kiss-wood":150,"kubera":151,"kurogane":152,"kuroko-no-basket":153,"kyuupi":154,"last-ranker":155,"layers":156,"legend-of-tyr":157,"les-aventures-de-sinbad":158,"lessa":159,"loveplus-rinko-days":160,"maga-tsuki":161,"magi":162,"magician":163,"mahou-tsukai-no-yome":164,"mahouka-koukou-no-rettousei":165,"major":166,"marchs-rabbit":167,"marionette":168,"metallica-metalluca":169,"mother-keeper":170,"muvLuv-alternative":171,"muvluv-unlimited":172,"my-hero-academia":173,"nanatsu-no-taizai":174,"naruto":175,"natsu-no-arashi":176,"nisekoi":177,"no-6":178,"noblesse":179,"nobunaga-no-chef":180,"noragami":181,"noragami-shuuishuu":182,"one-piece":183,"one-punch-man":184,"over-image":185,"over-steam":186,"owari-no-seraph":187,"pandora-hearts":188,"papi-nyang":189,"pastel":190,"pokemon-festival-of-champions":191,"psyren":192,"rakshasa-street":193,"ran-to-haiiro-no-sekai":194,"real-pg":195,"rebirth-knight":196,"regarding-death":197,"rin":198,"rising-x-rydeen":199,"rock-lee":200,"rose-guns-days-saison-1":201,"rrr":202,"saijou-no-meii":203,"samurai-high-school":204,"seitokai-yakuindomo":205,"sengoku-strays":206,"sensei-no-bulge":207,"shingeki-no-kyojin":208,"shingeki-no-kyojin-before-the-fall":209,"shinmai-fukei-kiruko-san":210,"shokugeki-no-soma":211,"silver-spoon":212,"soul-cartel":213,"soul-eater":214,"spiral-alive":215,"spirit-circle":216,"sporting-salt":217,"stealth-symphony":218,"sugarless":219,"superior-day":220,"tail-star":221,"tal":222,"tales-of-graces-f":223,"te-to-kuchi":224,"tears-to-tiara":225,"the-breaker":226,"the-breaker-new-waves":227,"the-devil-king-is-bored":228,"the-gamer":229,"the-god-of-high-school":230,"the-shape-of-voice":231,"threads-of-time":232,"to-aru-kagaku-no-accelerator":233,"to-aru-kagaku-no-railgun":234,"tokage":235,"tokko":236,"tokyo-ghoul":237,"toriko":238,"tower-of-god":239,"trace-15":240,"trace-20":241,"transfer-student-storm-bringer":242,"trump":243,"twin-star-exorcists":244,"ultimate-legend":245,"ultraduck":246,"umineko-episode-1":247,"umineko-episode-2":248,"umineko-episode-3":249,"under-prin":250,"uq-holder":251,"usogui":252,"vagabond":253,"vampire-knight":254,"ws":255,"wa":256,"wake-up-deadman":257,"watamote":258,"weiss":259,"welcome-to-the-el-palacio":260,"wild-life":261,"wolfs-castle":262,"wolfs-rain":263,"working":264,"world-trigger":265,"worst":266,"yamada-kun-to-7-nin-no-majo":267,"yandere-kanojo":268,"yasashii-sekai-no-tsukurikata":269,"yellow-dragon-ga-arawareta":270,"zettai-joousei":271,"zodiac-game":272,"zusun":273}}', true);
|
|
|
|
if(empty($this->asMangas))
|
|
{
|
|
$oDom = $this->getPageDom();
|
|
$aoOptions = $this->getSelectOptions($oDom, 'mangas');
|
|
foreach($aoOptions as $oOption)
|
|
{
|
|
//Manga Short Name
|
|
$sShortManga = mb_strstr(mb_substr($oOption->getAttribute('value'), mb_strlen('/'.self::READ_PATH.'/')), '/', true);
|
|
|
|
//Manga Long Name
|
|
$sMangaLong = $oOption->nodeValue;
|
|
|
|
//Manga Id
|
|
$iMangaId = count($this->asMangas);
|
|
$this->asMangas[$iMangaId] = array('short'=>$sShortManga, 'long'=>$sMangaLong);
|
|
$asMangaIds[$sShortManga] = $iMangaId;
|
|
}
|
|
}
|
|
return array('mangas'=>$this->asMangas, 'mangaids'=>$asMangaIds);
|
|
}
|
|
|
|
public function getChapters($sShortManga, $sLongManga)
|
|
{
|
|
//TODO delete
|
|
//return json_decode('{"chapters":[{"short":"1","long":"Rei Kiriyama"},{"short":"2","long":"La Ville Sur Le Fleuve"},{"short":"3","long":"Gatsu No Lion Akari"},{"short":"4","long":"De L\'autre C\u00f4t\u00e9 Du Pont"},{"short":"5","long":"Harunobu"},{"short":"6","long":"Par-Del\u00e0 Le Ciel \u00c9toil\u00e9"},{"short":"7","long":"Hina"},{"short":"8","long":"Comparaison"},{"short":"9","long":"Un Pacte"},{"short":"10","long":"Au Dessus D\'un Rid De Coucou"},{"short":"11","long":"L\'enfant Divin (1)"},{"short":"12","long":"L\'enfant Divin (2)"},{"short":"13","long":"Prochainement Sur Japscan.com"}],"chapterids":{"1":0,"2":1,"3":2,"4":3,"5":4,"6":5,"7":6,"8":7,"9":8,"10":9,"11":10,"12":11,"13":12}}', true);
|
|
|
|
$asChapters = array();
|
|
$oDom = $this->getPageDom($sShortManga);
|
|
$aoOptions = $this->getSelectOptions($oDom, 'chapitres');
|
|
for($iIndex=($aoOptions->length-1);$iIndex>=0;$iIndex--) $aoSortedOptions[] = $aoOptions->item($iIndex);
|
|
foreach($aoSortedOptions as $oOption)
|
|
{
|
|
//Chapter Short Name
|
|
$sChapterPath = $oOption->getAttribute('value');
|
|
if(substr($sChapterPath, -1)=='/') $sChapterPath = substr($sChapterPath, 0, -1);
|
|
$sShortChapter = substr($sChapterPath, strrpos($sChapterPath, '/')+1);
|
|
|
|
//Chapter Long Name
|
|
$sChapterDesc = $oOption->nodeValue;
|
|
$sLongChapter = self::mb_ucwords(trim(str_replace(array('Scan ', $sShortChapter.' ', $sLongManga, ' VF ', '--', ), '', $sChapterDesc)));
|
|
|
|
//Chapter Id
|
|
$iChapterId = count($asChapters);
|
|
$asChapters[$iChapterId] = array('short'=>$sShortChapter, 'long'=>$sLongChapter);
|
|
$asChapterIds[$sShortChapter] = $iChapterId;
|
|
}
|
|
return array('chapters'=>$asChapters, 'chapterids'=>$asChapterIds);
|
|
}
|
|
|
|
public function getPages($sShortManga, $sChapter)
|
|
{
|
|
//TODO delete
|
|
//return json_decode('{"pages":[{"short":"01","long":"Page 01"},{"short":"02","long":"Page 02"},{"short":"03","long":"Page 03"},{"short":"04","long":"Page 04"},{"short":"05","long":"Page 05"},{"short":"06","long":"Page 06"},{"short":"07","long":"Page 07"},{"short":"08","long":"Page 08"},{"short":"09","long":"Page 09"},{"short":"10","long":"Page 10"},{"short":"11","long":"Page 11"},{"short":"12","long":"Page 12"},{"short":"13","long":"Page 13"},{"short":"14","long":"Page 14"},{"short":"15","long":"Page 15"},{"short":"16","long":"Page 16"},{"short":"17","long":"Page 17"},{"short":"18","long":"Page 18"},{"short":"19","long":"Page 19"}],"pageids":{"01":0,"02":1,"03":2,"04":3,"05":4,"06":5,"07":6,"08":7,"09":8,"10":9,"11":10,"12":11,"13":12,"14":13,"15":14,"16":15,"17":16,"18":17,"19":18}}', true);
|
|
|
|
$asPages = array();
|
|
$oDom = $this->getPageDom($sShortManga, $sChapter);
|
|
$aoOptions = $this->getSelectOptions($oDom, 'pages');
|
|
foreach($aoOptions as $oOption)
|
|
{
|
|
//Page Short Name
|
|
$sPagePath = $oOption->getAttribute('value'); //e.g. /lecture-en-ligne/rrr/33/03.html
|
|
$sShortPage = substr($sPagePath, strrpos($sPagePath, '/')+1, -5); // 5 = strlen(.html)
|
|
|
|
//Page Long Name
|
|
$sPageLong = $oOption->nodeValue;
|
|
|
|
//Page Id
|
|
$iPageId = count($asPages);
|
|
$asPages[$iPageId] = array('short'=>$sShortPage, 'long'=>$sPageLong);
|
|
$asPageIds[$sShortPage] = $iPageId;
|
|
}
|
|
return array('pages'=>$asPages, 'pageids'=>$asPageIds);
|
|
}
|
|
|
|
private function getPage($sShortManga, $sChapter, $sPage)
|
|
{
|
|
$oDom = $this->getPageDom($sShortManga, $sChapter, $sPage);
|
|
$aoImages = $oDom->getElementsByTagName('img');
|
|
foreach($aoImages as $oImage)
|
|
{
|
|
if($oImage->getAttribute('id')=='imgscan') break;
|
|
}
|
|
return 'http:'.$oImage->getAttribute('src');
|
|
}
|
|
|
|
public function getPic($sLongManga, $sShortManga, $sShortChapter, $sShortPage, $bDoubleCheck=false)
|
|
{
|
|
//referer: http://www.japscan.com/lecture-en-ligne/samurai-high-school/1/22.html
|
|
//Pic: //cdn.japscan.com/lecture-en-ligne/Samurai%20High%20School/1/22.jpg
|
|
|
|
$sUrl = self::getUrl(array(self::READ_PATH, $sLongManga, $sShortChapter, $sShortPage.'.jpg'), 'cdn', true);
|
|
$sReferer = self::getUrl(array(self::READ_PATH, $sShortManga, $sShortChapter, $sShortPage.'.html'));
|
|
|
|
if($bDoubleCheck) $sUrl = $this->getPage($sShortManga, $sShortChapter, $sShortPage);
|
|
|
|
$oCurl = curl_init();
|
|
curl_setopt($oCurl, CURLOPT_URL, $sUrl);
|
|
curl_setopt($oCurl, CURLOPT_HEADER, false);
|
|
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($oCurl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
|
|
curl_setopt($oCurl, CURLOPT_REFERER, $sReferer);
|
|
$sContent = curl_exec($oCurl);
|
|
$asInfo = curl_getinfo($oCurl);
|
|
curl_close($oCurl);
|
|
|
|
return $asInfo['http_code']!=404?$sContent:$this->getPic($sLongManga, $sShortManga, $sShortChapter, $sShortPage, true);
|
|
}
|
|
|
|
private function getSelectOptions($oDom, $sSelectId)
|
|
{
|
|
$aoSelects = $oDom->getElementsByTagName('select');
|
|
foreach($aoSelects as $oSelect)
|
|
{
|
|
if($oSelect->getAttribute('id')==$sSelectId) break;
|
|
}
|
|
return $oSelect->getElementsByTagName('option');
|
|
}
|
|
|
|
private function getPageDom($sShortManga='', $sChapter='', $sPage='')
|
|
{
|
|
$oDom = new DOMDocument();
|
|
$sHtmlContent = $this->getRemotePage($sShortManga, $sChapter, $sPage);
|
|
@$oDom->loadHTML($sHtmlContent);
|
|
return $oDom->getElementsByTagName('body')->item(0);
|
|
}
|
|
|
|
private function getRemotePage($sShortManga='', $sChapter='', $sPage='')
|
|
{
|
|
$sFileName = 'cache_'.$sShortManga.'_'.$sChapter.'_'.$sPage.'.html';
|
|
$sPage = ($sPage!='')?$sPage.'.html':'';
|
|
$sUrl = self::getUrl(array(self::READ_PATH, $sShortManga, $sChapter, $sPage));
|
|
$sFilePath = self::CACHE_FOLDER.str_replace("&",'\&', str_replace(" ",'\ ', addslashes($sFileName)));
|
|
|
|
if(!file_exists($sFilePath) || date('dmY', filemtime($sFilePath))!=date('dmY')) file_put_contents($sFilePath, file_get_contents($sUrl));
|
|
return file_get_contents($sFilePath);
|
|
}
|
|
|
|
private function getSafeManga($sManga)
|
|
{
|
|
//FIXME use safename
|
|
$asMangasInfo = $this->getMangas();
|
|
foreach($asMangasInfo['mangas'] as $asMangaInfo) {if($asMangaInfo['long']==$sManga) break;}
|
|
|
|
return $asMangaInfo['short'];
|
|
//return $sSafeManga = str_replace(array(' ', '.', '!', '\'', '&'), array('-', '', '', '', 'and'), mb_strtolower($sManga));
|
|
}
|
|
|
|
private static function getUrl($asArgs=array(), $sVirtualHost='www', $bUrlEncode=false)
|
|
{
|
|
if($bUrlEncode) $asArgs = array_map('rawurlencode', $asArgs);
|
|
$sArgs = implode('/', array_filter($asArgs));
|
|
return self::HTTP.$sVirtualHost.'.'.self::JAPSCAN_DOMAIN.'/'.$sArgs;
|
|
}
|
|
|
|
private static function mb_ucwords($sText)
|
|
{
|
|
return mb_convert_case($sText, MB_CASE_TITLE, "UTF-8");
|
|
}
|
|
}
|
|
|
|
$sAction = isset($_GET['a'])?$_GET['a']:'';
|
|
$sType = isset($_GET['type'])?$_GET['type']:'json';
|
|
$sShortManga = isset($_GET['shortmanga'])?$_GET['shortmanga']:'';
|
|
$sLongManga = isset($_GET['longmanga'])?$_GET['longmanga']:'';
|
|
$sChapter = isset($_GET['chapter'])?$_GET['chapter']:'';
|
|
$sPage = isset($_GET['page'])?$_GET['page']:'';
|
|
|
|
$oJapScan = new JapScan();
|
|
if($sAction!='')
|
|
{
|
|
$sResult = '';
|
|
switch($sAction)
|
|
{
|
|
case 'chapters':
|
|
$oData = $oJapScan->getChapters($sShortManga, $sLongManga);
|
|
break;
|
|
case 'pages':
|
|
$oData = $oJapScan->getPages($sShortManga, $sChapter);
|
|
break;
|
|
case 'pic':
|
|
$oData = $oJapScan->getPic($sLongManga, $sShortManga, $sChapter, $sPage);
|
|
break;
|
|
}
|
|
|
|
//Return Json
|
|
switch($sType)
|
|
{
|
|
case 'json':
|
|
header('Content-type: application/json');
|
|
$sResult = json_encode($oData);
|
|
break;
|
|
case 'jpeg':
|
|
header("Content-Type: image/jpeg");
|
|
$sResult = $oData;
|
|
default:
|
|
$sResult = $oData;
|
|
}
|
|
echo $sResult;
|
|
}
|
|
else
|
|
{
|
|
$jVars = $oJapScan->getInitParameters();
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>JapScan</title>
|
|
<script type="text/javascript" src="script/jquery.js"></script>
|
|
<script type="text/javascript">
|
|
function JapScan(asVars)
|
|
{
|
|
self = this;
|
|
$.each(asVars, function(sVarName, asValues){self[sVarName] = asValues;});
|
|
this.sUrl = window.location.pathname;
|
|
this.sFileName = this.sUrl.substring(this.sUrl.lastIndexOf('/')+1);
|
|
|
|
//Refs
|
|
//this.asMangas -- loaded from PHP
|
|
//this.asMangaIds -- loaded from PHP
|
|
this.asChapters = {};
|
|
this.asChapterIds = {};
|
|
this.asPages = {};
|
|
this.asPageIds = {};
|
|
|
|
//Current position
|
|
this.iMangaId = -2;
|
|
this.iChapterId = -2;
|
|
this.iPageId = -2;
|
|
|
|
this.$Progress = {};
|
|
|
|
this.init = function()
|
|
{
|
|
//Keyboard navi
|
|
$(document).keydown(function(e)
|
|
{
|
|
switch(e.keyCode)
|
|
{
|
|
case 37: self.naviPage(-1); break; //left
|
|
case 38: self.naviPage(-1); break; //up
|
|
case 39: self.naviPage(+1); break; //right
|
|
case 40: self.naviPage(+1); break; //down
|
|
}
|
|
});
|
|
|
|
self.$Progress = $('<p>', {'class':'prog'});
|
|
|
|
$(window).bind('hashchange', self.onHash);
|
|
self.onHash();
|
|
};
|
|
|
|
this.get = function(sType, sOutput, iItemid)
|
|
{
|
|
var sUpType = sType.substr(0, 1).toUpperCase()+sType.substr(1);
|
|
var iItemId = (typeof iItemid === 'undefined')?self['i'+sUpType+'Id']:iItemid;
|
|
|
|
//console.log('accessing '+sOutput+' of '+sType+'. context: '+sType+' id = '+self['i'+sUpType+'Id']);
|
|
//console.log('result = '+self['as'+sUpType+'s'][iItemId][sOutput]);
|
|
|
|
return self['as'+sUpType+'s'][iItemId][sOutput];
|
|
};
|
|
|
|
this.commit = function(sType)
|
|
{
|
|
var sUpType = sType.substr(0, 1).toUpperCase()+sType.substr(1);
|
|
var sShortItem = self.asNew['short'+sType];
|
|
var iItemId = 0;
|
|
|
|
switch(sShortItem)
|
|
{
|
|
case '' : iItemId = 0; break;
|
|
case '_last_' : iItemId = self['as'+sUpType+'s'].length - 1; break;
|
|
default : iItemId = self['as'+sUpType+'Ids'][sShortItem]; break;
|
|
}
|
|
var bDelta = (iItemId !== self['i'+sUpType+'Id'] || sShortItem=='');
|
|
self['i'+sUpType+'Id'] = iItemId;
|
|
|
|
//console.log('setting bDelta = '+bDelta+' and self.i'+sUpType+'Id = '+iItemId+' (from short = '+sShortItem+')');
|
|
return bDelta;
|
|
};
|
|
|
|
this.getInfo = function(sAction, fOnSuccess, asVars, sType)
|
|
{
|
|
asVars = asVars || {};
|
|
sType = sType || 'json';
|
|
asVars.a = sAction;
|
|
$.ajax(
|
|
{
|
|
url: self.sFileName,
|
|
data: asVars,
|
|
dataType: sType
|
|
})
|
|
.done(function(oResult)
|
|
{
|
|
fOnSuccess(oResult);
|
|
});
|
|
};
|
|
|
|
this.getUrl = function(sAction, oVars)
|
|
{
|
|
oVars = oVars || {};
|
|
sVars = '';
|
|
$.each(oVars, function(sParam, sValue){sVars += '&'+sParam+'='+sValue;});
|
|
return window.location.protocol+'//'+window.location.host+window.location.pathname+'?a='+sAction+sVars;
|
|
};
|
|
|
|
this.onHash = function()
|
|
{
|
|
//Parse hash
|
|
var asHash = self.hash();
|
|
|
|
self.oMangaLoader = new $.Deferred();
|
|
self.oChapterLoader = new $.Deferred();
|
|
self.oPageLoader = new $.Deferred();
|
|
|
|
if(asHash.shortmanga != '')
|
|
{
|
|
self.asNew = asHash;
|
|
self.oMangaLoader.done(function(){ var bDelta = self.commit('manga'); self.loadChapters(bDelta);});
|
|
self.oChapterLoader.done(function(){var bDelta = self.commit('chapter'); self.loadPages(bDelta);});
|
|
self.oPageLoader.done(function(){ var bDelta = self.commit('page'); self.displayPage(bDelta);});
|
|
}
|
|
self.loadMangas();
|
|
};
|
|
|
|
this.hash = function(asHash)
|
|
{
|
|
var sSplitChar = ':';
|
|
if(!asHash)
|
|
{
|
|
//Parse hash
|
|
var sHash = window.location.hash.slice(1);
|
|
var asHash = sHash.split(sSplitChar);
|
|
|
|
var sShortManga = (typeof asHash[0] != 'undefined')?asHash[0]:'';
|
|
var sShortChapter = (typeof asHash[1] != 'undefined')?asHash[1]:'';
|
|
var sShortPage = (typeof asHash[2] != 'undefined')?asHash[2]:'';
|
|
|
|
return {shortmanga:sShortManga, shortchapter:sShortChapter, shortpage:sShortPage};
|
|
}
|
|
else window.location.hash = asHash.join(sSplitChar);
|
|
};
|
|
|
|
this.loadMangas = function()
|
|
{
|
|
//Display all mangas
|
|
var $Mangas = $('#mangas').find('ul');
|
|
if($Mangas.children('li').length == 0)
|
|
{
|
|
var sShortManga, sLongManga;
|
|
$.each(self.asMangas, function(iMangaId, asMangaInfo)
|
|
{
|
|
$Mangas.append($('<li>').append($('<a>', {id:'m_'+asMangaInfo['short'], 'class':'manga', href:'#'+asMangaInfo['short']}).text(asMangaInfo['long'])));
|
|
});
|
|
}
|
|
|
|
self.oMangaLoader.resolve();
|
|
};
|
|
|
|
this.loadChapters = function(bMangaDelta)
|
|
{
|
|
if(bMangaDelta)
|
|
{
|
|
self.getInfo('chapters', function(asInfo)
|
|
{
|
|
self.asChapters = [];
|
|
self.asChapters = asInfo.chapters;
|
|
self.asChapterIds = {};
|
|
self.asChapterIds = asInfo.chapterids;
|
|
|
|
$Chapter = $('#chapters').empty();
|
|
for(var i in self.asChapters)
|
|
{
|
|
sShortChapter = self.asChapters[i]['short'];
|
|
sLongChapter = self.asChapters[i]['long'];
|
|
|
|
$('<div>', {id:'c_'+sShortChapter, 'class':'chapter'})
|
|
.data('chapter', sShortChapter)
|
|
.append($('<p class="id">').text(sShortChapter))
|
|
.append($('<p class="name">').text(sLongChapter))
|
|
.click(function(){self.hash([self.get('manga', 'short'), $(this).data('chapter')]);})
|
|
.appendTo($Chapter);
|
|
}
|
|
self.oChapterLoader.resolve();
|
|
}
|
|
, {shortmanga:self.get('manga', 'short'), longmanga:self.get('manga', 'long')});
|
|
}
|
|
else self.oChapterLoader.resolve();
|
|
};
|
|
|
|
this.loadPages = function(bChapterDelta)
|
|
{
|
|
if(bChapterDelta)
|
|
{
|
|
self.getInfo('pages', function(asInfo)
|
|
{
|
|
self.asPages = asInfo.pages;
|
|
self.asPageIds = asInfo.pageids;
|
|
self.oPageLoader.resolve();
|
|
}
|
|
, {shortmanga:self.get('manga', 'short'), chapter:self.get('chapter', 'short')});
|
|
}
|
|
else self.oPageLoader.resolve();
|
|
};
|
|
|
|
this.naviPage = function(iDirection)
|
|
{
|
|
var iMangaId = self.iMangaId;
|
|
var iChapterId = self.iChapterId;
|
|
var iPageId = self.iPageId;
|
|
if((self.iPageId + iDirection < self.asPages.length) && (self.iPageId + iDirection >= 0)) //next/previous page
|
|
{
|
|
iPageId += iDirection;
|
|
self.hash([self.get('manga', 'short'), self.get('chapter', 'short'), self.get('page', 'short', iPageId)]);
|
|
}
|
|
else if((self.iChapterId + iDirection < self.asChapters.length) && (self.iChapterId + iDirection >= 0)) //next/previous chapter
|
|
{
|
|
iChapterId += iDirection;
|
|
if(self.iPageId + iDirection == self.asPages.length) self.hash([self.get('manga', 'short'), self.get('chapter', 'short', iChapterId)]);
|
|
else
|
|
{
|
|
sShortPage = '_last_';
|
|
self.hash([self.get('manga', 'short'), self.get('chapter', 'short', iChapterId), sShortPage]);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.displayPage = function()
|
|
{
|
|
var sUrl = self.getUrl('pic', { longmanga: self.get('manga', 'long'),
|
|
shortmanga: self.get('manga', 'short'),
|
|
chapter: self.get('chapter', 'short'),
|
|
page: self.get('page', 'short'),
|
|
type: 'jpeg'});
|
|
|
|
//console.log('loading image : '+sUrl);
|
|
$('#pic').attr('src', sUrl);
|
|
|
|
//Updating progress status
|
|
$('.chapter').add('.manga').removeClass('active');
|
|
var $Manga = $('#m_'+self.get('manga', 'short')).focus().addClass('active');
|
|
var $Chapter = $('#c_'+self.get('chapter', 'short')).focus().addClass('active');
|
|
self.$Progress
|
|
.remove()
|
|
.text('Page '+(self.iPageId + 1)+' sur '+(self.asPages.length))
|
|
.appendTo($Chapter);
|
|
|
|
//Preloading next images
|
|
for(var i=1;i<3;i++)
|
|
{
|
|
if(self.iPageId + i < self.asPages.length)
|
|
{
|
|
var oImage = new Image();
|
|
oImage.src = self.getUrl('pic', { longmanga: self.get('manga', 'long'),
|
|
shortmanga: self.get('manga', 'short'),
|
|
chapter: self.get('chapter', 'short'),
|
|
page: self.get('page', 'short', self.iPageId + i),
|
|
type: 'jpeg'});
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
var asParams = <?php echo $jVars; ?>;
|
|
var oJapScan = new JapScan(asParams);
|
|
$(document).ready(oJapScan.init);
|
|
</script>
|
|
<style type="text/css">
|
|
|
|
/* Generals */
|
|
a {color:black; text-decoration:none;}
|
|
a:visited {color:black; text-decoration:none;}
|
|
p {margin:0; padding:0;}
|
|
img {margin:0; padding:0; border:none;}
|
|
ul {list-style:none; margin:0; padding-left:0;}
|
|
|
|
/* Main Parts */
|
|
body {margin:0; padding:0; font-family: "Open Sans","Droid Sans",Helvetica,Arial,sans-serif; font-size:0.8em;}
|
|
#container {width:100vw; height:100vh; box-sizing:border-box;}
|
|
#mangas {width:20vw; height:100vh; float:left; overflow:auto;}
|
|
#chapters {width:12vw; height:100vh; float:left; overflow:auto;}
|
|
#scan {width:68vw; height:100vh; float:right; overflow:hidden; text-align:center; background:grey 50% 50% no-repeat;}
|
|
|
|
/* Mangas */
|
|
#mangas .manga {display: block; margin:0.5vw; padding:0.5vw; background:#4F5B93; color:white; border-radius:0.5vw;}
|
|
#mangas .manga:hover {background:#8892BF;}
|
|
#mangas .manga.active {background:#8892BF; color:black;}
|
|
#mangas .manga:visited {font-weight:bold;}
|
|
|
|
/* Chapters */
|
|
#chapters .chapter {width:9vw; height:9vw; margin:0.5vw; padding:0.5vw; background:#4F5B93; color:white; border-radius:1vw; text-align: center; cursor:pointer;}
|
|
#chapters .chapter:hover {background:#8892BF;}
|
|
#chapters .chapter .id {font-size:3em;}
|
|
#chapters .chapter.active {background:#8892BF; color:black; height:8vw;}
|
|
#chapters .chapter.active .prog {font-style:italic;}
|
|
#chapters .chapter.active .id {margin-top:0%;}
|
|
|
|
/* Scan */
|
|
#pic {max-width:65vw; max-height:100vh;}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div id="mangas"><ul></ul></div>
|
|
<div id="chapters"></div>
|
|
<div id="scan"><img id="pic" alt="Pick a manga" /></div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
<?php
|
|
}
|
|
?>
|