PageRenderTime 51ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/helpers/library/HTMLPurifier/URIScheme/data.php

https://bitbucket.org/adamanthea/sinister-gaming
PHP | 96 lines | 74 code | 6 blank | 16 comment | 22 complexity | cb4f49d5eded763ba49ab976ee987136 MD5 | raw file
  1. <?php
  2. /**
  3. * Implements data: URI for base64 encoded images supported by GD.
  4. */
  5. class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme {
  6. public $browsable = true;
  7. public $allowed_types = array(
  8. // you better write validation code for other types if you
  9. // decide to allow them
  10. 'image/jpeg' => true,
  11. 'image/gif' => true,
  12. 'image/png' => true,
  13. );
  14. // this is actually irrelevant since we only write out the path
  15. // component
  16. public $may_omit_host = true;
  17. public function doValidate(&$uri, $config, $context) {
  18. $result = explode(',', $uri->path, 2);
  19. $is_base64 = false;
  20. $charset = null;
  21. $content_type = null;
  22. if (count($result) == 2) {
  23. list($metadata, $data) = $result;
  24. // do some legwork on the metadata
  25. $metas = explode(';', $metadata);
  26. while(!empty($metas)) {
  27. $cur = array_shift($metas);
  28. if ($cur == 'base64') {
  29. $is_base64 = true;
  30. break;
  31. }
  32. if (substr($cur, 0, 8) == 'charset=') {
  33. // doesn't match if there are arbitrary spaces, but
  34. // whatever dude
  35. if ($charset !== null) continue; // garbage
  36. $charset = substr($cur, 8); // not used
  37. } else {
  38. if ($content_type !== null) continue; // garbage
  39. $content_type = $cur;
  40. }
  41. }
  42. } else {
  43. $data = $result[0];
  44. }
  45. if ($content_type !== null && empty($this->allowed_types[$content_type])) {
  46. return false;
  47. }
  48. if ($charset !== null) {
  49. // error; we don't allow plaintext stuff
  50. $charset = null;
  51. }
  52. $data = rawurldecode($data);
  53. if ($is_base64) {
  54. $raw_data = base64_decode($data);
  55. } else {
  56. $raw_data = $data;
  57. }
  58. // XXX probably want to refactor this into a general mechanism
  59. // for filtering arbitrary content types
  60. $file = tempnam("/tmp", "");
  61. file_put_contents($file, $raw_data);
  62. if (function_exists('exif_imagetype')) {
  63. $image_code = exif_imagetype($file);
  64. } elseif (function_exists('getimagesize')) {
  65. set_error_handler(array($this, 'muteErrorHandler'));
  66. $info = getimagesize($file);
  67. restore_error_handler();
  68. if ($info == false) return false;
  69. $image_code = $info[2];
  70. } else {
  71. trigger_error("could not find exif_imagetype or getimagesize functions", E_USER_ERROR);
  72. }
  73. $real_content_type = image_type_to_mime_type($image_code);
  74. if ($real_content_type != $content_type) {
  75. // we're nice guys; if the content type is something else we
  76. // support, change it over
  77. if (empty($this->allowed_types[$real_content_type])) return false;
  78. $content_type = $real_content_type;
  79. }
  80. // ok, it's kosher, rewrite what we need
  81. $uri->userinfo = null;
  82. $uri->host = null;
  83. $uri->port = null;
  84. $uri->fragment = null;
  85. $uri->query = null;
  86. $uri->path = "$content_type;base64," . base64_encode($raw_data);
  87. return true;
  88. }
  89. public function muteErrorHandler($errno, $errstr) {}
  90. }