├── .gitignore ├── README.md ├── application ├── config.php ├── controllers │ ├── Admin.php │ ├── Cache.php │ ├── Dashboard.php │ ├── Help.php │ ├── Home.php │ ├── Info.php │ ├── Movies.php │ ├── Series.php │ └── Watch.php ├── includes │ ├── Cache.php │ ├── MediaModel.php │ ├── Password.php │ ├── TvDb │ │ ├── Actor.php │ │ ├── Banner.php │ │ ├── Client.php │ │ ├── CurlException.php │ │ ├── Episode.php │ │ ├── Exception.php │ │ ├── Http │ │ │ ├── Cache │ │ │ │ ├── Cache.php │ │ │ │ └── FilesystemCache.php │ │ │ ├── CacheClient.php │ │ │ ├── CurlClient.php │ │ │ └── HttpClient.php │ │ ├── Serie.php │ │ └── XmlException.php │ ├── VideoStream.php │ └── providers │ │ ├── movie │ │ └── CouchPotato.php │ │ └── show │ │ └── SickRage.php ├── languages │ └── lang.en.php ├── models │ ├── accesslog_m.php │ ├── langs_m.php │ ├── menu_m.php │ └── user_m.php └── views │ ├── _layouts │ └── default.php │ ├── _partials │ ├── flashmessage.php │ ├── footer.php │ ├── headermeta.php │ └── navbar.php │ ├── admin │ ├── adduser.php │ └── index.php │ ├── dashboard │ └── index.php │ ├── help │ ├── android.php │ ├── ios.php │ ├── kodi.php │ ├── mac.php │ ├── synology.php │ └── windows.php │ ├── home │ └── login.php │ ├── info │ └── movie.php │ └── media │ ├── movies.add.php │ ├── movies.busy.php │ ├── movies.php │ ├── series.add.php │ ├── series.episodes.php │ ├── series.php │ └── watch.php ├── cache └── placeholder ├── css ├── bootstrap.css ├── bootstrap.min.css ├── custom.css ├── font │ ├── vjs.eot │ ├── vjs.svg │ ├── vjs.ttf │ └── vjs.woff ├── owl.carousel.css └── video-js.min.css ├── favicon.ico ├── fonts ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.svg ├── glyphicons-halflings-regular.ttf ├── glyphicons-halflings-regular.woff └── glyphicons-halflings-regular.woff2 ├── img ├── .db_password.php ├── actor.png ├── flags │ ├── .DS_Store │ ├── ad.png │ ├── ae.png │ ├── af.png │ ├── ag.png │ ├── ai.png │ ├── al.png │ ├── am.png │ ├── an.png │ ├── ao.png │ ├── ar.png │ ├── as.png │ ├── at.png │ ├── au.png │ ├── aw.png │ ├── ax.png │ ├── az.png │ ├── ba.png │ ├── bb.png │ ├── bd.png │ ├── be.png │ ├── bf.png │ ├── bg.png │ ├── bh.png │ ├── bi.png │ ├── bj.png │ ├── bm.png │ ├── bn.png │ ├── bo.png │ ├── br.png │ ├── bs.png │ ├── bt.png │ ├── bv.png │ ├── bw.png │ ├── by.png │ ├── bz.png │ ├── ca.png │ ├── catalonia.png │ ├── cc.png │ ├── cd.png │ ├── cf.png │ ├── cg.png │ ├── ch.png │ ├── ci.png │ ├── ck.png │ ├── cl.png │ ├── cm.png │ ├── cn.png │ ├── co.png │ ├── cr.png │ ├── cs.png │ ├── cu.png │ ├── cv.png │ ├── cx.png │ ├── cy.png │ ├── cz.png │ ├── de.png │ ├── dj.png │ ├── dk.png │ ├── dm.png │ ├── do.png │ ├── dz.png │ ├── ec.png │ ├── ee.png │ ├── eg.png │ ├── eh.png │ ├── en.png │ ├── england.png │ ├── er.png │ ├── es.png │ ├── et.png │ ├── europeanunion.png │ ├── fam.png │ ├── fi.png │ ├── fj.png │ ├── fk.png │ ├── fm.png │ ├── fo.png │ ├── fr.png │ ├── ga.png │ ├── gb.png │ ├── gd.png │ ├── ge.png │ ├── gf.png │ ├── gh.png │ ├── gi.png │ ├── gl.png │ ├── gm.png │ ├── gn.png │ ├── gp.png │ ├── gq.png │ ├── gr.png │ ├── gs.png │ ├── gt.png │ ├── gu.png │ ├── gw.png │ ├── gy.png │ ├── hk.png │ ├── hm.png │ ├── hn.png │ ├── hr.png │ ├── ht.png │ ├── hu.png │ ├── id.png │ ├── ie.png │ ├── il.png │ ├── in.png │ ├── io.png │ ├── iq.png │ ├── ir.png │ ├── is.png │ ├── it.png │ ├── jm.png │ ├── jo.png │ ├── jp.png │ ├── ke.png │ ├── kg.png │ ├── kh.png │ ├── ki.png │ ├── km.png │ ├── kn.png │ ├── kp.png │ ├── kr.png │ ├── kw.png │ ├── ky.png │ ├── kz.png │ ├── la.png │ ├── lb.png │ ├── lc.png │ ├── li.png │ ├── lk.png │ ├── lr.png │ ├── ls.png │ ├── lt.png │ ├── lu.png │ ├── lv.png │ ├── ly.png │ ├── ma.png │ ├── mc.png │ ├── md.png │ ├── me.png │ ├── mg.png │ ├── mh.png │ ├── mk.png │ ├── ml.png │ ├── mm.png │ ├── mn.png │ ├── mo.png │ ├── mp.png │ ├── mq.png │ ├── mr.png │ ├── ms.png │ ├── mt.png │ ├── mu.png │ ├── mv.png │ ├── mw.png │ ├── mx.png │ ├── my.png │ ├── mz.png │ ├── na.png │ ├── nc.png │ ├── ne.png │ ├── nf.png │ ├── ng.png │ ├── ni.png │ ├── nl.png │ ├── no.png │ ├── np.png │ ├── nr.png │ ├── nu.png │ ├── nz.png │ ├── om.png │ ├── pa.png │ ├── pe.png │ ├── pf.png │ ├── pg.png │ ├── ph.png │ ├── pk.png │ ├── pl.png │ ├── pm.png │ ├── pn.png │ ├── pr.png │ ├── ps.png │ ├── pt.png │ ├── pw.png │ ├── py.png │ ├── qa.png │ ├── re.png │ ├── ro.png │ ├── rs.png │ ├── ru.png │ ├── rw.png │ ├── sa.png │ ├── sb.png │ ├── sc.png │ ├── scotland.png │ ├── sd.png │ ├── se.png │ ├── sg.png │ ├── sh.png │ ├── si.png │ ├── sj.png │ ├── sk.png │ ├── sl.png │ ├── sm.png │ ├── sn.png │ ├── so.png │ ├── sr.png │ ├── st.png │ ├── sv.png │ ├── sy.png │ ├── sz.png │ ├── tc.png │ ├── td.png │ ├── tf.png │ ├── tg.png │ ├── th.png │ ├── tj.png │ ├── tk.png │ ├── tl.png │ ├── tm.png │ ├── tn.png │ ├── to.png │ ├── tr.png │ ├── tt.png │ ├── tv.png │ ├── tw.png │ ├── tz.png │ ├── ua.png │ ├── ug.png │ ├── um.png │ ├── us.png │ ├── uy.png │ ├── uz.png │ ├── va.png │ ├── vc.png │ ├── ve.png │ ├── vg.png │ ├── vi.png │ ├── vn.png │ ├── vu.png │ ├── wales.png │ ├── wf.png │ ├── ws.png │ ├── ye.png │ ├── yt.png │ ├── za.png │ ├── zm.png │ └── zw.png ├── glyphicons-halflings-white.png ├── glyphicons-halflings.png ├── help │ ├── synology-context-icon.png │ ├── synology-file-icon.png │ └── synology_webdav.png └── notfound.png ├── index.php ├── js ├── bootstrap.js ├── bootstrap.min.js ├── jquery.min.js ├── npm.js ├── owl.carousel.min.js ├── unveil.js ├── video-js.swf ├── video.js └── videojs.vlc.min.js ├── scripts ├── addUser.sh └── delUser.sh ├── setup ├── db.sql ├── setup.sh └── setupDownloaders.sh └── system ├── Controller.php ├── Core_controller.php ├── Core_db.php ├── DB.php ├── Form.php ├── Load.php ├── Template.php └── URL.php /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | !.cache/placeholder 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gunther - NO LONGER MAINTAINED 2 | ~ Easy web frontend for your media on a debian VPS. 3 | 4 | 5 | Gunther can be used as a easy-to-use web frontend for your personal media. You can stream your media, aswell as automatically request new media to programs controlled by API. (think CouchPotato, Sickbeard, ...) 6 | 7 | The idea is to have a central place for the less tech-savvy user. 8 | If you want to contribute, application/ is the folder you need. 9 | 10 | Note: This can install downloaders for you. [Use the setupDownloaders.sh script for that.](https://github.com/HazCod/Gunther/blob/master/setup/setupDownloaders.sh). 11 | 12 | # Features 13 | - Works with the high performance web server nginx 14 | - Uses the high performant Webdav protocol for sharing; almost every client supports this 15 | - No running database required; uses SQlite 16 | - Caches posters and actor images; a little slower, but at least everything is over HTTPS 17 | - Fetches all media info directly from providers. 18 | 19 | 20 | # Installation 21 | 0. Start with a fresh debian installation and be logged in as root. 22 | 1. Download the setup file to your VPS. 23 | ``` 24 | cd /tmp && wget --no-check-certificate https://raw.githubusercontent.com/HazCod/Gunther/master/setup/setup.sh 25 | ``` 26 | 2. Set your desired admin password in the script (default is `Gunth3r!`) and run the [setup script](setup/setup.sh) to setup everything on your Debian host. 27 | ``` 28 | nano setup.sh 29 | chmod +x setup.sh 30 | ./setup.sh 31 | ``` 32 | 3. Set your API keys in [config.php](/application/config.php). 33 | 4. Setup a daily cron job to keep the site snappy. (not mandatory) 34 | `01 0 * * * www-data wget --no-check-certificate -q http://localhost/cache &>/dev/null` 35 | 5. Login with admin and the password. 36 | 37 | # TODO 38 | [See issue tracker.](https://github.com/HazCod/Gunther/issues) 39 | 40 | # Screenshots 41 | ![Gunther login screenshot](https://i.imgur.com/RWgQcBR.png "Login screen") 42 | 43 | ![Gunther dashboard](https://i.imgur.com/UcSAg08.png "Dashboard") 44 | 45 | ![Movie info](https://i.imgur.com/0QovMZD.png "Movie info page") 46 | 47 | ![Series info](http://i.imgur.com/JxIlfeC.png "Series info page") 48 | 49 | ![Gunther stream screenshot](https://i.imgur.com/ddidCuk.jpg "Streaming screen") 50 | 51 | ![Gunther admin screenshot](https://i.imgur.com/87bhWjv.jpg "Admin interface") 52 | 53 | 54 | # Project dependencies 55 | (HTML/PHP/CSS/SHELL/JS), VideoJS, Bootswatch Flatly, Bootstrap, IMDB, TheTVDB, SQLite 56 | -------------------------------------------------------------------------------- /application/config.php: -------------------------------------------------------------------------------- 1 | '/mnt/media/', 7 | 8 | 'TVDB_URL' => 'http://thetvdb.com', 9 | 10 | 'cache_location' => 'cache/', #cache directory for TheTvDB/IMDB 11 | 12 | 'movie_provider' => 'CouchPotato', #Cache time-to-live in seconds, default 1 day 13 | 'movie_settings' => array( 14 | 'api' => '1e501582e6944bd388c1b479720d2f2f', 15 | 'location' => 'http://localhost:5050/', 16 | 'lang' => 'en' 17 | ), 18 | 'serie_provider' => '', 19 | 'serie_settings' => array( 20 | 'api' => '', 21 | 'location' => 'http://localhost:8083/', 22 | 'lang' => 'end' 23 | ), 24 | 25 | 'DEFAULT_LANG' => 'en', #default language 26 | 27 | 'REPORT_BAD_LOGIN' => true, #set to false if you don't want to hide failed login attempts 28 | 29 | 'DB_LOC' => '/etc/nginx/gunther.db', 30 | 'AUTH_DIGEST_FILE' => '/etc/nginx/webdav.auth', 31 | 'LOG' => '/var/log/nginx/error.log', 32 | 'LAST_LOG' => 10, #get last 10 logs 33 | 34 | 'TVDB_API' => '919407757B63D836', #Your TheTvDB API key 35 | ); 36 | -------------------------------------------------------------------------------- /application/controllers/Cache.php: -------------------------------------------------------------------------------- 1 | mediamodel->fillCache(); 25 | echo 'Caches flushed.'; 26 | return true; 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /application/controllers/Dashboard.php: -------------------------------------------------------------------------------- 1 | template->setPartial('navbar') 11 | ->setPartial('headermeta') 12 | ->setPartial('footer') 13 | ->setPartial('flashmessage'); 14 | 15 | $this->template->setPagetitle($this->lang['dashboard'] . ' - ' . $this->lang['title']); 16 | } 17 | 18 | public function index() 19 | { 20 | if ($this->checkPrivilege() == true){ 21 | if ($this->mediamodel->movieProvider() != false) 22 | $this->template->movies = $this->mediamodel->movieProvider()->getMovies('done', 10); 23 | if ($this->mediamodel->showProvider() != false) 24 | $this->template->episodes = $this->mediamodel->showProvider()->getLatestEpisodes('downloaded', 10); 25 | $this->template->render('dashboard/index'); 26 | } 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /application/controllers/Help.php: -------------------------------------------------------------------------------- 1 | template->setPartial('navbar') 11 | ->setPartial('headermeta') 12 | ->setPartial('footer') 13 | ->setPartial('flashmessage'); 14 | } 15 | 16 | public function index() 17 | { 18 | $this->redirect('dashboard/index'); 19 | } 20 | 21 | public function windows(){ 22 | $this->template->setPagetitle($this->lang['htwindows'] . ' - ' . $this->lang['title']); 23 | $this->template->render('help/windows'); 24 | } 25 | 26 | public function mac(){ 27 | $this->template->setPagetitle($this->lang['htmac'] . ' - ' . $this->lang['title']); 28 | $this->template->render('help/mac'); 29 | } 30 | 31 | public function synology(){ 32 | $this->template->setPagetitle($this->lang['htsynology'] . ' - ' . $this->lang['title']); 33 | $this->template->render('help/synology'); 34 | } 35 | 36 | public function kodi(){ 37 | $this->template->setPagetitle($this->lang['htkodi'] . ' - ' . $this->lang['title']); 38 | $this->template->render('help/kodi'); 39 | } 40 | 41 | public function android(){ 42 | $this->template->setPagetitle($this->lang['htandroid'] . ' - ' . $this->lang['title']); 43 | $this->template->render('help/android'); 44 | } 45 | 46 | public function ios(){ 47 | $this->template->setPagetitle($this->lang['htios'] . ' - ' . $this->lang['title']); 48 | $this->template->render('help/ios'); 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /application/controllers/Home.php: -------------------------------------------------------------------------------- 1 | template->setPartial('navbar') 10 | ->setPartial('headermeta') 11 | ->setPartial('footer') 12 | ->setPartial('flashmessage'); 13 | 14 | //set page title 15 | $this->template->setPagetitle($this->lang['title']); 16 | } 17 | 18 | public function index() 19 | { 20 | if (isset($_SESSION['user'])) { 21 | $this->redirect('dashboard'); 22 | } else { 23 | $this->template->render('home/login'); 24 | } 25 | } 26 | 27 | public function login() 28 | { 29 | $formdata = $this->form->getPost(); 30 | $this->form->validateLength('username', 4); 31 | $this->form->validateLength('password', 5); 32 | 33 | if ($this->form->isFormValid()) { 34 | if ($this->user_m->isValid(strtolower($formdata->username), $formdata->password)){ 35 | $this->user = $this->user_m->getUserByLogin(strtolower($formdata->username)); 36 | $_SESSION['user'] = $this->user->id; 37 | $this->redirect('dashboard'); 38 | } else { 39 | $this->template->formdata = $formdata; 40 | $this->setCurrentFlashmessage($this->lang['wronglogin'], 'danger'); 41 | $this->template->render('home/login'); 42 | } 43 | } else { 44 | $this->template->formdata = $formdata; 45 | $this->setCurrentFlashmessage($this->lang['invalidlogin'], 'danger'); 46 | $this->template->render('home/login'); 47 | } 48 | } 49 | 50 | public function logout() 51 | { 52 | session_unset(); 53 | $this->setFlashmessage($this->lang['loggedout']); 54 | $this->redirect("home"); 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /application/controllers/Info.php: -------------------------------------------------------------------------------- 1 | template->setPartial('navbar') 11 | ->setPartial('headermeta') 12 | ->setPartial('footer') 13 | ->setPartial('flashmessage'); 14 | 15 | //set page title 16 | 17 | } 18 | 19 | public function movie($id){ 20 | $this->template->movie = $this->mediamodel->movieProvider()->getMovie($id); 21 | if ($this->template->movie){ 22 | $this->template->setPagetitle($this->template->movie->name . ' - ' . $this->lang['title']); 23 | $this->template->render('info/movie'); 24 | } else { 25 | $this->setFlashmessage($this->lang['movienotfound'], 'danger'); 26 | $this->redirect('movies/index'); 27 | } 28 | } 29 | 30 | public function episode($id){ 31 | 32 | } 33 | 34 | public function index(){ 35 | $this->redirect('dashboard/index'); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /application/controllers/Movies.php: -------------------------------------------------------------------------------- 1 | template->setPartial('navbar') 11 | ->setPartial('headermeta') 12 | ->setPartial('footer') 13 | ->setPartial('flashmessage'); 14 | 15 | //set page title 16 | $this->template->setPagetitle($this->lang['movies'] . ' - ' . $this->lang['title']); 17 | } 18 | 19 | public function busy(){ 20 | $this->template->setPagetitle($this->lang['inactivemov'] . ' - ' . $this->lang['title']); 21 | $this->template->movies = $this->mediamodel->movieProvider()->getMovies('active'); 22 | $this->template->render('media/movies.busy'); 23 | } 24 | 25 | private function isMovieInList($list, $id){ 26 | $result = false; 27 | if ($list && $id){ 28 | foreach ($list as $movie){ 29 | if (strcmp($movie->id, $id) == 0){ 30 | $result = true; 31 | } 32 | } 33 | } 34 | return $result; 35 | } 36 | 37 | public function search(){ 38 | $formdata = $this->form->getPost(); 39 | if ($formdata){ 40 | $this->template->searchterm = $formdata->title; 41 | $allmovies = $this->mediamodel->movieProvider()->getMovies(false); 42 | $found_movies = array(); 43 | foreach ($this->mediamodel->findMedia('movie', $formdata->title) as $id => $found_movie){ 44 | if ($this->isMovieInList($allmovies, $found_movie->imdbID) == false){ 45 | array_push($found_movies, $found_movie); 46 | } 47 | } 48 | $this->template->results = $found_movies; 49 | $this->template->setPagetitle($this->lang['search'] . ': ' . $formdata->title . ' - Gunther'); 50 | $this->template->render('media/movies.add'); 51 | } else { 52 | $this->redirect('movies/add'); 53 | } 54 | } 55 | 56 | public function add($id=false){ 57 | $this->template->setPagetitle($this->lang['addmovie'] . ' - ' . $this->lang['title']); 58 | if ($id){ 59 | if ($this->mediamodel->movieProvider()->addMovie($id) == true){ 60 | $this->mediamodel->flushMovieCache(); 61 | $this->setflashmessage($this->lang['movieadded'], 'info'); 62 | } else { 63 | $this->setflashmessage($this->lang['movadderr'], 'danger'); 64 | } 65 | $this->redirect('movies/index'); 66 | } else { 67 | $this->template->render('media/movies.add'); 68 | } 69 | } 70 | 71 | public function index(){ 72 | if ($_POST){ 73 | $formdata = $this->form->getPost(); 74 | $this->template->searchterm = $formdata->search; 75 | $this->template->movies = $this->mediamodel->movieProvider()->searchMovie($formdata->search); 76 | } else { 77 | $this->template->movies = $this->mediamodel->movieProvider()->getMovies(); 78 | } 79 | $this->template->render('media/movies'); 80 | } 81 | 82 | 83 | } -------------------------------------------------------------------------------- /application/controllers/Series.php: -------------------------------------------------------------------------------- 1 | template->setPartial('navbar') 11 | ->setPartial('headermeta') 12 | ->setPartial('footer') 13 | ->setPartial('flashmessage'); 14 | 15 | //set page title 16 | $this->template->setPagetitle($this->lang['series'] . ' - ' . $this->lang['title']); 17 | } 18 | 19 | private function isShowInList($list, $id){ 20 | foreach ($list as $item){ 21 | if (strcmp((string) $item->id, $id) == 0){ 22 | return true; 23 | } 24 | } 25 | return false; 26 | } 27 | 28 | public function search(){ 29 | $formdata = $this->form->getPost(); 30 | $this->template->searchterm = $formdata->title; 31 | $existing = $this->mediamodel->showProvider()->getShows(); 32 | $arr=array(); 33 | foreach ($this->mediamodel->showProvider()->searchShow($formdata->title) as $result){ 34 | if ($this->isShowInList($existing, $result->id) == false){ 35 | array_push($arr, $result); 36 | } else { 37 | $this->setCurrentflashmessage($this->lang['hiddenshows'], 'info'); 38 | } 39 | } 40 | $this->template->results = $arr; 41 | $this->template->setPagetitle('Search: ' . $formdata->title . ' - Gunther'); 42 | $this->template->render('media/series.add'); 43 | } 44 | 45 | public function add($id=false){ 46 | $this->template->setPagetitle($this->lang['addshow'] . ' - ' . $this->lang['title']); 47 | if ($id){ 48 | if ($this->mediamodel->showProvider()->addShow($id)){ 49 | $this->setflashmessage($this->lang['showadded'], 'info'); 50 | } else { 51 | $this->setflashmessage($this->lang['showadderr'], 'danger'); 52 | } 53 | $this->mediamodel->flushShowCache(); 54 | $this->redirect('series/index'); 55 | } else { 56 | $this->template->render('media/series.add'); 57 | } 58 | } 59 | 60 | public function episodes($id=false){ 61 | if ($id != false) { 62 | $this->template->show = $this->mediamodel->showProvider()->getShow($id); 63 | $this->template->setPagetitle($this->template->show->name . ' - ' . $this->lang['title']); 64 | $this->template->render('media/series.episodes'); 65 | } 66 | } 67 | 68 | public function index(){ 69 | if ($_POST){ 70 | $formdata = $this->form->getPost(); 71 | $this->template->searchterm = $formdata->search; 72 | $this->template->shows = $this->mediamodel->showProvider()->searchShow($formdata->search); 73 | } else { 74 | $this->template->shows = $this->mediamodel->showProvider()->getShows(); 75 | } 76 | $this->template->render('media/series'); 77 | } 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /application/includes/Cache.php: -------------------------------------------------------------------------------- 1 | location = $cache_location; 24 | 25 | $this->tvdb = new Client('https://thetvdb.com/', '919407757B63D836'); 26 | $cache = new FilesystemCache($this->location); 27 | $httpClient = new CacheClient($cache, 604800); 28 | $this->tvdb->setHttpClient($httpClient); 29 | 30 | } 31 | 32 | private function download($url, $path){ 33 | $ch = curl_init($url); 34 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 35 | 36 | $data = curl_exec($ch); 37 | 38 | curl_close($ch); 39 | 40 | file_put_contents($path, $data); 41 | } 42 | 43 | public function getImage($url, $force=false) { 44 | if (!file_exists($this->location . 'img/')) { 45 | mkdir($this->location . 'img/', 0777, true); 46 | } 47 | $cacheFile = $this->location . 'img/' . sha1($url) . '.' . pathinfo($url, PATHINFO_EXTENSION); 48 | if (file_exists($cacheFile) and $force == false){ 49 | return '/' . $cacheFile; 50 | } else { 51 | $this->download($url, $cacheFile); 52 | if (file_exists($cacheFile)){ 53 | return '/' . $cacheFile; 54 | } else { 55 | error_log('Could not fetch ' . $url . ' to ' . $cacheFile); 56 | return false; 57 | } 58 | } 59 | } 60 | 61 | public function getJson($url, $ttl=false) { 62 | $cacheFile = $this->location . md5($url); 63 | 64 | if (file_exists($cacheFile) and $ttl != false) { 65 | $fh = fopen($cacheFile, 'r'); 66 | $cacheTime = trim(fgets($fh)); 67 | 68 | if ($cacheTime > strtotime($ttl)) { 69 | return json_decode(fread($fh, filesize($cacheFile))); 70 | } else { 71 | fclose($fh); 72 | unlink($cacheFile); 73 | } 74 | } 75 | 76 | $data = file_get_contents($url); 77 | if ($data){ 78 | $json = json_decode($data); 79 | $fh = fopen($cacheFile, 'w'); 80 | if ($fh == false){ 81 | error_log("!ERROR: Could not write to cache.. check your permissions! (" . $cacheFile . ")"); 82 | } else { 83 | fwrite($fh, time() . "\n"); 84 | fwrite($fh, $data); 85 | fclose($fh); 86 | } 87 | return $json; 88 | } else { 89 | error_log('Could not fetch ' . $url); 90 | return false; 91 | } 92 | } 93 | 94 | public function storeObject($id, $json){ 95 | $cacheFile = $this->location . 'objects/' . $id; 96 | return (file_put_contents($cacheFile, $json) == 0); 97 | } 98 | 99 | public function getObject($id){ 100 | $result = false; 101 | $cacheFile = $this->location . 'objects/' . $id; 102 | if (!file_exists($this->location . 'objects/')) { 103 | mkdir($this->location . 'objects/', 0777, true); 104 | } 105 | if (file_exists($cacheFile)){ 106 | $result = file_get_contents($cacheFile); 107 | } 108 | return $result; 109 | } 110 | } 111 | ?> -------------------------------------------------------------------------------- /application/includes/TvDb/Actor.php: -------------------------------------------------------------------------------- 1 | 10 | **/ 11 | 12 | class Actor 13 | { 14 | 15 | /** 16 | * @var int 17 | */ 18 | public $id; 19 | 20 | /** 21 | * @var string 22 | */ 23 | public $image; 24 | 25 | /** 26 | * @var string 27 | */ 28 | public $name; 29 | 30 | /** 31 | * @var string 32 | */ 33 | public $role; 34 | 35 | /** 36 | * @var int 37 | */ 38 | public $sortOrder; 39 | 40 | /** 41 | * Constructor 42 | * 43 | * @access public 44 | * @param \SimpleXMLElement $data A simplexml element created from thetvdb.com's xml data for the actor 45 | * @return \Moinax\TvDb\Actor 46 | */ 47 | public function __construct($data) 48 | { 49 | $this->id = (int)$data->id; 50 | $this->image = (string)$data->Image; 51 | $this->name = (string)$data->Name; 52 | $this->role = (string)$data->Role; 53 | $this->sortOrder = (int)$data->SortOrder; 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /application/includes/TvDb/Banner.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class Banner 12 | { 13 | 14 | /** 15 | * @var int 16 | */ 17 | public $id; 18 | 19 | /** 20 | * @var string 21 | */ 22 | public $path = ''; 23 | 24 | /** 25 | * @var string 26 | */ 27 | public $type = ''; 28 | 29 | /** 30 | * @var string 31 | */ 32 | public $type2 = ''; 33 | 34 | /** 35 | * @var array 36 | */ 37 | public $colors = array(); 38 | 39 | /** 40 | * @var string 41 | */ 42 | public $language = ''; 43 | 44 | /** 45 | * @var string 46 | */ 47 | public $rating = ''; 48 | 49 | /** 50 | * @var int 51 | */ 52 | public $ratingCount = 0; 53 | 54 | /** 55 | * @var string 56 | */ 57 | public $seriesName = ''; 58 | 59 | /** 60 | * @var string 61 | */ 62 | public $thumbnailPath = ''; 63 | 64 | /** 65 | * @var string 66 | */ 67 | public $vignettePath = ''; 68 | 69 | /** 70 | * @var int 71 | */ 72 | public $season; 73 | 74 | /** 75 | * Constructor 76 | * 77 | * @access public 78 | * @param \SimpleXMLElement $data A simplexml element created from thetvdb.com's xml data for the tv serie banner 79 | * @return \Moinax\TvDb\Banner 80 | */ 81 | public function __construct($data) 82 | { 83 | $this->id = (int)$data->id; 84 | $this->path = (string)$data->BannerPath; 85 | $this->type = (string)$data->BannerType; 86 | $this->type2 = (string)$data->BannerType2; 87 | $this->colors = (array)$data->Colors; 88 | $this->language = (string)$data->Language; 89 | $this->rating = (string)$data->Rating; 90 | $this->ratingCount = (int)$data->RatingCount; 91 | $this->seriesName = (string)$data->SeriesName; 92 | $this->thumbnailPath = (string)$data->ThumbnailPath; 93 | $this->vignettePath = (string)$data->VignettePath; 94 | $this->season = (int)$data->Season; 95 | } 96 | } -------------------------------------------------------------------------------- /application/includes/TvDb/CurlException.php: -------------------------------------------------------------------------------- 1 | 10 | **/ 11 | class Episode 12 | { 13 | 14 | /** 15 | * @var int 16 | */ 17 | public $id = 0; 18 | 19 | /** 20 | * @var int 21 | */ 22 | public $number = 0; 23 | 24 | /** 25 | * @var int 26 | */ 27 | public $season = 0; 28 | 29 | /** 30 | * @var array 31 | */ 32 | public $directors = array(); 33 | 34 | /** 35 | * @var array 36 | */ 37 | public $guestStars = array(); 38 | 39 | /** 40 | * @var array 41 | */ 42 | public $writers = array(); 43 | 44 | /** 45 | * @var string 46 | */ 47 | public $name = ''; 48 | 49 | /** 50 | * @var \DateTime 51 | */ 52 | public $firstAired; 53 | 54 | /** 55 | * @var string 56 | */ 57 | public $imdbId = ''; 58 | 59 | /** 60 | * @var string 61 | */ 62 | public $language = Client::DEFAULT_LANGUAGE; 63 | 64 | /** 65 | * @var string 66 | */ 67 | public $overview = ''; 68 | 69 | /** 70 | * @var string 71 | */ 72 | public $rating = ''; 73 | 74 | /** 75 | * @var int 76 | */ 77 | public $ratingCount = 0; 78 | 79 | /** 80 | * @var \DateTime 81 | */ 82 | public $lastUpdated; 83 | 84 | /** 85 | * @var int 86 | */ 87 | public $seasonId = 0; 88 | 89 | /** 90 | * @var int 91 | */ 92 | public $serieId = 0; 93 | 94 | /** 95 | * @var string 96 | */ 97 | public $thumbnail = ''; 98 | 99 | /** 100 | * Constructor 101 | * 102 | * @access public 103 | * @return \Moinax\TvDb\Episode 104 | * @param \SimpleXMLElement $data simplexml element created from thetvdb.com's xml data for the tv episode 105 | */ 106 | public function __construct($data) 107 | { 108 | $this->id = (int)$data->id; 109 | $this->number = (int)$data->EpisodeNumber; 110 | $this->season = (int)$data->SeasonNumber; 111 | $this->directors = (array)Client::removeEmptyIndexes(explode('|', (string)$data->Director)); 112 | $this->name = (string)$data->EpisodeName; 113 | $this->firstAired = (string)$data->FirstAired !== '' ? new \DateTime((string)$data->FirstAired) : null; 114 | $this->guestStars = Client::removeEmptyIndexes(explode('|', (string)$data->GuestStars)); 115 | $this->imdbId = (string)$data->IMDB_ID; 116 | $this->language = (string) $data->Language; 117 | $this->overview = (string)$data->Overview; 118 | $this->rating = (string)$data->Rating; 119 | $this->ratingCount = (int)$data->RatingCount; 120 | $this->lastUpdated = \DateTime::createFromFormat('U', (int)$data->lastupdated); 121 | $this->writers = (array)Client::removeEmptyIndexes(explode('|', (string)$data->Writer)); 122 | $this->thumbnail = (string)$data->filename; 123 | $this->seasonId = (int)$data->seasonid; 124 | $this->serieId = (int)$data->seriesid; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /application/includes/TvDb/Exception.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 12 | } 13 | 14 | /** 15 | * 16 | * @see \Moinax\TvDb\Http\Cache\Cache::getDate() 17 | */ 18 | public function getDate($resource) 19 | { 20 | $path = $this->getPath($resource); 21 | if(!file_exists($path)) { 22 | return -1; 23 | } 24 | return filemtime($path); 25 | } 26 | 27 | /** 28 | * 29 | * @see \Moinax\TvDb\Http\Cache\Cache::setDate() 30 | */ 31 | public function setDate($resource, $date) 32 | { 33 | $path = $this->getPath($resource); 34 | 35 | if(! file_exists($path)) { 36 | return; 37 | } 38 | 39 | touch($path, $date); 40 | } 41 | 42 | /** 43 | * 44 | * @see \Moinax\TvDb\Http\Cache\Cache::cache() 45 | */ 46 | public function cache($resource, $date, $content) 47 | { 48 | $path = $this->getPath($resource); 49 | 50 | $dirname = dirname($path); 51 | if(!is_dir($dirname)) { 52 | mkdir($dirname, 0777, true); 53 | } 54 | 55 | file_put_contents($path, $content); 56 | $this->setDate($resource, $date); 57 | } 58 | 59 | /** 60 | * 61 | * @see \Moinax\TvDb\Http\Cache\Cache::getContent() 62 | */ 63 | public function getContent($resource) 64 | { 65 | $path = $this->getPath($resource); 66 | 67 | if(! file_exists($path)) { 68 | return ''; 69 | } 70 | 71 | return file_get_contents($path); 72 | } 73 | 74 | private function getPath($resource) { 75 | return $this->directory . $resource; 76 | } 77 | } -------------------------------------------------------------------------------- /application/includes/TvDb/Http/CacheClient.php: -------------------------------------------------------------------------------- 1 | cache = $cache; 33 | 34 | $this->ttl = $ttl; 35 | } 36 | 37 | /** 38 | * 39 | * @see \Moinax\TvDb\Http\HttpClient::fetch() 40 | */ 41 | public function fetch($url, array $params = array(), $method = HttpClient::GET) 42 | { 43 | $ch = $this->curlInit($url, $params, $method); 44 | if($method == HttpClient::POST) { 45 | return $this->doPost($ch, $url); 46 | } 47 | return $this->doGet($ch, $url); 48 | } 49 | 50 | /** 51 | * Get the cache time to live. 52 | * 53 | * @return number 54 | */ 55 | public function getTtl() 56 | { 57 | return $this->ttl; 58 | } 59 | 60 | /** 61 | * Set the cache time to live. 62 | * 63 | * @param integer $ttl 64 | */ 65 | public function setTtl($ttl) 66 | { 67 | $this->ttl = $ttl; 68 | } 69 | 70 | /** 71 | * Do a GET request. 72 | * 73 | * @param resource $ch 74 | * @param string $url 75 | * @throws CurlException 76 | * @return string 77 | */ 78 | private function doGet($ch, $url) 79 | { 80 | $now = time(); 81 | $resource = $this->getResourceName($url); 82 | $date = $this->cache->getDate($resource); 83 | $limit = $now - $this->ttl; 84 | 85 | //Return content if ttl has not yet expired. 86 | if($date > 0 && $date > $limit) { 87 | return $this->cache->getContent($resource); 88 | } 89 | 90 | //Add the If-Modified-Since header 91 | if($date > 0) { 92 | curl_setopt($ch, CURLOPT_HTTPHEADER, array( 93 | sprintf("If-Modified-Since: %s GMT", gmdate("D, d M Y H:i:s", $date)), 94 | )); 95 | } 96 | 97 | curl_setopt($ch, CURLOPT_FILETIME, true); 98 | 99 | $data = $this->curlExec($ch); 100 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 101 | $date = curl_getinfo($ch, CURLINFO_FILETIME); 102 | curl_close($ch); 103 | 104 | //Return content from cache. 105 | if($httpCode == 304) { 106 | $this->cache->setDate($resource, $date); 107 | return $this->cache->getContent($resource); 108 | } 109 | 110 | //Cache content 111 | if ($httpCode == 200) { 112 | $date = ($date >= 0) ? $date : $now; 113 | $this->cache->cache($resource, $date, $data); 114 | 115 | return $data; 116 | } 117 | 118 | throw new CurlException(sprintf('Cannot fetch %s', $url), $httpCode); 119 | } 120 | 121 | /** 122 | * Do a POST request. 123 | * 124 | * @param resource $ch 125 | * @param string $url 126 | * @throws CurlException 127 | * @return string 128 | */ 129 | private function doPost($ch, $url) 130 | { 131 | $data = $this->curlExec($ch); 132 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 133 | curl_close($ch); 134 | 135 | if ($httpCode != 200) { 136 | throw new CurlException(sprintf('Cannot fetch %s', $url), $httpCode); 137 | } 138 | 139 | return $data; 140 | } 141 | 142 | /** 143 | * Exec the given cURL connection and return the content body. 144 | * @param resource $ch 145 | * @return string 146 | */ 147 | private function curlExec($ch) 148 | { 149 | $response = curl_exec($ch); 150 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 151 | return substr($response, $headerSize); 152 | } 153 | 154 | /** 155 | * Initialize a new cURL client. 156 | * 157 | * @param string $url 158 | * @param array $params 159 | * @param string $method 160 | * 161 | * @return resource 162 | */ 163 | private function curlInit($url, array $params, $method) 164 | { 165 | $ch = curl_init($url); 166 | curl_setopt($ch, CURLOPT_HEADER, 1); 167 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 168 | 169 | if ($method == HttpClient::POST) { 170 | curl_setopt($ch, CURLOPT_POST, 1); 171 | curl_setopt($ch, CURLOPT_POSTFIELDS, $params); 172 | } 173 | 174 | return $ch; 175 | } 176 | 177 | /** 178 | * Get the resource name from url removing the host part and the API key if provided. 179 | * 180 | * @param string $url 181 | * @return string 182 | */ 183 | private function getResourceName($url) 184 | { 185 | $url = parse_url($url); 186 | $extension = pathinfo($url['path'], PATHINFO_EXTENSION); 187 | 188 | $resource = $url['path']; 189 | if(in_array($extension, array('xml', 'zip'))) { 190 | //Remove the api key from the resource name. 191 | $path = explode('/', $url['path']); 192 | unset($path[2]); 193 | $resource = implode('/', $path); 194 | } 195 | 196 | if (!empty($url['query'])) { 197 | $resource .= '?' . $url['query']; 198 | } 199 | 200 | return $resource; 201 | } 202 | } -------------------------------------------------------------------------------- /application/includes/TvDb/Http/CurlClient.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class Serie 12 | { 13 | /** 14 | * @var int 15 | */ 16 | public $id; 17 | 18 | /** 19 | * @var string 20 | */ 21 | public $language; 22 | 23 | /** 24 | * @var string 25 | */ 26 | public $name; 27 | 28 | /** 29 | * @var string 30 | */ 31 | public $banner; 32 | 33 | /** 34 | * @var string 35 | */ 36 | public $overview; 37 | 38 | /** 39 | * @var \DateTime 40 | */ 41 | public $firstAired; 42 | 43 | /** 44 | * @var string 45 | */ 46 | public $imdbId; 47 | 48 | /** 49 | * @var array 50 | */ 51 | public $actors = array(); 52 | 53 | /** 54 | * @var string 55 | */ 56 | public $airsDayOfWeek = ''; 57 | 58 | /** 59 | * @var string 60 | */ 61 | public $airsTime = ''; 62 | 63 | /** 64 | * @var string 65 | */ 66 | public $contentRating = ''; 67 | 68 | /** 69 | * @var array 70 | */ 71 | public $genres = array(); 72 | 73 | /** 74 | * @var string 75 | */ 76 | public $network = ''; 77 | 78 | /** 79 | * @var string 80 | */ 81 | public $rating = ''; 82 | 83 | /** 84 | * @var int 85 | */ 86 | public $ratingCount = 0; 87 | 88 | /** 89 | * @var int 90 | */ 91 | public $runtime = 0; 92 | 93 | /** 94 | * @var string 95 | */ 96 | public $status = ''; 97 | 98 | /** 99 | * @var \DateTime 100 | */ 101 | public $added; 102 | 103 | /** 104 | * @var int 105 | */ 106 | public $addedBy; 107 | 108 | /** 109 | * @var string 110 | */ 111 | public $fanArt = ''; 112 | 113 | /** 114 | * @var \DateTime 115 | */ 116 | public $lastUpdated; 117 | 118 | /** 119 | * @var string 120 | */ 121 | public $poster = ''; 122 | 123 | /** 124 | * @var string 125 | */ 126 | public $zap2ItId = ''; 127 | 128 | /** 129 | * @var array 130 | */ 131 | public $aliasNames = array(); 132 | 133 | /** 134 | * Constructor 135 | * 136 | * @access public 137 | * @param \SimpleXMLElement $data A simplexml element created from thetvdb.com's xml data for the tv show 138 | * @return \Moinax\TvDb\Serie 139 | */ 140 | public function __construct($data) 141 | { 142 | $this->id = (int)$data->id; 143 | $this->language = (string)$data->Language; 144 | if(isset($data->language)) { 145 | $this->language = (string)$data->language; 146 | } 147 | $this->name = (string)$data->SeriesName; 148 | $this->banner = (string)$data->banner; 149 | $this->overview = (string)$data->Overview; 150 | $this->firstAired = new \DateTime((string)$data->FirstAired); 151 | $this->imdbId = (string)$data->IMDB_ID; 152 | $this->actors = (array)Client::removeEmptyIndexes(explode('|', (string)$data->Actors)); 153 | $this->airsDayOfWeek = (string)$data->Airs_DayOfWeek; 154 | $this->airsTime = (string)$data->Airs_Time; 155 | $this->contentRating = (string)$data->ContentRating; 156 | $this->genres = (array)Client::removeEmptyIndexes(explode('|', (string)$data->Genre)); 157 | $this->network = (string)$data->Network; 158 | $this->rating = (string)$data->Rating; 159 | $this->ratingCount = (string)$data->RatingCount; 160 | $this->runtime = (int)$data->Runtime; 161 | $this->status = (string)$data->Status; 162 | $this->added = new \DateTime((string)$data->added); 163 | $this->addedBy = (int)$data->addedBy; 164 | $this->fanArt = (string)$data->fanart; 165 | $this->lastUpdated = \DateTime::createFromFormat('U', (int)$data->lastupdated); 166 | $this->poster = (string)$data->poster; 167 | $this->zap2ItId = (string)$data->zap2it_id; 168 | if(isset($data->AliasNames)) { 169 | $this->aliasNames = (array)Client::removeEmptyIndexes(explode('|', (string)$data->AliasNames)); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /application/includes/TvDb/XmlException.php: -------------------------------------------------------------------------------- 1 | path = $filePath; 22 | } 23 | 24 | /** 25 | * Open stream 26 | */ 27 | private function open() 28 | { 29 | if (!($this->stream = fopen($this->path, 'rb', false, stream_context_create()))) { 30 | die('Could not open stream for reading'); 31 | } 32 | 33 | } 34 | 35 | /** 36 | * Set proper header to serve the video content 37 | */ 38 | private function setHeader() 39 | { 40 | ob_get_clean(); 41 | header("Content-Type: video/mp4"); 42 | header("Cache-Control: max-age=2592000, public"); 43 | header("Expires: ".gmdate('D, d M Y H:i:s', time()+2592000) . ' GMT'); 44 | header("Last-Modified: ".gmdate('D, d M Y H:i:s', @filemtime($this->path)) . ' GMT' ); 45 | $this->start = 0; 46 | $this->size = filesize($this->path); 47 | $this->end = $this->size - 1; 48 | header("Accept-Ranges: 0-".$this->end); 49 | 50 | if (isset($_SERVER['HTTP_RANGE'])) { 51 | 52 | $c_start = $this->start; 53 | $c_end = $this->end; 54 | 55 | list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); 56 | if (strpos($range, ',') !== false) { 57 | header('HTTP/1.1 416 Requested Range Not Satisfiable'); 58 | header("Content-Range: bytes $this->start-$this->end/$this->size"); 59 | exit; 60 | } 61 | if ($range == '-') { 62 | $c_start = $this->size - substr($range, 1); 63 | }else{ 64 | $range = explode('-', $range); 65 | $c_start = $range[0]; 66 | 67 | $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end; 68 | } 69 | $c_end = ($c_end > $this->end) ? $this->end : $c_end; 70 | if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) { 71 | header('HTTP/1.1 416 Requested Range Not Satisfiable'); 72 | header("Content-Range: bytes $this->start-$this->end/$this->size"); 73 | exit; 74 | } 75 | $this->start = $c_start; 76 | $this->end = $c_end; 77 | $length = $this->end - $this->start + 1; 78 | fseek($this->stream, $this->start); 79 | header('HTTP/1.1 206 Partial Content'); 80 | header("Content-Length: ".$length); 81 | header("Content-Range: bytes $this->start-$this->end/".$this->size); 82 | } 83 | else 84 | { 85 | header("Content-Length: ".$this->size); 86 | } 87 | 88 | } 89 | 90 | /** 91 | * close curretly opened stream 92 | */ 93 | private function end() 94 | { 95 | fclose($this->stream); 96 | exit; 97 | } 98 | 99 | /** 100 | * perform the streaming of calculated range 101 | */ 102 | private function stream() 103 | { 104 | $i = $this->start; 105 | set_time_limit(0); 106 | while(!feof($this->stream) && $i <= $this->end && connection_aborted() == 0) { 107 | $bytesToRead = $this->buffer; 108 | if(($i+$bytesToRead) > $this->end) { 109 | $bytesToRead = $this->end - $i + 1; 110 | } 111 | $data = stream_get_contents($this->stream, $bytesToRead); 112 | echo $data; 113 | flush(); 114 | $i += $bytesToRead; 115 | } 116 | } 117 | 118 | /** 119 | * Start streaming video content 120 | */ 121 | function start() 122 | { 123 | session_write_close(); //ensure our session is written away before streaming, else we cannot use it elsewhere 124 | $this->open(); 125 | $this->setHeader(); 126 | $this->stream(); 127 | $this->end(); 128 | } 129 | } 130 | ?> 131 | -------------------------------------------------------------------------------- /application/includes/providers/movie/CouchPotato.php: -------------------------------------------------------------------------------- 1 | settings['location'] . 'api/' . $this->settings['api'] . '/'; 7 | } 8 | 9 | private function convert($json){ 10 | $result = false; 11 | if ($json != false){ 12 | $result = new Movie(); 13 | $result->name = $json->title; 14 | $result->year = $json->info->year; 15 | $result->description = $json->info->plot; 16 | $result->genres = $json->info->genres; 17 | $result->id = $json->identifiers->imdb; 18 | $result->actors = $json->info->actors; 19 | $release = $this->getRelease($json->releases); 20 | $result->location = $release['movie']; 21 | $result->subtitles = $release['subtitles']; 22 | $result->quality = $release['quality']; 23 | $result->size = $release['size']; 24 | $result->rating = 0; //todo 25 | 26 | foreach ($json->info->images->actors as $actor => $img){ 27 | $json->info->images->actors->$actor = $this->cache->getImage($img); 28 | } 29 | 30 | $result->images = array( 31 | 'poster' => $this->cache->getImage($json->info->images->poster[0]), 32 | 'actors' => $json->info->images->actors, 33 | 'backdrop' => $this->cache->getImage($json->info->images->backdrop[0]), 34 | ); 35 | $result->status = $json->status; 36 | $result->rating = $json->info->rating->imdb[0]; 37 | } 38 | return $result; 39 | } 40 | 41 | public function humanFileSize($size, $unit='') 42 | { 43 | if ( (!$unit && $size >= 1<<30) || $unit == "GB") 44 | return number_format($size/(1<<30),2). " GB"; 45 | if ( (!$unit && $size >= 1<<20) || $unit == "MB") 46 | return number_format($size/(1<<20),2) . " MB"; 47 | if ( (!$unit && $size >= 1<<10) || $unit == "KB") 48 | return number_format($size/(1<<10),2) . " KB"; 49 | return number_format($size) . " bytes"; 50 | } 51 | 52 | 53 | private function getRelease($releases){ 54 | $result = array('movie' => false, 'subtitles' => array(), 'quality' => false, 'size' => 0); 55 | foreach ($releases as $id => $release){ 56 | if ($release->status == "done"){ 57 | //movie 58 | foreach ($release->files->movie as $id => $movie_entry){ 59 | if (file_exists($movie_entry)){ 60 | if ($result['movie'] == false or filesize($movie_entry) > filesize($result['movie'])){ 61 | $result['movie'] = $movie_entry; 62 | $result['quality'] = $release->quality; 63 | $result['size'] = $this->humanFileSize(filesize($movie_entry)); 64 | } 65 | } 66 | } 67 | //subs 68 | foreach ($release->files->subtitle as $id => $sub_entry){ 69 | if (file_exists($sub_entry)){ 70 | $lang = pathinfo(pathinfo($sub_entry, PATHINFO_EXTENSION), PATHINFO_EXTENSION); 71 | if ($lang == false) $lang = 'en'; 72 | array_push($result['subtitles'], array('language' => $lang, 'subtitle' => $sub_entry)); 73 | } 74 | } 75 | } 76 | } 77 | return $result; 78 | } 79 | 80 | function getMovies($status='done', $num=false, $force=false){ 81 | $result = array(); 82 | $url = 'media.list?x=x'; 83 | if ($status != false) $url .= '&status=' . urlencode($status); 84 | if ($num != false) $url .= '&limit_offset=' . urlencode($num); 85 | $ttl = '-1 hour'; 86 | if ($force == true){ 87 | $ttl = false; 88 | } 89 | $json = $this->cache->getJson($this->buildURL() . $url, $ttl); 90 | if ($json->success){ 91 | foreach ($json->movies as $id => $movie){ 92 | array_push($result, $this->convert($movie)); 93 | } 94 | } 95 | return $result; 96 | } 97 | 98 | function getMovie($id){ 99 | $json = $this->cache->getJson($this->buildURL() . 'media.get?id=' . $id, '-1 week'); 100 | return $this->convert($json->media); 101 | } 102 | 103 | function restartApp(){ 104 | $response = $this->cache->getJson($this->buildURL() . 'app.restart'); 105 | if ($response){ 106 | return true; 107 | } else { 108 | return false; 109 | } 110 | } 111 | 112 | function refresh(){ 113 | $json = $this->cache->getJson($this->buildURL() . 'manage.update?full=true'); 114 | return ($json && $json->success); 115 | } 116 | 117 | function getRefreshProgress(){ 118 | $json = $this->cache->getJson($this->buildURL() . 'manager.progress'); 119 | return $json->progress; 120 | } 121 | 122 | function refreshMovie($id){ 123 | $json = $this->cache->getJson($this->buildURL() . 'media.refresh?id=' . urlencode($id)); 124 | return ($json && $json->success == true); 125 | } 126 | 127 | function searchMovie($title){ 128 | $result = array(); 129 | $json = $this->cache->getJson($this->buildURL() . 'media.list?search=' . urlencode($title), '-1 week'); 130 | if ($json->success){ 131 | foreach ($json->movies as $id => $movie){ 132 | array_push($result, $this->convert($movie)); 133 | } 134 | } 135 | return $result; 136 | } 137 | 138 | function addMovie($id){ 139 | $json = $this->cache->getJson($this->buildURL() . 'movie.add?identifier=' . urlencode($id)); 140 | return ($json != false && $json->success == true); 141 | } 142 | 143 | function getLatestNotifications($offset=false, $limit=100){ 144 | if ($offset == false) $offset = ''; 145 | $json = $this->cache->getJson($this->buildURL() . 'notification.list?limit_offset=' . urlencode($offset) . ',' . urlencode($limit)); 146 | $result = $json->success; 147 | if ($result == true) $result = $json->notifications; 148 | return $result; 149 | } 150 | 151 | } 152 | 153 | ?> 154 | -------------------------------------------------------------------------------- /application/includes/providers/show/SickRage.php: -------------------------------------------------------------------------------- 1 | settings['location'] . 'api/' . $this->settings['api'] . '/?cmd='; 7 | } 8 | 9 | private function buildShow($id){ 10 | $show = false; 11 | $json = $this->cache->getJson($this->buildURL() . 'show&tvdbid=' . urlencode($id), 1440); 12 | if ($json && $json->success == 'success'){ 13 | $show = $this->convertShow($json); 14 | if ($show){ 15 | $this->cache->storeObject($id, $show); 16 | } 17 | } 18 | return $show; 19 | } 20 | 21 | private function convertShow($show){ 22 | $result = false; 23 | if ($show != false){ 24 | $result = new Show(); 25 | $result->quality = $show->quality; 26 | $result->id = $show->tvdbid; 27 | $result->name = $show->show_name; 28 | $result->network = $show->network; 29 | $result->language = $show->language; 30 | if (array_key_exists('imdbid', $show) == true) $result->imdbid = $show->imdbid; 31 | 32 | $tvdb = $this->cache->tvdb->getSerieEpisodes($result->id, $this->settings['lang']); 33 | 34 | $result->seasons = $this->getSeasons($result->id, $tvdb); 35 | $result->active = ($show->status != 'Ended'); 36 | $result->status = $show->status; 37 | $result->images = array( 38 | 'poster' => $this->cache->getImage('http://thetvdb.com/banners/' . $tvdb['serie']->poster), 39 | 'banner' => $this->cache->getImage($this->getBanner($result->id)) 40 | ); 41 | $result->description = $tvdb['serie']->overview; 42 | $result->airs = $tvdb['serie']->airsDayOfWeek . ' ' . $tvdb['serie']->airsTime; 43 | 44 | $result->air_by_date = $tvdb['serie']->firstAired->format('Y'); 45 | $result->genres = $tvdb['serie']->genres; 46 | $result->rating = $tvdb['serie']->rating; 47 | } 48 | return $result; 49 | } 50 | 51 | private function convertEpisode($episode, $id, $nr, $e_nr){ 52 | $result = false; 53 | if ($episode != false){ 54 | $result = new Episode(); 55 | $result->airdate = $episode->airdate; 56 | $result->size = $episode->file_size; 57 | $result->location = $episode->location; 58 | $result->name = $episode->name; 59 | $result->status = $episode->status; 60 | 61 | $tvdb = $this->cache->tvdb->getEpisode($id, $nr, $e_nr); 62 | $result->description = $tvdb->overview; 63 | $result->images = array( 64 | 'thumbnail' => $this->cache->getImage('http://thetvdb.com/banners/' . $tvdb->thumbnail) 65 | ); 66 | } 67 | return $result; 68 | } 69 | 70 | private function getBanner($id){ 71 | return $this->cache->getImage($this->buildURL() . 'show.getbanner&tvdbid=' . urlencode($id)); 72 | } 73 | /* 74 | function searchShow($title){ 75 | $result = array(); 76 | $shows = $this->getShows(); 77 | foreach ($shows as $show){ 78 | if ($title == '' or strpos(strtolower($show->name), strtolower($title)) !== 0){ 79 | array_push($result, $show); 80 | } 81 | } 82 | return $result; 83 | } 84 | */ 85 | 86 | function getLatestEpisodes($type="downloaded", $limit=10){ 87 | $result = array(); 88 | $json = $this->cache->getJson($this->buildURL() . 'history&type=' . urlencode($type) . '&limit=' . urlencode($limit)); 89 | if ($json){ 90 | foreach ($json->data as $log){ 91 | array_push($result, $this->convertEpisode($log)); 92 | } 93 | } 94 | return $result; 95 | } 96 | 97 | function getShow($id){ 98 | $result = false; 99 | $json = $this->cache->getJson($this->buildURL() . 'show&tvdbid=' . urlencode($id), 1440); 100 | if ($json && $json->result == 'success'){ 101 | $result = $this->convertShow($json->data); 102 | } 103 | return $result; 104 | } 105 | 106 | function getShows($force=false){ 107 | $result = array(); 108 | if ($force == false) $force = '-1 day'; 109 | $json = $this->cache->getJson($this->buildURL() . 'shows&sort=name', $force); 110 | if ($json && $json->result == 'success'){ 111 | foreach ($json->data as $id => $showObj){ 112 | array_push($result, $this->convertShow($showObj)); 113 | } 114 | } 115 | return $result; 116 | } 117 | 118 | 119 | function getSeasons($id){ 120 | $result = array(); 121 | $json = $this->cache->getJson($this->buildURL() . 'show.seasons&tvdbid=' . urlencode($id), 1440); 122 | if ($json && $json->result == 'success'){ 123 | foreach ($json->data as $nr => $s){ 124 | $season = array(); 125 | foreach ($s as $e_nr => $episode){ 126 | array_push($season, $this->convertEpisode($episode, $id, $nr, $e_nr)); 127 | } 128 | array_push($result, $season); 129 | } 130 | } 131 | return $result; 132 | } 133 | 134 | function getEpisode($id, $season, $episode){ 135 | $result = false; 136 | $json = $this->cache->getJson($this->buildURL() . 'episode&full_path=1&tvdbid=' . urlencode($id) . '&season=' . urlencode($season) . '&episode=' . urlencode($episode), 1440); 137 | if ($json && $json->result == 'success'){ 138 | $result = $this->convertEpisode($json->data, $id, $season, $episode); 139 | } 140 | return $result; 141 | } 142 | 143 | function restartApp(){ 144 | $json = $this->cache->getJson($this->buildURL() . 'sb.restart'); 145 | return ($json && $json->result == 'success'); 146 | } 147 | 148 | function refresh(){ 149 | return false; 150 | } 151 | 152 | function getRefreshProgress(){ 153 | return false; 154 | } 155 | 156 | function refreshShow($id){ 157 | $json = $this->cache->getJson($this->buildURL() . 'show.refresh&tvdbid=' . urlencode($id)); 158 | return ($json && $json->result == 'success'); 159 | } 160 | 161 | function searchShow($title){ 162 | $result = array(); 163 | //echo $this->buildURL() . 'sb.searchtvdb&name=' . urlencode($title) . '&lang=' . urlencode($this->settings['lang']); die(); 164 | $json = $this->cache->getJson($this->buildURL() . 'sb.searchtvdb&name=' . urlencode($title) . '&lang=' . urlencode($this->settings['lang'])); 165 | if ($json->result == 'success'){ 166 | foreach ($json->data->results as $i => $showObj){ 167 | $show = new Show(); 168 | $show->id = $showObj->tvdbid; 169 | $show->name = $showObj->name; 170 | $show->air_by_date = $showObj->first_aired; 171 | array_push($result, $show); 172 | } 173 | } 174 | return $result; 175 | } 176 | 177 | function addShow($id){ 178 | $json = $this->cache->getJson($this->buildURL() . 'show.addnew&status=wanted&tvdbid=' . urlencode($id)); 179 | return ($json && $json->result == 'success'); 180 | } 181 | 182 | function getLatestNotifications($limit=100){ 183 | $json = $this->cache->getJSon($this->buildURL() . 'history&type=downloaded&limit=' . urlencode($limit)); 184 | } 185 | } 186 | 187 | ?> -------------------------------------------------------------------------------- /application/languages/lang.en.php: -------------------------------------------------------------------------------- 1 | addAccessLog($date, $user, $user, $file, $msec); 35 | } 36 | } 37 | ftruncate($handle, 0); 38 | fclose($handle); 39 | } else { 40 | error_log('Accesslog processor could not read /var/log/nginx/webdav.log'); 41 | } 42 | } 43 | 44 | private function addAccessLog($date, $user, $ip, $file, $msec) 45 | { 46 | //req_movies (date DATESTR, file TEXT NOT NULL, user SMALLINT REFERENCES users(id), ip varchar(39));", 47 | $query = "INSERT INTO req_movies(date, file, user, ip, msec) values (?, ?, ?, ?, ?);"; 48 | 49 | $this->db->query($query, array( 50 | $date, 51 | $file, 52 | $user, 53 | $ip, 54 | $msec 55 | )); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /application/models/langs_m.php: -------------------------------------------------------------------------------- 1 | LANG_PATH . "lang.[a-z][a-z].php"); 26 | 27 | foreach ($all as $i => $langf){ 28 | $parts = explode('.', $langf, 3); 29 | $result[] = (object) array( 30 | 'id' => $i, 31 | 'name' => $this->getLanguageName($parts[1]), 32 | 'flag' => $parts[1], 33 | ); 34 | } 35 | 36 | return $result; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /application/models/menu_m.php: -------------------------------------------------------------------------------- 1 | login)){ 8 | return $this->getUsermenu($lang, ($user->role == 1)); 9 | } else { 10 | return $this->getStartmenu($lang); 11 | } 12 | } 13 | 14 | 15 | public function getStartmenu($lang) 16 | { 17 | $menuitems = array( 18 | array( 19 | 'link' => 'home/index', 20 | 'description' => $lang['login'], 21 | ), 22 | ); 23 | return $menuitems; 24 | } 25 | 26 | 27 | public function getUsermenu($lang,$admin=false) 28 | { 29 | $menuitems = array( 30 | array( 31 | 'link' => 'home/index', 32 | 'description' => $lang['dashboard'], 33 | ), 34 | array( 35 | 'link' => 'movies/index', 36 | 'description' => $lang['movies'], 37 | ), 38 | array( 39 | 'link' => 'series/index', 40 | 'description' => $lang['series'], 41 | ), 42 | array( 43 | 'link' => array( 44 | array('link' => 'help/windows', 45 | 'description' => 'Windows' 46 | ), 47 | array('link' => 'help/mac', 48 | 'description' => 'Mac' 49 | ), 50 | array('link' => 'help/synology', 51 | 'description' => 'Synology' 52 | ), 53 | array('link' => 'help/kodi', 54 | 'description' => 'XBMC/Kodi' 55 | ), 56 | array('link' => 'help/android', 57 | 'description' => 'Android' 58 | ), 59 | array('link' => 'help/ios', 60 | 'description' => 'iOS' 61 | ), 62 | ), 63 | 'description' => $lang['help'], 64 | ), 65 | ); 66 | if ($admin == true){ 67 | array_push($menuitems, array( 68 | 'link' => 'admin/index', 69 | 'description' => '' . $lang['admin'] . '', 70 | )); 71 | } 72 | return $menuitems; 73 | } 74 | 75 | public function getAdminmenu(){ 76 | $menuitems = array(); 77 | return $menuitems; 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /application/models/user_m.php: -------------------------------------------------------------------------------- 1 | needSetup) and $this->needSetup == true){ 8 | error_log('First run, so filling gunther.auth..'); 9 | $this->writeAuthFile(); 10 | } 11 | parent::__construct(); 12 | } 13 | 14 | 15 | private function writeAuthFile() 16 | { 17 | global $settings; 18 | 19 | $str = ""; 20 | foreach ($this->getUsers() as $user){ 21 | $str .= $user->login . ':' . 'Media' . ':' . $user->pass . "\n"; 22 | } 23 | 24 | file_put_contents($settings['AUTH_DIGEST_FILE'], $str, LOCK_EX); 25 | return true; 26 | } 27 | 28 | 29 | public function isValid($login, $password) 30 | { 31 | $result = false; 32 | $user = $this->getUserByLogin($login); 33 | $passwordhash = $login . ':Media:' . hash('md5', $password); 34 | if ($user && strcmp($passwordhash, $user->pass) == 0) { 35 | $result = true; 36 | } elseif ($settings['REPORT_BAD_LOGIN'] == true){ 37 | error_log('User ' . $login . ' tried bad password ' . $password); 38 | error_log($passwordhash . ' != ' . $user->pass); 39 | } 40 | return $result; 41 | } 42 | 43 | public function getRoles() 44 | { 45 | $result = false; 46 | 47 | $query = "SELECT * FROM roles;"; 48 | $roles = $this->db->query($query); 49 | 50 | if ($roles){ 51 | $result = $roles->getResult(); 52 | } 53 | 54 | return $result; 55 | } 56 | 57 | public function getRoleById($id) 58 | { 59 | $result = false; 60 | 61 | $role = $this->db->query("SELECT * FROM roles WHERE (id = ?);", $id); 62 | if ($role){ 63 | $result = $role->getRow(); 64 | } 65 | 66 | return $result; 67 | } 68 | 69 | public function getUserById($id) 70 | { 71 | $result = false; 72 | 73 | $query = "SELECT * FROM users WHERE (id = ?);"; 74 | $user = $this->db->query($query, $id); 75 | 76 | if ($user){ 77 | $result = $user->getRow(); 78 | } 79 | 80 | return $result; 81 | } 82 | 83 | public function getUserByLogin($login) 84 | { 85 | $result = false; 86 | 87 | $query = "SELECT * FROM users WHERE (login = ?);"; 88 | $user = $this->db->query($query, strtolower($login)); 89 | 90 | if ($user){ 91 | $result = $user->getRow(); 92 | } 93 | 94 | return $result; 95 | } 96 | 97 | public function addUser($login, $pass, $name, $email, $role) 98 | { 99 | $role = $this->getRoleById($role); 100 | if ($role){ 101 | $role = $role->name; 102 | $pass_str = hash('md5', $login . ':Media:' . $pass); 103 | $query = "INSERT INTO users(login, name, email, pass, role) VALUES (?,?,?,?,?);"; 104 | $this->db->query($query, array($login, $name, $email, $pass_str, $role)); 105 | 106 | $user = $this->db->query("SELECT * FROM users WHERE (login = ?);", $login); 107 | $result = ($user != false); 108 | if ($result){ 109 | $this->writeAuthFile(); 110 | } 111 | } else { 112 | error_log("Could not find role '" . $role ."' when adding user " . $login); 113 | } 114 | return ($role != false); 115 | } 116 | 117 | public function delUser($id) 118 | { 119 | $query = "DELETE FROM users WHERE (id = ?);"; 120 | $this->db->query($query, $id); 121 | 122 | $user = $this->db->query("SELECT * FROM users WHERE (id = ?);", $id); 123 | $result = ($user == false); 124 | if ($result){ 125 | $this->writeAuthFile(); 126 | } 127 | return $result; 128 | } 129 | 130 | public function getUsers(){ 131 | $result = false; 132 | 133 | $query = "SELECT * FROM users;"; 134 | $users = $this->db->query($query); 135 | 136 | if ($users){ 137 | $result = $users->getResult(); 138 | } 139 | 140 | return $result; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /application/views/_layouts/default.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | renderPartial('headermeta'); ?> 5 | 6 | 7 | renderPartial('navbar'); ?> 8 | 9 | 14 | 15 |
16 | getContent(); ?> 17 |
18 | 19 | 20 | 21 | 22 | 51 | 52 | 53 | 56 | 57 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /application/views/_partials/flashmessage.php: -------------------------------------------------------------------------------- 1 | flashmessage): ?> 2 |
3 | 4 | flashmessage->message; ?> 5 |
6 | 7 | -------------------------------------------------------------------------------- /application/views/_partials/footer.php: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /application/views/_partials/headermeta.php: -------------------------------------------------------------------------------- 1 | 2 | <?php echo $this->getPagetitle(); ?> 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /application/views/_partials/navbar.php: -------------------------------------------------------------------------------- 1 | flag == $code){ 6 | $result = $arr[$i]->name; 7 | break; 8 | } 9 | } 10 | return $result; 11 | } 12 | ?> 13 | 65 | -------------------------------------------------------------------------------- /application/views/admin/adduser.php: -------------------------------------------------------------------------------- 1 |
2 | 7 | 8 | renderPartial('flashmessage'); ?> 9 | 10 |
11 | 12 |
13 |

