PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/discojuice/lib/Feed.php

http://simplesamlphp.googlecode.com/
PHP | 577 lines | 388 code | 156 blank | 33 comment | 82 complexity | e9ee283b2dcd0b2ba00ef9c28f7c6b97 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, MIT
  1. <?php
  2. /*
  3. * File: SimpleImage.php
  4. * Author: Simon Jarvis
  5. * Copyright: 2006 Simon Jarvis
  6. * Date: 08/11/06
  7. * Link: http://www.white-hat-web-design.co.uk/articles/php-image-resizing.php
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details:
  18. * http://www.gnu.org/licenses/gpl.html
  19. *
  20. */
  21. class SimpleImage {
  22. var $image;
  23. var $image_type;
  24. function load($filename) {
  25. $image_info = getimagesize($filename);
  26. $this->image_type = $image_info[2];
  27. if( $this->image_type == IMAGETYPE_JPEG ) {
  28. $this->image = imagecreatefromjpeg($filename);
  29. } elseif( $this->image_type == IMAGETYPE_GIF ) {
  30. $this->image = imagecreatefromgif($filename);
  31. } elseif( $this->image_type == IMAGETYPE_PNG ) {
  32. $this->image = imagecreatefrompng($filename);
  33. }
  34. }
  35. function save($filename, $image_type=IMAGETYPE_PNG, $compression=90, $permissions=null) {
  36. if( $image_type == IMAGETYPE_JPEG ) {
  37. imagejpeg($this->image,$filename,$compression);
  38. } elseif( $image_type == IMAGETYPE_GIF ) {
  39. imagegif($this->image,$filename);
  40. } elseif( $image_type == IMAGETYPE_PNG ) {
  41. imagepng($this->image,$filename);
  42. }
  43. if( $permissions != null) {
  44. chmod($filename,$permissions);
  45. }
  46. }
  47. function output($image_type=IMAGETYPE_JPEG) {
  48. if( $image_type == IMAGETYPE_JPEG ) {
  49. imagejpeg($this->image);
  50. } elseif( $image_type == IMAGETYPE_GIF ) {
  51. imagegif($this->image);
  52. } elseif( $image_type == IMAGETYPE_PNG ) {
  53. imagepng($this->image);
  54. }
  55. }
  56. function getWidth() {
  57. return imagesx($this->image);
  58. }
  59. function getHeight() {
  60. return imagesy($this->image);
  61. }
  62. function resizeToHeight($height) {
  63. $ratio = $height / $this->getHeight();
  64. $width = $this->getWidth() * $ratio;
  65. $this->resize($width,$height);
  66. }
  67. function resizeToWidth($width) {
  68. $ratio = $width / $this->getWidth();
  69. $height = $this->getheight() * $ratio;
  70. $this->resize($width,$height);
  71. }
  72. function scale($scale) {
  73. $width = $this->getWidth() * $scale/100;
  74. $height = $this->getheight() * $scale/100;
  75. $this->resize($width,$height);
  76. }
  77. function resize($width,$height) {
  78. $new_image = imagecreatetruecolor($width, $height);
  79. imagealphablending($new_image, false);
  80. imagesavealpha($new_image,true);
  81. $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
  82. imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent);
  83. imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
  84. $this->image = $new_image;
  85. }
  86. }
  87. /**
  88. * ...
  89. */
  90. class sspmod_discojuice_Feed {
  91. protected $config, $djconfig;
  92. protected $excludes, $override, $insert, $idplist;
  93. protected $metadata;
  94. protected $feed;
  95. protected $contrytags, $countryTLDs;
  96. function __construct() {
  97. $this->config = SimpleSAML_Configuration::getInstance();
  98. $this->djconfig = SimpleSAML_Configuration::getOptionalConfig('discojuicefeed.php');
  99. $metadatah = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
  100. $saml2 = $metadatah->getList('saml20-idp-remote');
  101. $shib = $metadatah->getList('shib13-idp-remote');
  102. foreach($shib AS $s) {
  103. $this->metadata[$s['entityid']] = $s;
  104. }
  105. foreach($saml2 AS $s) {
  106. $this->metadata[$s['entityid']] = $s;
  107. }
  108. // $this->metadata = array_merge($this->metadata, $shib);
  109. $this->idplist = $this->getIdPList();
  110. SimpleSAML_Logger::info('IdP List contained : ' . count($this->idplist) . ' entries.');
  111. $this->excludes = array_flip($this->djconfig->getValue('exclude'));
  112. $this->insert = $this->djconfig->getValue('insert');
  113. $this->overrides = $this->djconfig->getValue('overrides');
  114. $this->countrytags = array(
  115. 'croatia' => 'HR',
  116. 'czech' => 'CZ',
  117. 'denmark' => 'DK',
  118. 'finland' => 'FI',
  119. 'france' => 'FR',
  120. 'germany' => 'DE',
  121. 'greece' => 'GR',
  122. 'ireland' => 'IE',
  123. 'italy' => 'IT',
  124. 'luxembourg' => 'LU',
  125. 'hungary' => 'HU',
  126. 'netherlands' => 'NL',
  127. 'norway' => 'NO',
  128. 'portugal' => 'PT',
  129. 'poland' => 'PL',
  130. 'slovenia' => 'SI',
  131. 'spain' => 'ES',
  132. 'sweden' => 'SE',
  133. 'switzerland' => 'CH',
  134. 'turkey' => 'TR',
  135. 'us' => 'US',
  136. 'uk' => 'GB',
  137. 'japan' => 'JP',
  138. );
  139. $this->countryTLDs = array(
  140. 'lp.' => 'PL',
  141. 'uh.' => 'HU',
  142. 'es.' => 'SE',
  143. 'ed.' => 'DE',
  144. 'if.' => 'FI',
  145. 'zc.' => 'CZ',
  146. 'rt.' => 'TR',
  147. 'kd.' => 'DK',
  148. 'on.' => 'NO',
  149. 'ude.' => 'US',
  150. 'ku.oc.' => 'GB',
  151. );
  152. }
  153. public function store() {
  154. $datadir = $this->config->getPathValue('datadir', 'data/');
  155. if (!is_dir($datadir))
  156. throw new Exception('Data directory [' . $datadir. '] does not exist');
  157. if (!is_writable($datadir))
  158. throw new Exception('Data directory [' . $datadir. '] is not writable');
  159. $djdatadir = $datadir . 'discojuice/';
  160. if (!is_dir($djdatadir)) {
  161. mkdir($djdatadir);
  162. }
  163. $djdatafile = $djdatadir . 'discojuice.cache';
  164. $data = $this->getJSON();
  165. file_put_contents($djdatafile, json_encode($data));
  166. }
  167. public function read() {
  168. $djdatafile = $this->config->getPathValue('datadir', 'data/') . 'discojuice/' . 'discojuice.cache';
  169. if (!file_exists($djdatafile)) {
  170. error_log('Did not find cached version, generating content again...');
  171. return json_encode($this->getJSON());
  172. }
  173. return file_get_contents($djdatafile);
  174. }
  175. private function exclude($e) {
  176. if ($this->excludes === NULL) return FALSE;
  177. return (array_key_exists($e, $this->excludes));
  178. }
  179. protected function getIdPList() {
  180. $api = $this->djconfig->getValue('idplistapi', NULL);
  181. if (empty($api)) return array();
  182. $result = array();
  183. $apiresult = json_decode(file_get_contents($api), TRUE);
  184. if ($apiresult['status'] === 'ok') {
  185. foreach($apiresult['data'] AS $idp) {
  186. $result[$idp] = 1;
  187. }
  188. }
  189. return $result;
  190. }
  191. private function process() {
  192. $this->feed = array();
  193. $this->merge();
  194. foreach($this->metadata AS $m) {
  195. if ($this->exclude($m['entityid'])) continue;
  196. $nc = $this->processEntity($m);
  197. // if (empty($nc['icon'])) continue;
  198. $this->feed[] = $nc;
  199. }
  200. if (!empty($this->insert)) {
  201. foreach($this->insert AS $i) {
  202. $this->feed[] = $i;
  203. }
  204. }
  205. }
  206. protected function merge() {
  207. $mergeendpoints = $this->djconfig->getValue('mergeEndpoints', NULL);
  208. SimpleSAML_Logger::info('Processing merge endpoint: ' . var_export($mergeendpoints, TRUE));
  209. if ($mergeendpoints === NULL) return;
  210. if (!is_array($mergeendpoints)) return;
  211. foreach($mergeendpoints AS $me) {
  212. SimpleSAML_Logger::info('Processing merge endpoint: ' . $me);
  213. $newlist = json_decode(file_get_contents($me), TRUE);
  214. $this->feed = array_merge($this->feed, $newlist);
  215. }
  216. }
  217. private function processEntity($m) {
  218. $data = array('entityID' => $m['entityid']);
  219. $this->getCountry($data, $m);
  220. $this->getTitle($data, $m);
  221. $this->getOverrides($data, $m);
  222. $this->getGeo($data, $m);
  223. $this->getLogo($data, $m);
  224. if (!empty($this->idplist)) {
  225. $this->islisted($data, $m);
  226. }
  227. return $data;
  228. }
  229. public function getJSON() {
  230. $this->process();
  231. return $this->feed;
  232. }
  233. protected function islisted(&$data, $m) {
  234. $weight = 0;
  235. if (array_key_exists('weight', $data)) $weight = $data['weight'];
  236. if (!array_key_exists($m['entityid'], $this->idplist)) {
  237. #echo 'Match for ' . $m['entityid'];
  238. $weight += 2;
  239. }
  240. $data['weight'] = $weight;
  241. # echo '<pre>';
  242. # print_r($this->idplist); exit;
  243. }
  244. protected static function getPreferredLogo($logos) {
  245. $current = array('height' => 0);
  246. $found = false;
  247. foreach($logos AS $logo) {
  248. if (
  249. $logo['height'] > 23 &&
  250. $logo['height'] < 41 &&
  251. $logo['height'] > $current['height']
  252. ) {
  253. $current = $logo;
  254. $found = true;
  255. }
  256. }
  257. if ($found) return $current;
  258. foreach($logos AS $logo) {
  259. if (
  260. $logo['height'] > $current['height']
  261. ) {
  262. $current = $logo;
  263. $found = true;
  264. }
  265. }
  266. if ($found) return $current;
  267. return NULL;
  268. }
  269. protected static function getCachedLogo($logo) {
  270. $hash = sha1($logo['url']);
  271. $relfile = 'cached/' . $hash;
  272. $file = dirname(dirname(__FILE__)) . '/www/discojuice/logos/' . $relfile;
  273. $fileorig = $file . '.orig';
  274. if (file_exists($file)) {
  275. return $relfile;
  276. }
  277. //echo 'icon file: ' . $file; exit;
  278. $orgimg = file_get_contents($logo['url']);
  279. if (empty($orgimg)) return null;
  280. file_put_contents($fileorig, $orgimg);
  281. if ($logo['height'] > 40) {
  282. $image = new SimpleImage();
  283. $image->load($fileorig);
  284. $image->resizeToHeight(38);
  285. $image->save($file);
  286. if (file_exists($file)) {
  287. return $relfile;
  288. }
  289. }
  290. file_put_contents($file, $orgimg);
  291. if (file_exists($file)) {
  292. return $relfile;
  293. }
  294. }
  295. protected function getLogo(&$data, $m) {
  296. if (!empty($m['mdui']) && !empty($m['mdui']['logos'])) {
  297. $cl = self::getPreferredLogo($m['mdui']['logos']);
  298. if (!empty($cl)) {
  299. $cached = self::getCachedLogo($cl);
  300. if (!empty($cached)) {
  301. $data['icon'] = $cached;
  302. }
  303. }
  304. // echo '<pre>'; print_r($m); exit;
  305. }
  306. }
  307. protected function getGeo(&$data, $m) {
  308. if (!empty($m['disco']) && !empty($m['disco']['geo'])) {
  309. $data['geo'] = $m['disco']['geo'];
  310. // $data['discogeo'] = 1;
  311. }
  312. // Do not lookup Geo locations from IP if geo location is already set.
  313. if (array_key_exists('geo', $data)) return;
  314. // Look for SingleSignOnService endpoint.
  315. if (!empty($m['SingleSignOnService']) ) {
  316. $m['metadata-set'] = 'saml20-idp-remote';
  317. $mc = SimpleSAML_Configuration::loadFromArray($m);
  318. $endpoint = $mc->getDefaultEndpoint('SingleSignOnService');
  319. try {
  320. $host = parse_url($endpoint['Location'], PHP_URL_HOST); if (empty($host)) return;
  321. $ip = gethostbyname($host);
  322. if (empty($ip)) return;
  323. if ($ip === $host) return;
  324. $capi = new sspmod_discojuice_Country($ip);
  325. if (empty($data['geo'])) {
  326. $geo = $capi->getGeo();
  327. $geos = explode(',', $geo);
  328. $data['geo'] = array('lat' => $geos[0], 'lon' => $geos[1]);
  329. }
  330. } catch(Exception $e) {
  331. error_log('Error looking up geo coordinates: ' . $e->getMessage());
  332. }
  333. }
  334. }
  335. protected function getCountry(&$data, $m) {
  336. if (!empty($m['tags'])) {
  337. foreach($m['tags'] AS $tag) {
  338. if (array_key_exists($tag, $this->countrytags)) {
  339. $data['country'] = $this->countrytags[$tag];
  340. return;
  341. }
  342. }
  343. }
  344. $c = self::countryFromURL($m['entityid']);
  345. if (!empty($c)) { $data['country'] = $c; return; }
  346. if (!empty($m['SingleSignOnService']) ) {
  347. SimpleSAML_Logger::debug('SingleSignOnService found');
  348. $m['metadata-set'] = 'saml20-idp-remote';
  349. $mc = SimpleSAML_Configuration::loadFromArray($m);
  350. $endpoint = $mc->getDefaultEndpoint('SingleSignOnService');
  351. error_log('Endpoint: ' . var_export($endpoint, TRUE));
  352. $c = $this->countryFromURL($endpoint['Location']);
  353. if (!empty($c)) { $data['country'] = $c; return; }
  354. try {
  355. $host = parse_url($endpoint['Location'], PHP_URL_HOST);
  356. $ip = gethostbyname($host);
  357. $capi = new sspmod_discojuice_Country($ip);
  358. $region = $capi->getRegion();
  359. if (preg_match('|^([A-Z][A-Z])/|', $region, $match)) {
  360. $data['country'] = $match[1];
  361. }
  362. } catch(Exception $e) {}
  363. }
  364. return null;
  365. }
  366. protected function getTitle(&$data, $m) {
  367. if(isset($m['name']) && is_string($m['name'])) {
  368. $data['title'] = $m['name'];
  369. } else if(isset($m['name']) && array_key_exists('en', $m['name'])) {
  370. $data['title'] = $m['name']['en'];
  371. } else if(isset($m['name']) && is_array($m['name'])) {
  372. $data['title'] = array_pop($m['name']);
  373. } else if (isset($m['name']) && is_string($m['name'])) {
  374. $data['title'] = $m['name'];
  375. } else if (isset($m['OrganizationName']) && isset($m['OrganizationName']['en'])) {
  376. $data['title'] = $m['OrganizationName']['en'];
  377. } else if (isset($m['OrganizationName']) && is_array($m['OrganizationName'])) {
  378. $data['title'] = array_pop($m['OrganizationName']);
  379. } else {
  380. $data['title'] = substr($m['entityid'], 0, 20);
  381. $data['weight'] = 9;
  382. }
  383. }
  384. protected function getOverrides(&$data, $m) {
  385. if (empty($this->overrides)) return;
  386. if (empty($this->overrides[$m['entityid']])) return;
  387. $override = $this->overrides[$m['entityid']];
  388. foreach($override AS $k => $v) {
  389. $data[$k] = $v;
  390. }
  391. }
  392. protected static function prefix($word, $prefix) {
  393. if ( strlen($word) < strlen($prefix)) {
  394. $tmp = $prefix;
  395. $prefix = $word;
  396. $word = $tmp;
  397. }
  398. $word = substr($word, 0, strlen($prefix));
  399. if ($prefix == $word) {
  400. return 1;
  401. }
  402. return 0;
  403. }
  404. protected function countryFromURL($entityid) {
  405. try {
  406. $pu = parse_url($entityid, PHP_URL_HOST);
  407. if (!empty($pu)) {
  408. $rh = strrev($pu);
  409. // error_log('Looking up TLD : ' . $rh);
  410. foreach($this->countryTLDs AS $domain => $country) {
  411. if (self::prefix($domain, $rh)) {
  412. error_log('Looking up TLD : ' . $rh . ' matched ' . $country);
  413. return $country;
  414. }
  415. }
  416. }
  417. } catch(Exception $e) {
  418. }
  419. return null;
  420. }
  421. }