lang['adduser']; ?>

14 |
15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 |
27 |
28 |
29 | 30 |
31 | 32 |
33 |
34 |
35 | 36 |
37 | 38 |
39 |
40 |
41 | 42 |
43 | 52 |
53 |
54 |
55 |
56 | 57 | lang['cancel']; ?> 58 |
59 |
60 |
61 |
62 | 63 |
64 |
65 | -------------------------------------------------------------------------------- /application/views/admin/index.php: -------------------------------------------------------------------------------- 1 |
2 | 9 | 10 | renderPartial('flashmessage'); ?> 11 | 12 |
13 |
14 |
15 |

lang['users']; ?> 16 |
17 |
18 |
19 | lang['searchuser']; ?> 20 | 21 | 22 | lang['add']; ?> 23 | 24 |
25 |
26 |
27 | users as $user): ?> 28 | 29 | login; ?> 30 |
31 | 32 | 33 |
34 |
35 | 36 |
37 |

38 | 39 |
40 |

settings['movie_provider']; ?> (lang['movies']; ?>)

41 |
42 | lang['refreshlibfull']; ?> 43 | lang['refreshlib']; ?> 44 | lang['restart']; ?> 45 | lang['flushmovies']; ?> 46 |
47 | 48 |
49 |

settings['show_provider']; ?> (lang['series']; ?>)

50 |
51 | lang['refreshlib']; ?> 52 | lang['restart']; ?> 53 | lang['flushshows']; ?> 54 |
55 |
56 | 57 |
58 | 59 |
60 |

Log

61 | 64 |
65 |
log; ?>
66 |
67 | 68 |
69 |
70 | -------------------------------------------------------------------------------- /application/views/dashboard/index.php: -------------------------------------------------------------------------------- 1 |
2 | 6 | 7 | renderPartial('flashmessage'); ?> 8 | 9 |
10 | movies): ?> 11 |

lang['recentmovies']; ?>


12 |
13 | movies as $movie): ?> 14 | 15 | <?= $movie->name; ?> 16 | 17 | 18 |
19 | 20 | 21 |
22 | 23 | episodes): ?> 24 |

lang['recentepi']; ?>


25 |
26 | episodes as $episode): ?> 27 | 28 |
29 | <?= $episode->name; ?> 30 |
31 | season . 'E' . $episode->number . ': ' . $episode->name; ?> 32 |
33 |
34 |
35 | 36 |
37 | 38 |
-------------------------------------------------------------------------------- /application/views/help/android.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/application/views/help/android.php -------------------------------------------------------------------------------- /application/views/help/ios.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/application/views/help/ios.php -------------------------------------------------------------------------------- /application/views/help/kodi.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/application/views/help/kodi.php -------------------------------------------------------------------------------- /application/views/help/mac.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/application/views/help/mac.php -------------------------------------------------------------------------------- /application/views/help/synology.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Synology...

4 |

lang['synology-info']; ?>

5 |

lang['readmore']; ?>

6 |
7 | 8 |
9 | 10 |
11 |

lang['synology-howto']; ?>

12 |
    13 |
  1. 14 | Click on File Station (the folder icon) in your Synology web interface. 15 | Synology File station icon 16 |
  2. 17 |
    18 |
  3. 19 | Click on "Tools" and on "Make Connection". 20 | Synology tools menu. 21 |
  4. 22 |
    23 |
  5. 24 | Add our webdav share as seen on the picture. (fill in your username and password) 25 | Synology webdav details 26 |
  6. 27 |
28 |
29 |
-------------------------------------------------------------------------------- /application/views/help/windows.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
-------------------------------------------------------------------------------- /application/views/home/login.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | renderPartial('flashmessage'); ?> 4 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /application/views/info/movie.php: -------------------------------------------------------------------------------- 1 |
2 | 12 | 13 | renderPartial('flashmessage'); ?> 14 | 15 |
16 |
17 |
18 | <?= $this->movie->name; ?> poster 19 |
20 |
21 | movie->quality; ?> 22 | movie->size; ?> 23 |
24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 |
32 |
33 | movie->genres); ?> 34 |
35 |

36 | movie->name; ?> movie->year; ?> 37 |

38 |
movie->rating; ?>/10
39 |
40 |

41 | movie->description; ?> 42 |

43 |
44 |
45 |

lang['actors']; ?>

46 |
47 |
48 | movie->images['actors'] as $actor => $img): ?> 49 |
50 | 51 | <?= $actor; ?> 52 | 53 | <?= $actor; ?> 54 | 55 |
56 | 57 |
58 |
59 | 60 |
61 |
62 |
63 |
64 |
65 | -------------------------------------------------------------------------------- /application/views/media/movies.add.php: -------------------------------------------------------------------------------- 1 |
2 | 15 | 16 | renderPartial('flashmessage'); ?> 17 | 18 |
19 |
20 |
21 | lang['movtitle']; ?> 22 | 23 |
24 |
25 |
26 | results) && (count($this->results) > 0)): ?> 27 |
28 |
29 | 35 |
36 | results): ?> 37 |
38 |

39 | lang['nomovies']; ?> 40 |

41 |
42 | 43 |
44 | 45 | -------------------------------------------------------------------------------- /application/views/media/movies.busy.php: -------------------------------------------------------------------------------- 1 |
2 | 15 | 16 | movies): ?> 17 | movies as $movie): ?> 18 |
19 | <?= $movie->name; ?> 20 |
21 | 22 | 23 |
24 | 25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /application/views/media/movies.php: -------------------------------------------------------------------------------- 1 |
2 | 15 | 16 | renderPartial('flashmessage'); ?> 17 | 18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 | 28 |
29 | 30 | movies): ?> 31 | movies as $movie): ?> 32 |
33 | 34 | <?= $movie->name; ?> 35 | 36 |
37 | 38 | 39 |

40 | lang['nomovies']; ?> 41 |

42 |

43 | lang['oraddit']; ?> 44 |

45 | 46 |
47 | -------------------------------------------------------------------------------- /application/views/media/series.add.php: -------------------------------------------------------------------------------- 1 |
2 | 11 | 12 | renderPartial('flashmessage'); ?> 13 | 14 |
15 |
16 |
17 | lang['movtitle']; ?> 18 | 19 |
20 |
21 |
22 | results) && (count($this->results) > 0)): ?> 23 |
24 |
25 |
26 | results as $show): ?> 27 | name != false): ?> 28 | 29 |

name; ?> (air_by_date; ?>)

30 |
31 | 32 | 33 |
34 |
35 | results): ?> 36 |
37 |

38 | lang['noshows']; ?> 39 |

40 |
41 | 42 |
43 | 44 | -------------------------------------------------------------------------------- /application/views/media/series.episodes.php: -------------------------------------------------------------------------------- 1 |
2 | 12 | 13 | renderPartial('flashmessage'); ?> 14 | 15 |
16 |
17 |
18 | <?= $this->show->name; ?> 19 |
20 |
21 | IMDb 22 |
23 |
24 |
25 |
26 |
27 | show->genres); ?> 28 |
29 |

show->name; ?> show->status != 'Ended'){ echo $this->show->air_by_date; } else { echo 'Ended'; } ?>

30 |
31 | show->rating; ?>/10 32 |
33 |
34 |

35 | show->description; ?> 36 |

37 |

38 |

    39 |
  • lang['seasons']; ?>:
  • 40 | show->seasons as $nr_s => $season): ?> 41 |
  • 42 | 43 |
44 |

45 |
46 | show->seasons): ?> 47 | show->seasons as $nr_s => $season): ?> 48 |

Season

49 | $episode): ?> 50 |
51 | status == 'Downloaded'): ?> 52 | 53 |
54 | <?= $episode->name; ?> 55 |
56 | name; ?> 57 |
58 |
59 |
60 | 61 |
62 | <?= $episode->name; ?> 63 |
64 | name; ?> 65 |
66 |
67 | 68 |
69 | 70 |
71 |
72 | 73 | 74 |

75 | lang['noseasons']; ?> 76 |

77 | 78 |
79 |
80 |
81 | -------------------------------------------------------------------------------- /application/views/media/series.php: -------------------------------------------------------------------------------- 1 |
2 | 12 | 13 | renderPartial('flashmessage'); ?> 14 | 15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 | 25 |
26 | 27 | shows): ?> 28 | shows as $show): ?> 29 |
30 | 31 | <?= $show->name; ?> 32 | 33 |
34 | 35 | 36 |

lang['noshows']; ?>

37 | 38 |
-------------------------------------------------------------------------------- /application/views/media/watch.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /cache/placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/cache/placeholder -------------------------------------------------------------------------------- /css/custom.css: -------------------------------------------------------------------------------- 1 | .grey-inactive { 2 | opacity: 0.4; 3 | filter: alpha(opacity=40); 4 | } 5 | .imgscale { 6 | width: 100%; 7 | max-height: 250px; 8 | } 9 | 10 | div.desc{ 11 | background-color: #2c3e50; 12 | bottom: 0; 13 | color: #fff; 14 | left: 0; 15 | width: 100%; 16 | height: 45px; 17 | padding-left: 3px; 18 | } 19 | 20 | .fix{ 21 | width: 100%; 22 | padding: 0px; 23 | } 24 | 25 | @media only screen and (max-width:599px) { 26 | .vjs-default-skin .vjs-big-play-button {left:25%;top:25%;width:50%;height:50%;} 27 | } 28 | @media only screen and (min-width:600px) and (max-width:768px) { 29 | .vjs-default-skin .vjs-big-play-button {left:25%;top:25%;width:50%;height:50%;font-size:5em;} 30 | } 31 | .video-js {padding-top: 56.25%} 32 | .vjs-fullscreen {padding-top: 0px} 33 | .clickable{ cursor:hand; } 34 | -------------------------------------------------------------------------------- /css/font/vjs.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/css/font/vjs.eot -------------------------------------------------------------------------------- /css/font/vjs.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/css/font/vjs.ttf -------------------------------------------------------------------------------- /css/font/vjs.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/css/font/vjs.woff -------------------------------------------------------------------------------- /css/owl.carousel.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Owl Carousel - Animate Plugin 3 | */ 4 | .owl-carousel .animated { 5 | -webkit-animation-duration: 1000ms; 6 | animation-duration: 1000ms; 7 | -webkit-animation-fill-mode: both; 8 | animation-fill-mode: both; 9 | } 10 | .owl-carousel .owl-animated-in { 11 | z-index: 0; 12 | } 13 | .owl-carousel .owl-animated-out { 14 | z-index: 1; 15 | } 16 | .owl-carousel .fadeOut { 17 | -webkit-animation-name: fadeOut; 18 | animation-name: fadeOut; 19 | } 20 | 21 | @-webkit-keyframes fadeOut { 22 | 0% { 23 | opacity: 1; 24 | } 25 | 26 | 100% { 27 | opacity: 0; 28 | } 29 | } 30 | @keyframes fadeOut { 31 | 0% { 32 | opacity: 1; 33 | } 34 | 35 | 100% { 36 | opacity: 0; 37 | } 38 | } 39 | 40 | /* 41 | * Owl Carousel - Auto Height Plugin 42 | */ 43 | .owl-height { 44 | -webkit-transition: height 500ms ease-in-out; 45 | -moz-transition: height 500ms ease-in-out; 46 | -ms-transition: height 500ms ease-in-out; 47 | -o-transition: height 500ms ease-in-out; 48 | transition: height 500ms ease-in-out; 49 | } 50 | 51 | /* 52 | * Core Owl Carousel CSS File 53 | */ 54 | .owl-carousel { 55 | display: none; 56 | width: 100%; 57 | -webkit-tap-highlight-color: transparent; 58 | /* position relative and z-index fix webkit rendering fonts issue */ 59 | position: relative; 60 | z-index: 1; 61 | } 62 | .owl-carousel .owl-stage { 63 | position: relative; 64 | -ms-touch-action: pan-Y; 65 | } 66 | .owl-carousel .owl-stage:after { 67 | content: "."; 68 | display: block; 69 | clear: both; 70 | visibility: hidden; 71 | line-height: 0; 72 | height: 0; 73 | } 74 | .owl-carousel .owl-stage-outer { 75 | position: relative; 76 | overflow: hidden; 77 | /* fix for flashing background */ 78 | -webkit-transform: translate3d(0px, 0px, 0px); 79 | } 80 | .owl-carousel .owl-controls .owl-nav .owl-prev, 81 | .owl-carousel .owl-controls .owl-nav .owl-next, 82 | .owl-carousel .owl-controls .owl-dot { 83 | cursor: pointer; 84 | cursor: hand; 85 | -webkit-user-select: none; 86 | -khtml-user-select: none; 87 | -moz-user-select: none; 88 | -ms-user-select: none; 89 | user-select: none; 90 | } 91 | .owl-carousel.owl-loaded { 92 | display: block; 93 | } 94 | .owl-carousel.owl-loading { 95 | opacity: 0; 96 | display: block; 97 | } 98 | .owl-carousel.owl-hidden { 99 | opacity: 0; 100 | } 101 | .owl-carousel .owl-refresh .owl-item { 102 | display: none; 103 | } 104 | .owl-carousel .owl-item { 105 | position: relative; 106 | min-height: 1px; 107 | float: left; 108 | -webkit-backface-visibility: hidden; 109 | -webkit-tap-highlight-color: transparent; 110 | -webkit-touch-callout: none; 111 | -webkit-user-select: none; 112 | -moz-user-select: none; 113 | -ms-user-select: none; 114 | user-select: none; 115 | } 116 | .owl-carousel .owl-item img { 117 | display: block; 118 | width: 100%; 119 | -webkit-transform-style: preserve-3d; 120 | } 121 | .owl-carousel.owl-text-select-on .owl-item { 122 | -webkit-user-select: auto; 123 | -moz-user-select: auto; 124 | -ms-user-select: auto; 125 | user-select: auto; 126 | } 127 | .owl-carousel .owl-grab { 128 | cursor: move; 129 | cursor: -webkit-grab; 130 | cursor: -o-grab; 131 | cursor: -ms-grab; 132 | cursor: grab; 133 | } 134 | .owl-carousel.owl-rtl { 135 | direction: rtl; 136 | } 137 | .owl-carousel.owl-rtl .owl-item { 138 | float: right; 139 | } 140 | 141 | /* No Js */ 142 | .no-js .owl-carousel { 143 | display: block; 144 | } 145 | 146 | /* 147 | * Owl Carousel - Lazy Load Plugin 148 | */ 149 | .owl-carousel .owl-item .owl-lazy { 150 | opacity: 0; 151 | -webkit-transition: opacity 400ms ease; 152 | -moz-transition: opacity 400ms ease; 153 | -ms-transition: opacity 400ms ease; 154 | -o-transition: opacity 400ms ease; 155 | transition: opacity 400ms ease; 156 | } 157 | .owl-carousel .owl-item img { 158 | transform-style: preserve-3d; 159 | } 160 | 161 | /* 162 | * Owl Carousel - Video Plugin 163 | */ 164 | .owl-carousel .owl-video-wrapper { 165 | position: relative; 166 | height: 100%; 167 | background: #000; 168 | } 169 | .owl-carousel .owl-video-play-icon { 170 | position: absolute; 171 | height: 80px; 172 | width: 80px; 173 | left: 50%; 174 | top: 50%; 175 | margin-left: -40px; 176 | margin-top: -40px; 177 | background: url("owl.video.play.png") no-repeat; 178 | cursor: pointer; 179 | z-index: 1; 180 | -webkit-backface-visibility: hidden; 181 | -webkit-transition: scale 100ms ease; 182 | -moz-transition: scale 100ms ease; 183 | -ms-transition: scale 100ms ease; 184 | -o-transition: scale 100ms ease; 185 | transition: scale 100ms ease; 186 | } 187 | .owl-carousel .owl-video-play-icon:hover { 188 | -webkit-transition: scale(1.3, 1.3); 189 | -moz-transition: scale(1.3, 1.3); 190 | -ms-transition: scale(1.3, 1.3); 191 | -o-transition: scale(1.3, 1.3); 192 | transition: scale(1.3, 1.3); 193 | } 194 | .owl-carousel .owl-video-playing .owl-video-tn, 195 | .owl-carousel .owl-video-playing .owl-video-play-icon { 196 | display: none; 197 | } 198 | .owl-carousel .owl-video-tn { 199 | opacity: 0; 200 | height: 100%; 201 | background-position: center center; 202 | background-repeat: no-repeat; 203 | -webkit-background-size: contain; 204 | -moz-background-size: contain; 205 | -o-background-size: contain; 206 | background-size: contain; 207 | -webkit-transition: opacity 400ms ease; 208 | -moz-transition: opacity 400ms ease; 209 | -ms-transition: opacity 400ms ease; 210 | -o-transition: opacity 400ms ease; 211 | transition: opacity 400ms ease; 212 | } 213 | .owl-carousel .owl-video-frame { 214 | position: relative; 215 | z-index: 1; 216 | } 217 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/favicon.ico -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /img/.db_password.php: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /img/actor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/actor.png -------------------------------------------------------------------------------- /img/flags/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/.DS_Store -------------------------------------------------------------------------------- /img/flags/ad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ad.png -------------------------------------------------------------------------------- /img/flags/ae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ae.png -------------------------------------------------------------------------------- /img/flags/af.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/af.png -------------------------------------------------------------------------------- /img/flags/ag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ag.png -------------------------------------------------------------------------------- /img/flags/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ai.png -------------------------------------------------------------------------------- /img/flags/al.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/al.png -------------------------------------------------------------------------------- /img/flags/am.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/am.png -------------------------------------------------------------------------------- /img/flags/an.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/an.png -------------------------------------------------------------------------------- /img/flags/ao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ao.png -------------------------------------------------------------------------------- /img/flags/ar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ar.png -------------------------------------------------------------------------------- /img/flags/as.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/as.png -------------------------------------------------------------------------------- /img/flags/at.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/at.png -------------------------------------------------------------------------------- /img/flags/au.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/au.png -------------------------------------------------------------------------------- /img/flags/aw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/aw.png -------------------------------------------------------------------------------- /img/flags/ax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ax.png -------------------------------------------------------------------------------- /img/flags/az.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/az.png -------------------------------------------------------------------------------- /img/flags/ba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ba.png -------------------------------------------------------------------------------- /img/flags/bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bb.png -------------------------------------------------------------------------------- /img/flags/bd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bd.png -------------------------------------------------------------------------------- /img/flags/be.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/be.png -------------------------------------------------------------------------------- /img/flags/bf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bf.png -------------------------------------------------------------------------------- /img/flags/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bg.png -------------------------------------------------------------------------------- /img/flags/bh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bh.png -------------------------------------------------------------------------------- /img/flags/bi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bi.png -------------------------------------------------------------------------------- /img/flags/bj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bj.png -------------------------------------------------------------------------------- /img/flags/bm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bm.png -------------------------------------------------------------------------------- /img/flags/bn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bn.png -------------------------------------------------------------------------------- /img/flags/bo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bo.png -------------------------------------------------------------------------------- /img/flags/br.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/br.png -------------------------------------------------------------------------------- /img/flags/bs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bs.png -------------------------------------------------------------------------------- /img/flags/bt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bt.png -------------------------------------------------------------------------------- /img/flags/bv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bv.png -------------------------------------------------------------------------------- /img/flags/bw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bw.png -------------------------------------------------------------------------------- /img/flags/by.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/by.png -------------------------------------------------------------------------------- /img/flags/bz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/bz.png -------------------------------------------------------------------------------- /img/flags/ca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ca.png -------------------------------------------------------------------------------- /img/flags/catalonia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/catalonia.png -------------------------------------------------------------------------------- /img/flags/cc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cc.png -------------------------------------------------------------------------------- /img/flags/cd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cd.png -------------------------------------------------------------------------------- /img/flags/cf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cf.png -------------------------------------------------------------------------------- /img/flags/cg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cg.png -------------------------------------------------------------------------------- /img/flags/ch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ch.png -------------------------------------------------------------------------------- /img/flags/ci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ci.png -------------------------------------------------------------------------------- /img/flags/ck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ck.png -------------------------------------------------------------------------------- /img/flags/cl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cl.png -------------------------------------------------------------------------------- /img/flags/cm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cm.png -------------------------------------------------------------------------------- /img/flags/cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cn.png -------------------------------------------------------------------------------- /img/flags/co.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/co.png -------------------------------------------------------------------------------- /img/flags/cr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cr.png -------------------------------------------------------------------------------- /img/flags/cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cs.png -------------------------------------------------------------------------------- /img/flags/cu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cu.png -------------------------------------------------------------------------------- /img/flags/cv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cv.png -------------------------------------------------------------------------------- /img/flags/cx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cx.png -------------------------------------------------------------------------------- /img/flags/cy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cy.png -------------------------------------------------------------------------------- /img/flags/cz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/cz.png -------------------------------------------------------------------------------- /img/flags/de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/de.png -------------------------------------------------------------------------------- /img/flags/dj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/dj.png -------------------------------------------------------------------------------- /img/flags/dk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/dk.png -------------------------------------------------------------------------------- /img/flags/dm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/dm.png -------------------------------------------------------------------------------- /img/flags/do.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/do.png -------------------------------------------------------------------------------- /img/flags/dz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/dz.png -------------------------------------------------------------------------------- /img/flags/ec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ec.png -------------------------------------------------------------------------------- /img/flags/ee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ee.png -------------------------------------------------------------------------------- /img/flags/eg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/eg.png -------------------------------------------------------------------------------- /img/flags/eh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/eh.png -------------------------------------------------------------------------------- /img/flags/en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/en.png -------------------------------------------------------------------------------- /img/flags/england.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/england.png -------------------------------------------------------------------------------- /img/flags/er.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/er.png -------------------------------------------------------------------------------- /img/flags/es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/es.png -------------------------------------------------------------------------------- /img/flags/et.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/et.png -------------------------------------------------------------------------------- /img/flags/europeanunion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/europeanunion.png -------------------------------------------------------------------------------- /img/flags/fam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/fam.png -------------------------------------------------------------------------------- /img/flags/fi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/fi.png -------------------------------------------------------------------------------- /img/flags/fj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/fj.png -------------------------------------------------------------------------------- /img/flags/fk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/fk.png -------------------------------------------------------------------------------- /img/flags/fm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/fm.png -------------------------------------------------------------------------------- /img/flags/fo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/fo.png -------------------------------------------------------------------------------- /img/flags/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/fr.png -------------------------------------------------------------------------------- /img/flags/ga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ga.png -------------------------------------------------------------------------------- /img/flags/gb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gb.png -------------------------------------------------------------------------------- /img/flags/gd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gd.png -------------------------------------------------------------------------------- /img/flags/ge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ge.png -------------------------------------------------------------------------------- /img/flags/gf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gf.png -------------------------------------------------------------------------------- /img/flags/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gh.png -------------------------------------------------------------------------------- /img/flags/gi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gi.png -------------------------------------------------------------------------------- /img/flags/gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gl.png -------------------------------------------------------------------------------- /img/flags/gm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gm.png -------------------------------------------------------------------------------- /img/flags/gn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gn.png -------------------------------------------------------------------------------- /img/flags/gp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gp.png -------------------------------------------------------------------------------- /img/flags/gq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gq.png -------------------------------------------------------------------------------- /img/flags/gr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gr.png -------------------------------------------------------------------------------- /img/flags/gs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gs.png -------------------------------------------------------------------------------- /img/flags/gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gt.png -------------------------------------------------------------------------------- /img/flags/gu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gu.png -------------------------------------------------------------------------------- /img/flags/gw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gw.png -------------------------------------------------------------------------------- /img/flags/gy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/gy.png -------------------------------------------------------------------------------- /img/flags/hk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/hk.png -------------------------------------------------------------------------------- /img/flags/hm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/hm.png -------------------------------------------------------------------------------- /img/flags/hn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/hn.png -------------------------------------------------------------------------------- /img/flags/hr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/hr.png -------------------------------------------------------------------------------- /img/flags/ht.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ht.png -------------------------------------------------------------------------------- /img/flags/hu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/hu.png -------------------------------------------------------------------------------- /img/flags/id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/id.png -------------------------------------------------------------------------------- /img/flags/ie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ie.png -------------------------------------------------------------------------------- /img/flags/il.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/il.png -------------------------------------------------------------------------------- /img/flags/in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/in.png -------------------------------------------------------------------------------- /img/flags/io.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/io.png -------------------------------------------------------------------------------- /img/flags/iq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/iq.png -------------------------------------------------------------------------------- /img/flags/ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ir.png -------------------------------------------------------------------------------- /img/flags/is.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/is.png -------------------------------------------------------------------------------- /img/flags/it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/it.png -------------------------------------------------------------------------------- /img/flags/jm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/jm.png -------------------------------------------------------------------------------- /img/flags/jo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/jo.png -------------------------------------------------------------------------------- /img/flags/jp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/jp.png -------------------------------------------------------------------------------- /img/flags/ke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ke.png -------------------------------------------------------------------------------- /img/flags/kg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/kg.png -------------------------------------------------------------------------------- /img/flags/kh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/kh.png -------------------------------------------------------------------------------- /img/flags/ki.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ki.png -------------------------------------------------------------------------------- /img/flags/km.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/km.png -------------------------------------------------------------------------------- /img/flags/kn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/kn.png -------------------------------------------------------------------------------- /img/flags/kp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/kp.png -------------------------------------------------------------------------------- /img/flags/kr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/kr.png -------------------------------------------------------------------------------- /img/flags/kw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/kw.png -------------------------------------------------------------------------------- /img/flags/ky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ky.png -------------------------------------------------------------------------------- /img/flags/kz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/kz.png -------------------------------------------------------------------------------- /img/flags/la.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/la.png -------------------------------------------------------------------------------- /img/flags/lb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/lb.png -------------------------------------------------------------------------------- /img/flags/lc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/lc.png -------------------------------------------------------------------------------- /img/flags/li.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/li.png -------------------------------------------------------------------------------- /img/flags/lk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/lk.png -------------------------------------------------------------------------------- /img/flags/lr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/lr.png -------------------------------------------------------------------------------- /img/flags/ls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ls.png -------------------------------------------------------------------------------- /img/flags/lt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/lt.png -------------------------------------------------------------------------------- /img/flags/lu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/lu.png -------------------------------------------------------------------------------- /img/flags/lv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/lv.png -------------------------------------------------------------------------------- /img/flags/ly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ly.png -------------------------------------------------------------------------------- /img/flags/ma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ma.png -------------------------------------------------------------------------------- /img/flags/mc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mc.png -------------------------------------------------------------------------------- /img/flags/md.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/md.png -------------------------------------------------------------------------------- /img/flags/me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/me.png -------------------------------------------------------------------------------- /img/flags/mg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mg.png -------------------------------------------------------------------------------- /img/flags/mh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mh.png -------------------------------------------------------------------------------- /img/flags/mk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mk.png -------------------------------------------------------------------------------- /img/flags/ml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ml.png -------------------------------------------------------------------------------- /img/flags/mm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mm.png -------------------------------------------------------------------------------- /img/flags/mn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mn.png -------------------------------------------------------------------------------- /img/flags/mo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mo.png -------------------------------------------------------------------------------- /img/flags/mp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mp.png -------------------------------------------------------------------------------- /img/flags/mq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mq.png -------------------------------------------------------------------------------- /img/flags/mr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mr.png -------------------------------------------------------------------------------- /img/flags/ms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ms.png -------------------------------------------------------------------------------- /img/flags/mt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mt.png -------------------------------------------------------------------------------- /img/flags/mu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mu.png -------------------------------------------------------------------------------- /img/flags/mv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mv.png -------------------------------------------------------------------------------- /img/flags/mw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mw.png -------------------------------------------------------------------------------- /img/flags/mx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mx.png -------------------------------------------------------------------------------- /img/flags/my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/my.png -------------------------------------------------------------------------------- /img/flags/mz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/mz.png -------------------------------------------------------------------------------- /img/flags/na.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/na.png -------------------------------------------------------------------------------- /img/flags/nc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/nc.png -------------------------------------------------------------------------------- /img/flags/ne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ne.png -------------------------------------------------------------------------------- /img/flags/nf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/nf.png -------------------------------------------------------------------------------- /img/flags/ng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ng.png -------------------------------------------------------------------------------- /img/flags/ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ni.png -------------------------------------------------------------------------------- /img/flags/nl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/nl.png -------------------------------------------------------------------------------- /img/flags/no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/no.png -------------------------------------------------------------------------------- /img/flags/np.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/np.png -------------------------------------------------------------------------------- /img/flags/nr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/nr.png -------------------------------------------------------------------------------- /img/flags/nu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/nu.png -------------------------------------------------------------------------------- /img/flags/nz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/nz.png -------------------------------------------------------------------------------- /img/flags/om.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/om.png -------------------------------------------------------------------------------- /img/flags/pa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pa.png -------------------------------------------------------------------------------- /img/flags/pe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pe.png -------------------------------------------------------------------------------- /img/flags/pf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pf.png -------------------------------------------------------------------------------- /img/flags/pg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pg.png -------------------------------------------------------------------------------- /img/flags/ph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ph.png -------------------------------------------------------------------------------- /img/flags/pk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pk.png -------------------------------------------------------------------------------- /img/flags/pl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pl.png -------------------------------------------------------------------------------- /img/flags/pm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pm.png -------------------------------------------------------------------------------- /img/flags/pn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pn.png -------------------------------------------------------------------------------- /img/flags/pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pr.png -------------------------------------------------------------------------------- /img/flags/ps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ps.png -------------------------------------------------------------------------------- /img/flags/pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pt.png -------------------------------------------------------------------------------- /img/flags/pw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/pw.png -------------------------------------------------------------------------------- /img/flags/py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/py.png -------------------------------------------------------------------------------- /img/flags/qa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/qa.png -------------------------------------------------------------------------------- /img/flags/re.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/re.png -------------------------------------------------------------------------------- /img/flags/ro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ro.png -------------------------------------------------------------------------------- /img/flags/rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/rs.png -------------------------------------------------------------------------------- /img/flags/ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ru.png -------------------------------------------------------------------------------- /img/flags/rw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/rw.png -------------------------------------------------------------------------------- /img/flags/sa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sa.png -------------------------------------------------------------------------------- /img/flags/sb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sb.png -------------------------------------------------------------------------------- /img/flags/sc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sc.png -------------------------------------------------------------------------------- /img/flags/scotland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/scotland.png -------------------------------------------------------------------------------- /img/flags/sd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sd.png -------------------------------------------------------------------------------- /img/flags/se.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/se.png -------------------------------------------------------------------------------- /img/flags/sg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sg.png -------------------------------------------------------------------------------- /img/flags/sh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sh.png -------------------------------------------------------------------------------- /img/flags/si.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/si.png -------------------------------------------------------------------------------- /img/flags/sj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sj.png -------------------------------------------------------------------------------- /img/flags/sk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sk.png -------------------------------------------------------------------------------- /img/flags/sl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sl.png -------------------------------------------------------------------------------- /img/flags/sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sm.png -------------------------------------------------------------------------------- /img/flags/sn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sn.png -------------------------------------------------------------------------------- /img/flags/so.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/so.png -------------------------------------------------------------------------------- /img/flags/sr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sr.png -------------------------------------------------------------------------------- /img/flags/st.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/st.png -------------------------------------------------------------------------------- /img/flags/sv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sv.png -------------------------------------------------------------------------------- /img/flags/sy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sy.png -------------------------------------------------------------------------------- /img/flags/sz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/sz.png -------------------------------------------------------------------------------- /img/flags/tc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tc.png -------------------------------------------------------------------------------- /img/flags/td.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/td.png -------------------------------------------------------------------------------- /img/flags/tf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tf.png -------------------------------------------------------------------------------- /img/flags/tg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tg.png -------------------------------------------------------------------------------- /img/flags/th.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/th.png -------------------------------------------------------------------------------- /img/flags/tj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tj.png -------------------------------------------------------------------------------- /img/flags/tk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tk.png -------------------------------------------------------------------------------- /img/flags/tl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tl.png -------------------------------------------------------------------------------- /img/flags/tm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tm.png -------------------------------------------------------------------------------- /img/flags/tn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tn.png -------------------------------------------------------------------------------- /img/flags/to.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/to.png -------------------------------------------------------------------------------- /img/flags/tr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tr.png -------------------------------------------------------------------------------- /img/flags/tt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tt.png -------------------------------------------------------------------------------- /img/flags/tv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tv.png -------------------------------------------------------------------------------- /img/flags/tw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tw.png -------------------------------------------------------------------------------- /img/flags/tz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/tz.png -------------------------------------------------------------------------------- /img/flags/ua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ua.png -------------------------------------------------------------------------------- /img/flags/ug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ug.png -------------------------------------------------------------------------------- /img/flags/um.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/um.png -------------------------------------------------------------------------------- /img/flags/us.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/us.png -------------------------------------------------------------------------------- /img/flags/uy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/uy.png -------------------------------------------------------------------------------- /img/flags/uz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/uz.png -------------------------------------------------------------------------------- /img/flags/va.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/va.png -------------------------------------------------------------------------------- /img/flags/vc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/vc.png -------------------------------------------------------------------------------- /img/flags/ve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ve.png -------------------------------------------------------------------------------- /img/flags/vg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/vg.png -------------------------------------------------------------------------------- /img/flags/vi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/vi.png -------------------------------------------------------------------------------- /img/flags/vn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/vn.png -------------------------------------------------------------------------------- /img/flags/vu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/vu.png -------------------------------------------------------------------------------- /img/flags/wales.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/wales.png -------------------------------------------------------------------------------- /img/flags/wf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/wf.png -------------------------------------------------------------------------------- /img/flags/ws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ws.png -------------------------------------------------------------------------------- /img/flags/ye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/ye.png -------------------------------------------------------------------------------- /img/flags/yt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/yt.png -------------------------------------------------------------------------------- /img/flags/za.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/za.png -------------------------------------------------------------------------------- /img/flags/zm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/zm.png -------------------------------------------------------------------------------- /img/flags/zw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/flags/zw.png -------------------------------------------------------------------------------- /img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /img/help/synology-context-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/help/synology-context-icon.png -------------------------------------------------------------------------------- /img/help/synology-file-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/help/synology-file-icon.png -------------------------------------------------------------------------------- /img/help/synology_webdav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/help/synology_webdav.png -------------------------------------------------------------------------------- /img/notfound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/img/notfound.png -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | run(); 35 | -------------------------------------------------------------------------------- /js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /js/unveil.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Unveil 3 | * A very lightweight jQuery plugin to lazy load images 4 | * http://luis-almeida.github.com/unveil 5 | * 6 | * Licensed under the MIT license. 7 | * Copyright 2013 Luís Almeida 8 | * https://github.com/luis-almeida 9 | */ 10 | 11 | ;(function($) { 12 | 13 | $.fn.unveil = function(threshold, callback) { 14 | 15 | var $w = $(window), 16 | th = threshold || 0, 17 | retina = window.devicePixelRatio > 1, 18 | attrib = retina? "data-src-retina" : "data-src", 19 | images = this, 20 | loaded; 21 | 22 | this.one("unveil", function() { 23 | var source = this.getAttribute(attrib); 24 | source = source || this.getAttribute("data-src"); 25 | if (source) { 26 | this.setAttribute("src", source); 27 | if (typeof callback === "function") callback.call(this); 28 | } 29 | }); 30 | 31 | function unveil() { 32 | var inview = images.filter(function() { 33 | var $e = $(this); 34 | if ($e.is(":hidden")) return; 35 | 36 | var wt = $w.scrollTop(), 37 | wb = wt + $w.height(), 38 | et = $e.offset().top, 39 | eb = et + $e.height(); 40 | 41 | return eb >= wt - th && et <= wb + th; 42 | }); 43 | 44 | loaded = inview.trigger("unveil"); 45 | images = images.not(loaded); 46 | } 47 | 48 | $w.on("scroll.unveil resize.unveil lookup.unveil", unveil); 49 | 50 | unveil(); 51 | 52 | return this; 53 | 54 | }; 55 | 56 | })(window.jQuery || window.Zepto); 57 | -------------------------------------------------------------------------------- /js/video-js.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/js/video-js.swf -------------------------------------------------------------------------------- /js/videojs.vlc.min.js: -------------------------------------------------------------------------------- 1 | videojs.Vlc=videojs.MediaTechController.extend({init:function(e,t,i){videojs.MediaTechController.call(this,e,t,i);var r=t.source,o=e.id()+"_vlc_api",n=this;this.player_=e;var s=videojs.util.mergeOptions({animationatstart:"true",transparentatstart:"true",windowless:"true",controls:"false",bgcolor:"#000000",autostart:e.options.autoplay?"true":"false",allowfullscreen:"true",text:"Video.js VLC plug-in"},t.params);r&&(s.source=r.src,this.ready(function(){this.setSrc(r.src)}));var l=videojs.util.mergeOptions({id:o,name:o,"class":"vjs-tech"},t.attributes),a=t.parentEl,c=this.el_=videojs.Component.prototype.createEl("div",{id:e.id()+"temp_vlc"});a.firstChild?a.insertBefore(c,a.firstChild):a.appendChild(c),t.startTime&&this.ready(function(){this.load(),this.play(),this.currentTime(t.startTime)}),e.ready(function(){}),this.el_=videojs.Vlc.embed(c,s,l),this.el_.tech=this,videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerOpening",function(){e.trigger("loadstart")}),videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerBuffering",function(){e.trigger("loadeddata"),e.trigger("volumechange")}),videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerPlaying",function(){e.trigger("play"),e.trigger("playing")}),videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerPaused",function(){e.trigger("pause")}),videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerStopped",function(){e.trigger("pause"),e.trigger("ended")}),videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerEndReached",function(){e.trigger("pause"),e.trigger("ended")}),videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerTimeChanged",function(){e.trigger("timeupdate")}),videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerPositionChanged",function(){e.trigger("progress")}),videojs.Vlc.registerEvent(this.getApi(),"MediaPlayerLengthChanged",function(){e.trigger("durationchange")}),setTimeout(function(){n.triggerReady()},100)}}),videojs.Vlc.prototype.params=[],videojs.Vlc.prototype.dispose=function(){this.el_&&this.el_.parentNode.removeChild(this.el_),videojs.MediaTechController.prototype.dispose.call(this)},videojs.Vlc.prototype.src=function(e){return void 0===e?this.currentSrc():this.setSrc(e)},videojs.Vlc.prototype.setSrc=function(e){e=videojs.Vlc.getAbsoluteURL(e),this.getApi().playlist.items.clear(),this.getApi().playlist.add(e)},videojs.Vlc.prototype.currentSrc=function(){return this.currentSource_?this.currentSource_.src:this.getApi().playlist.items[this.getApi().playlist.currentItem]},videojs.Vlc.prototype.load=function(){},videojs.Vlc.prototype.poster=function(){this.el_.vjs_getProperty("poster")},videojs.Vlc.prototype.setPoster=function(){},videojs.Vlc.prototype.play=function(){this.getApi().playlist.play()},videojs.Vlc.prototype.ended=function(){var e=this.getApi().input.state;return 6===e||7===e},videojs.Vlc.prototype.pause=function(){this.getApi().playlist.pause()},videojs.Vlc.prototype.paused=function(){var e=this.getApi().input.state;return 4===e||6===e},videojs.Vlc.prototype.currentTime=function(){return this.getApi().input.time/1e3},videojs.Vlc.prototype.setCurrentTime=function(e){this.getApi().input.time=1e3*e},videojs.Vlc.prototype.duration=function(){return this.getApi().input.length/1e3},videojs.Vlc.prototype.buffered=function(){return[]},videojs.Vlc.prototype.volume=function(){return this.getApi().audio.volume/100},videojs.Vlc.prototype.setVolume=function(e){e&&(this.getApi().audio.volume=100*e)},videojs.Vlc.prototype.muted=function(){return this.getApi().audio.mute},videojs.Vlc.prototype.setMuted=function(e){this.getApi().audio.mute.mute=e},videojs.Vlc.prototype.supportsFullScreen=function(){return!0},videojs.Vlc.prototype.enterFullScreen=function(){this.getApi().video.fullscreen=!0,this.player_.trigger("fullscreenchange")},videojs.Vlc.prototype.exitFullScreen=function(){this.getApi().video.fullscreen=!1,this.player_.trigger("fullscreenchange")},videojs.Vlc.prototype.getApi=function(){return this.el_},videojs.Vlc.registerEvent=function(e,t,i){e&&(e.attachEvent?e.attachEvent(t,i):e.addEventListener?e.addEventListener(t,i,!1):e["on"+t]=i)},videojs.Vlc.unregisterEvent=function(e,t,i){e&&(e.detachEvent?e.detachEvent(t,i):e.removeEventListener?e.removeEventListener(t,i,!1):e["on"+t]=null)},videojs.Vlc.embed=function(e,t,i){{var r=videojs.Vlc.getEmbedCode(t,i),o=videojs.Component.prototype.createEl("div",{innerHTML:r}).childNodes[0];e.parentNode}return e.parentNode.replaceChild(o,e),o},videojs.Vlc.getEmbedCode=function(e,t){var i,r,o="",n="";if(window.ActiveXObject){i='';for(r in t)n+=r+'="'+t[r]+'" ';return i+n+">"+o+""}i='"},videojs.Vlc.getAbsoluteURL=function(e){return e.match(/^https?:\/\//)||(e=videojs.Component.prototype.createEl("div",{innerHTML:'x'}).firstChild.href),e},videojs.Vlc.isSupported=function(){var e;if(window.ActiveXObject)try{e=new window.ActiveXObject("VideoLAN.VLCPlugin.2")}catch(t){}else if(navigator.plugins&&navigator.mimeTypes.length>0){var i="VLC";if(navigator.plugins&&navigator.plugins.length>0)for(var r=0;r /var/www/digest_temp 24 | cat /var/www/digest_temp > "$HTDIGEST_FILE" 25 | rm /var/www/digest_temp 26 | fi 27 | 28 | # build an htdigest appropriate line, and tack it onto the file 29 | echo "$username:$AUTH_REALM:${htdigest_hash:0:32}" >> "$HTDIGEST_FILE" 30 | echo "$rand_pw" 31 | else 32 | echo "ERROR: Expects two arguments. (digest_file and username)" 33 | fi 34 | -------------------------------------------------------------------------------- /scripts/delUser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | username=$2 4 | HTDIGEST_FILE=$1 5 | 6 | AUTH_REALM=Media 7 | 8 | 9 | if [ "$#" -eq 2 ]; then 10 | if [ -f "$HTDIGEST_FILE" ]; then 11 | sed -i "/$username:Media/d" "$HTDIGEST_FILE" 12 | fi 13 | else 14 | echo "ERROR: Expects two arguments. (digest_file and username)" 15 | fi 16 | -------------------------------------------------------------------------------- /setup/db.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazcod/Gunther/9e275b6f87f66a31888cdde1c884c6d207819b43/setup/db.sql -------------------------------------------------------------------------------- /setup/setupDownloaders.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run this after setup.sh 4 | 5 | adduser media 6 | usermod -a -G www-data media 7 | mkdir /home/media 8 | 9 | # CouchPotato 10 | git clone https://github.com/ruudburger/couchpotatoserver /home/media/couchpotato 11 | cp /home/media/couchpotato/init/ubuntu /etc/init.d/couchpotato 12 | chmod +x /etc/init.d/couchpotato 13 | cp /home/media/couchpotato/init/ubuntu.default /etc/default/couchpotato 14 | mkdir /home/media/.couchpotato 15 | sed -i 's/CP_HOME=/CP_HOME=\/home\/media\/couchpotato\//g' /etc/default/couchpotato 16 | sed -i 's/CP_USER=/CP_USER=media/g' /etc/default/couchpotato 17 | #echo "HOST=127.0.0.1" >> /etc/default/couchpotato DOES NOT WORK 18 | echo "PORT=5050" >> /etc/default/couchpotato 19 | echo "SSD_OPTS=--group=media" >> /etc/default/couchpotato 20 | echo "CP_PIDFILE=/home/media/couchpotato/cp.pid" >> /etc/default/couchpotato 21 | echo "CP_DATA=/home/media/.couchpotato/" >> /etc/default/couchpotato 22 | update-rc.d couchpotato defaults 23 | 24 | 25 | # Sickbeard 26 | apt-get install python-cheetah 27 | git clone https://github.com/SiCKRAGETV/SickRage /home/media/sickrage 28 | cp /home/media/sickrage/runscripts/init.debian /etc/init.d/sickrage 29 | chmod +x /etc/init.d/sickrage 30 | mkdir /home/media/.sickrage 31 | echo "SR_USER=media" > /etc/default/sickrage 32 | echo "SR_HOME=/home/media/sickrage" >> /etc/default/sickrage 33 | echo "SR_OPTS=\"-p 8081\"" >> /etc/default/sickrage 34 | echo "SR_GROUP=media" >> /etc/default/sickrage 35 | echo "SR_DATA=/home/media/.sickrage" >> /etc/default/sickrage 36 | echo "SR_PIDFILE=/home/media/sickrage/sr.pid" >> /etc/default/sickrage 37 | #TODO: HOST 38 | update-rc.d sickrage defaults 39 | 40 | # Sabnzbd 41 | r=$(grep "ppa.launchpad.net/jcfp/ppa/ubuntu precise main" /etc/apt/sources.list) 42 | if [ -z "$r" ]; then 43 | echo "deb http://ppa.launchpad.net/jcfp/ppa/ubuntu precise main" | tee -a /etc/apt/sources.list 44 | apt-key adv --keyserver hkp://pool.sks-keyservers.net:11371 --recv-keys 0x98703123E0F52B2BE16D586EF13930B14BB9F05F 45 | fi 46 | apt-get update 47 | apt-get upgrade -y 48 | apt-get install -y --force-yes sabnzbdplus 49 | mkdir /home/media/sabnzbdplus 50 | sed -i 's/USER=/USER=media/g' /etc/default/sabnzbdplus 51 | sed -i 's/CONFIG=/CONFIG=\/home\/media\/sabnzbdplus\/settings/g' /etc/default/sabnzbdplus 52 | sed -i 's/HOST=/HOST=127.0.0.1/g' /etc/default/sabnzbdplus 53 | sed -i 's/PORT=/PORT=8080/g' /etc/default/sabnzbdplus 54 | #sed -i 's/EXTRAOPTS=/EXTRAOPTS="--group=media"/g' /etc/default/sabnzbdplus 55 | update-rc.d sabnzbdplus defaults 56 | 57 | # Headphones; TODO 58 | git clone https://github.com/rembo10/headphones /home/media/headphones 59 | cp /home/media/headphones/init-scripts/init.ubuntu /etc/init.d/headphones 60 | chmod +x /etc/init.d/headphones 61 | echo "HP_USER=media" > /etc/default/headphones 62 | echo "HP_HOME=/home/media/headphones" > /etc/default/headphones 63 | echo "HP_PORT=/home/media/headphones" > /etc/default/headphones 64 | echo "SSD_OPTS=--group=media" > /etc/default/headphones 65 | #Host is localhost by default 66 | update-rc.d headphones defaults 67 | 68 | chown media:www-data -R /home/media 69 | service couchpotato start 70 | service sickrage start 71 | service sabnzbdplus start 72 | service headphones start 73 | -------------------------------------------------------------------------------- /system/Controller.php: -------------------------------------------------------------------------------- 1 | parseUri(); 17 | } 18 | 19 | private function parseUri() 20 | { 21 | // strip the controllerfile out of the scriptname 22 | $scriptprefix = str_replace(self::CONTROLLERFILE, '', $_SERVER['SCRIPT_NAME']); 23 | $uri = str_replace(self::CONTROLLERFILE, '', $_SERVER['REQUEST_URI']); 24 | 25 | $n = strpos($uri, "?lang="); 26 | if ($n > 0){ 27 | $_SESSION['lang'] = substr($uri, $n + 6, $n + 6 + 2); 28 | $uri = substr($uri, 0, $n); 29 | } 30 | 31 | // get the part of the uri, starting from the position after the scriptprefix 32 | $path = substr($uri, strlen($scriptprefix)); 33 | 34 | // strip non-alphanumeric characters out of the path 35 | $path = preg_replace('/[^a-zA-Z0-9]\//', "", $path); 36 | 37 | // trim the path for / 38 | $path = trim($path, '/'); 39 | 40 | // explode the $path into three parts to get the controller, action and parameters 41 | // the @-sign is used to supress errors when the function after it fails 42 | @list($controller, $action, $params) = explode("/", $path, 3); 43 | 44 | $this->setController($controller); 45 | if (isset($action)) { 46 | $this->setAction($action); 47 | if (isset($params)) { 48 | $this->setParams(explode("/", $params)); 49 | } 50 | } 51 | } 52 | 53 | private function setController($controller) 54 | { 55 | $controller = ($controller) ? $controller : self::DEFAULT_CONTROLLER; 56 | 57 | $controllerfile = APPLICATION_PATH . self::CONTROLLERPATH . ucfirst(strtolower($controller)) . '.php'; 58 | 59 | // check if controller file exists 60 | if (file_exists($controllerfile)) { 61 | require_once($controllerfile); 62 | $this->controller = $controller; 63 | } else { 64 | error_log("Controller '$controller' not found."); 65 | header ("HTTP/1.1 404 Not Found"); 66 | exit; 67 | } 68 | 69 | return $this; 70 | } 71 | 72 | public function getController() 73 | { 74 | return $this->controller; 75 | } 76 | 77 | public static function sanitize($input) 78 | { 79 | if (is_array($input)) { 80 | for($i=0;$icontroller, $action)) { 95 | error_log("Action '$action' does not exist in class '$this->controller'."); 96 | header ("HTTP/1.1 404 Not Found"); 97 | exit; 98 | } else { 99 | $this->action = $action; 100 | } 101 | 102 | return $this; 103 | } 104 | 105 | private function setParams(array $params) 106 | { 107 | // loop through each element of the parameters to urldecode it 108 | array_walk($params, create_function('&$val', '$val = urldecode($val);')); 109 | 110 | // some XSS filtering 111 | $this->params = self::sanitize($params); 112 | return $this; 113 | } 114 | 115 | public function run() 116 | { 117 | 118 | // checking the parameter count, using Reflection (http://www.php.net/reflection) 119 | $reflector = new ReflectionClass($this->controller); 120 | $method = $reflector->getMethod($this->action); 121 | $parameters = $method->getNumberOfRequiredParameters(); 122 | 123 | if (($parameters) > count($this->params)) { 124 | error_log("Action '$this->action' in class '$this->controller' expects $parameters mandatory parameter(s), you only provided " . count($this->params) . "."); 125 | header ("HTTP/1.1 404 Not Found"); 126 | exit; 127 | } 128 | 129 | // create an instance of the controller as an object 130 | $controller = new $this->controller(); 131 | 132 | // call the method based on $this->action and the params 133 | call_user_func_array(array($controller, $this->action), $this->params); 134 | } 135 | } -------------------------------------------------------------------------------- /system/Core_controller.php: -------------------------------------------------------------------------------- 1 | template = new Template(); 11 | $this->template->flashmessage = $this->getFlashMessage(); 12 | 13 | $this->form = Form::getInstance(); 14 | 15 | global $settings; 16 | $this->settings = $settings; 17 | 18 | if (!isset($_SESSION['lang'])){ 19 | $_SESSION['lang'] = $settings['DEFAULT_LANG']; 20 | } 21 | 22 | include(APPLICATION_PATH . 'languages/lang.'.$_SESSION['lang'].'.php'); 23 | $this->lang = getLang(); 24 | $this->template->lang = $this->lang; 25 | 26 | include(APPLICATION_PATH . 'includes/MediaModel.php'); 27 | $this->mediamodel = new MediaModel($settings); 28 | $this->template->mediamodel = $this->mediamodel; 29 | 30 | include(APPLICATION_PATH . 'includes/Password.php'); 31 | 32 | if ($protected == true){ 33 | $this->checkPrivilege(); 34 | } 35 | 36 | $this->user_m = Load::model('user_m'); 37 | $this->user_m->settings = $this->settings; 38 | 39 | if (isset($_SESSION['user'])){ 40 | $this->user = $this->user_m->getUserById($_SESSION['user']); 41 | $this->template->user = clone $this->user; 42 | } 43 | 44 | $this->menu_m = Load::model('menu_m'); 45 | $this->template->menuitems = $this->menu_m->getMenu($this->user, $this->lang); 46 | 47 | $this->langs_m = Load::model('langs_m'); 48 | $this->template->langs = $this->langs_m->getLangs(); 49 | } 50 | 51 | public function checkPrivilege() 52 | { 53 | if (!isset($_SESSION['user'])){ 54 | $this->setFlashmessage($this->lang['accessdenied'], 'danger'); 55 | $this->redirect('home/index'); 56 | return false; 57 | } else { 58 | return true; 59 | } 60 | } 61 | 62 | public function isAdminUser(){ 63 | if ($this->user != false and $this->user->role == 1){ 64 | return true; 65 | } else { 66 | return false; 67 | } 68 | } 69 | 70 | public function __set($name, $value) 71 | { 72 | $this->data[$name] = $value; 73 | } 74 | 75 | public function __get($name) 76 | { 77 | if (array_key_exists($name, $this->data)) { 78 | return $this->data[$name]; 79 | } 80 | return false; 81 | } 82 | 83 | public function setFlashmessage($message, $status = 'success') 84 | { 85 | $flashmessage = new stdClass(); 86 | $flashmessage->status = $status; 87 | $flashmessage->message = $message; 88 | 89 | $_SESSION['flashmessage'] = $flashmessage; 90 | 91 | return $this; 92 | } 93 | 94 | public function setCurrentFlashmessage($message, $status = 'success') 95 | { 96 | $this->template->flashmessage = new stdClass(); 97 | $this->template->flashmessage->status = $status; 98 | $this->template->flashmessage->message = $message; 99 | 100 | return $this; 101 | } 102 | 103 | public function getFlashMessage() 104 | { 105 | if (isset($_SESSION['flashmessage'])) { 106 | $flashmessage = $_SESSION['flashmessage']; 107 | unset($_SESSION['flashmessage']); 108 | } else { 109 | $flashmessage = false; 110 | } 111 | 112 | return $flashmessage; 113 | } 114 | 115 | public function redirect($newlocation = '') 116 | { 117 | if (!headers_sent($filename, $linenum)) { 118 | header('Location: ' . URL::base_uri($newlocation)); 119 | exit(); 120 | } else { 121 | echo "Headers already sent in $filename on line $linenum\n"; 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /system/Core_db.php: -------------------------------------------------------------------------------- 1 | db = DB::getInstance(); 9 | global $settings; 10 | $this->settings = $settings; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /system/DB.php: -------------------------------------------------------------------------------- 1 | db = new PDO('sqlite:' . $settings['DB_LOC']); 25 | // set the error reporting attribute 26 | $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 27 | 28 | //error_log('Checking ' . $settings['DB_LOC'] . ' = ' . var_dump(file_exists($settings['DB_LOC']))); 29 | if (! $this->testDB()) { 30 | error_log('No active database found, creating at ' . $settings['DB_LOC']); 31 | $this->needSetup = true; 32 | $this->setup(); 33 | } 34 | } catch(PDOException $e) { 35 | error_log($e->getMessage()); 36 | } 37 | } 38 | 39 | private function testDB() 40 | { 41 | global $settings; 42 | return (filesize($settings['DB_LOC']) != 0); 43 | } 44 | 45 | private function setup() 46 | { 47 | // new database, so setup 48 | // TODO: separate file? 49 | $queries = array( 50 | "CREATE TABLE IF NOT EXISTS roles (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(10) NOT NULL);", 51 | "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, login VARCHAR(20) NOT NULL, pass VARCHAR(32) NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL, role SMALLINT REFERENCES roles(id));", 52 | "CREATE TABLE IF NOT EXISTS req_movies (date DATESTR, file TEXT NOT NULL, user SMALLINT REFERENCES users(id), ip VARCHAR(39), msec DOUBLE);", 53 | "CREATE TABLE IF NOT EXISTS version (version VARCHAR(10) NOT NULL);", 54 | "CREATE TABLE IF NOT EXISTS static_cache (id INTEGER PRIMARY KEY AUTOINCREMENT, type VARCHAR(10) NOT NULL, path TEXT NOT NULL, url TEXT NOT NULL);", 55 | "CREATE TABLE IF NOT EXISTS movies (id INTEGER PRIMARY KEY AUTOINCREMENT, tvdbid INT NOT NULL, name VARCHAR(30) NOT NULL, description TEXT NOT NULL, quality VARCHAR(15), release VARCHAR(20));", 56 | 57 | "INSERT INTO version(version) VALUES ('1.0.0');", 58 | "INSERT INTO roles(id, name) VALUES (0, 'Administrator'), (1, 'Regular user');", 59 | "INSERT INTO users(id, login, name, email, pass, role) VALUES (0,'admin','admin','admin@localhost.local', 'admin:Media:2b952a0aecefebc7facc12d56a3519af', 1);" 60 | ); 61 | foreach ($queries as $query){ 62 | $this->query($query); 63 | } 64 | } 65 | 66 | public function query($sql, $arguments = array()) 67 | { 68 | if (!is_array($arguments)) { 69 | $arguments = array($arguments); 70 | } 71 | 72 | try { 73 | $this->stmt = $this->db->prepare($sql); 74 | $this->stmt->execute($arguments); 75 | $this->stmt->setFetchMode(PDO::FETCH_ASSOC); 76 | } catch(PDOException $e) { 77 | error_log($e->getMessage()); 78 | } 79 | 80 | return $this; 81 | } 82 | 83 | public function getResult() 84 | { 85 | $result = array(); 86 | 87 | if ($this->stmt) { 88 | // as long as there are rows, add them to the data-output array 89 | while ($row = $this->stmt->fetchObject()) { 90 | $result[] = $row; 91 | } 92 | } 93 | 94 | return $result; 95 | } 96 | 97 | public function getRow() 98 | { 99 | $row = false; 100 | 101 | if ($this->stmt) { 102 | $row = $this->stmt->fetchObject(); 103 | } 104 | 105 | return $row; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /system/Form.php: -------------------------------------------------------------------------------- 1 | safe['get'] = new stdClass(); 19 | $this->safe['post'] = new stdClass(); 20 | 21 | $this->doSafeGet(); 22 | $this->doSafePost(); 23 | } 24 | 25 | private function doSafePost() 26 | { 27 | foreach($_POST as $key=>$value) { 28 | $this->safe['post']->$key = Controller::sanitize($value); 29 | } 30 | } 31 | 32 | private function doSafeGet() 33 | { 34 | foreach($_GET as $key=>$value) { 35 | $this->safe['get']->$key = Controller::sanitize($value); 36 | } 37 | } 38 | 39 | public function getGet($key = false) 40 | { 41 | if (!$key) { 42 | $return = $this->safe['get']; 43 | } else if (is_array($key)) { 44 | $return = new stdClass(); 45 | foreach ($key as $value) { 46 | $return->$value = $this->getGet($value); 47 | } 48 | } else if (isset($this->safe['get']->$key)) { 49 | $return = $this->safe['get']->$key; 50 | } else { 51 | $return = false; 52 | } 53 | 54 | return $return; 55 | } 56 | 57 | public function getPost($key = false) 58 | { 59 | if (!$key) { 60 | $return = $this->safe['post']; 61 | } else if (is_array($key)) { 62 | $return = new stdClass(); 63 | foreach ($key as $value) { 64 | $return->$value = $this->getPost($value); 65 | } 66 | } else if (isset($this->safe['post']->$key)) { 67 | $return = $this->safe['post']->$key; 68 | } else { 69 | $return = false; 70 | } 71 | 72 | return $return; 73 | } 74 | 75 | public function isFieldMSGset() 76 | { 77 | return !(empty($this->fieldmessage)); 78 | } 79 | 80 | public function getFieldMessage($key) 81 | { 82 | if (isset($this->fieldmessage[$key]['message'])) { 83 | $message = $this->fieldmessage[$key]['message']; 84 | } else { 85 | $message = false; 86 | } 87 | 88 | return $message; 89 | } 90 | 91 | public function getFieldStatus($key) 92 | { 93 | if (isset($this->fieldmessage[$key]['status'])) { 94 | $status = $this->fieldmessage[$key]['status']; 95 | } else { 96 | $status = false; 97 | } 98 | 99 | return $status; 100 | } 101 | 102 | public function isFormValid() 103 | { 104 | foreach ($this->fieldmessage as $field) { 105 | if ((array_key_exists('status', $field)) && ($field['status'] != 'success')) { 106 | return false; 107 | } 108 | } 109 | 110 | return true; 111 | } 112 | 113 | public function validateDate($datekey, $daykey, $monthkey, $yearkey, $method = 'post') 114 | { 115 | if ((isset($this->safe[$method]->$daykey)) && (isset($this->safe[$method]->$monthkey)) && (isset($this->safe[$method]->$yearkey)) && (checkdate($this->safe[$method]->$monthkey, $this->safe[$method]->$daykey, $this->safe[$method]->$yearkey))) { 116 | $this->fieldmessage[$datekey]['status'] = 'success'; 117 | $return = true; 118 | } else { 119 | $this->fieldmessage[$datekey]['message'] = 'must be a valid date' . $datekey . $daykey . $monthkey . $yearkey ; 120 | $this->fieldmessage[$datekey]['status'] = 'danger'; 121 | $return = false;; 122 | } 123 | 124 | return $return; 125 | } 126 | 127 | public function validateLength($key, $minlength = 1, $method = 'post') 128 | { 129 | if ((isset($this->safe[$method]->$key)) && (strlen($this->safe[$method]->$key) >= $minlength)) { 130 | $this->fieldmessage[$key]['status'] = 'success'; 131 | $return = true; 132 | } else { 133 | $this->fieldmessage[$key]['message'] = "Must be at least $minlength characters long."; 134 | $this->fieldmessage[$key]['status'] = 'danger'; 135 | $return = false; 136 | } 137 | 138 | return $return; 139 | } 140 | 141 | public function validateNumeric($key, $method = 'post') 142 | { 143 | if ((isset($this->safe[$method]->$key)) && (is_numeric($this->safe[$method]->$key))) { 144 | $this->fieldmessage[$key]['status'] = 'success'; 145 | $return = true; 146 | } else { 147 | $this->fieldmessage[$key]['message'] = "Must be numeric."; 148 | $this->fieldmessage[$key]['status'] = 'danger'; 149 | $return = false; 150 | } 151 | 152 | return $return; 153 | } 154 | 155 | public function validateInteger($key, $method = 'post') 156 | { 157 | if ((isset($this->safe[$method]->$key)) && (is_int((int)$this->safe[$method]->$key))) { 158 | $this->fieldmessage[$key]['status'] = 'success'; 159 | $return = true; 160 | } else { 161 | $this->fieldmessage[$key]['message'] = "Must be an integer."; 162 | $this->fieldmessage[$key]['status'] = 'danger'; 163 | $return = false; 164 | } 165 | 166 | return $return; 167 | } 168 | 169 | public function validateInterval($key, $max = 50, $min = 0, $method = 'post') 170 | { 171 | if ((isset($this->safe[$method]->$key)) && ($this->safe[$method]->$key >= $min) && ($this->safe[$method]->$key <= $max)) { 172 | $this->fieldmessage[$key]['status'] = 'success'; 173 | $return = true; 174 | } else { 175 | $this->fieldmessage[$key]['message'] = "Must be between $min and $max."; 176 | $this->fieldmessage[$key]['status'] = 'danger'; 177 | $return = false; 178 | } 179 | 180 | return $return; 181 | } 182 | 183 | public function validateEmail($key, $method = 'post') 184 | { 185 | if ((isset($this->safe[$method]->$key)) && (filter_var($this->safe[$method]->$key, FILTER_VALIDATE_EMAIL))) { 186 | $this->fieldmessage[$key]['status'] = 'success'; 187 | $return = true; 188 | } else { 189 | $this->fieldmessage[$key]['message'] = "$this->safe[$method]->$key is not a valid email-adress."; 190 | $this->fieldmessage[$key]['status'] = 'danger'; 191 | $return = false; 192 | } 193 | 194 | return $return; 195 | } 196 | 197 | 198 | } 199 | -------------------------------------------------------------------------------- /system/Load.php: -------------------------------------------------------------------------------- 1 | setLayout($layoutname); 14 | 15 | if (class_exists('Form')) { 16 | $this->form = Form::getInstance(); 17 | } 18 | } 19 | 20 | // render the main content of the site 21 | // while rendering the layout, render the partials as well 22 | public function render($viewname) 23 | { 24 | $this->content = $this->renderView(Load::view($viewname)); 25 | 26 | $this->renderLayout(); 27 | } 28 | 29 | // helper to display the content in the layout template 30 | public function getContent() 31 | { 32 | echo $this->content; 33 | } 34 | 35 | // first step: generate partial 36 | public function renderPartial($name) 37 | { 38 | if (array_key_exists($name, $this->partials)) { 39 | echo $this->renderView($this->partials[$name]); 40 | } else { 41 | error_log("partial not rendered: $name"); 42 | } 43 | } 44 | 45 | // second step: generate the layout 46 | public function renderLayout() 47 | { 48 | include($this->layoutfile); 49 | } 50 | 51 | public function setLayout($layoutname) 52 | { 53 | $this->layoutfile = Load::layout($layoutname); 54 | } 55 | 56 | // helper to generate a partial 57 | public function setPartial($partialname, $partialfile = '') 58 | { 59 | // if $partialfile is not set, use the partialname as filename 60 | $partialfile = ($partialfile) ? $partialfile : $partialname; 61 | 62 | $this->partials[$partialname] = Load::partial($partialfile); 63 | 64 | return $this; 65 | } 66 | 67 | // render a view (partial or main content) 68 | private function renderView($view) 69 | { 70 | 71 | 72 | 73 | // create an output buffer to get a rendered partial and store its content in a var. 74 | ob_start(); 75 | include($view); 76 | $data = ob_get_contents(); 77 | ob_end_clean(); 78 | 79 | return $data; 80 | } 81 | 82 | public function setPagetitle($title) 83 | { 84 | $this->pagetitle = $title; 85 | 86 | return $this; 87 | } 88 | 89 | public function getPagetitle() 90 | { 91 | return $this->pagetitle; 92 | } 93 | 94 | // automatic getter and setter, remapping every value to the protected attribute 95 | // read more about this on www.php.net/manual/en/language.oop5.overloading.php 96 | public function __set($name, $value) 97 | { 98 | $this->data[$name] = $value; 99 | } 100 | 101 | public function __get($name) 102 | { 103 | if (array_key_exists($name, $this->data)) { 104 | return $this->data[$name]; 105 | } 106 | return false; 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /system/URL.php: -------------------------------------------------------------------------------- 1 |