OAuthUtil.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. class OAuthUtil {
  3. public static function urlencode_rfc3986($input) {
  4. if (is_array($input)) {
  5. return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input);
  6. } else if (is_scalar($input)) {
  7. return str_replace(
  8. '+',
  9. ' ',
  10. str_replace('%7E', '~', rawurlencode($input))
  11. );
  12. } else {
  13. return '';
  14. }
  15. }
  16. // This decode function isn't taking into consideration the above
  17. // modifications to the encoding process. However, this method doesn't
  18. // seem to be used anywhere so leaving it as is.
  19. public static function urldecode_rfc3986($string) {
  20. return urldecode($string);
  21. }
  22. // Utility function for turning the Authorization: header into
  23. // parameters, has to do some unescaping
  24. // Can filter out any non-oauth parameters if needed (default behaviour)
  25. // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement.
  26. // see http://code.google.com/p/oauth/issues/detail?id=163
  27. public static function split_header($header, $only_allow_oauth_parameters = true) {
  28. $params = array();
  29. if (preg_match_all('/('.($only_allow_oauth_parameters ? 'oauth_' : '').'[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) {
  30. foreach ($matches[1] as $i => $h) {
  31. $params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]);
  32. }
  33. if (isset($params['realm'])) {
  34. unset($params['realm']);
  35. }
  36. }
  37. return $params;
  38. }
  39. // helper to try to sort out headers for people who aren't running apache
  40. public static function get_headers() {
  41. if (function_exists('apache_request_headers')) {
  42. // we need this to get the actual Authorization: header
  43. // because apache tends to tell us it doesn't exist
  44. $headers = apache_request_headers();
  45. // sanitize the output of apache_request_headers because
  46. // we always want the keys to be Cased-Like-This and arh()
  47. // returns the headers in the same case as they are in the
  48. // request
  49. $out = array();
  50. foreach ($headers AS $key => $value) {
  51. $key = str_replace(
  52. " ",
  53. "-",
  54. ucwords(strtolower(str_replace("-", " ", $key)))
  55. );
  56. $out[$key] = $value;
  57. }
  58. } else {
  59. // otherwise we don't have apache and are just going to have to hope
  60. // that $_SERVER actually contains what we need
  61. $out = array();
  62. if( isset($_SERVER['CONTENT_TYPE']) )
  63. $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
  64. if( isset($_ENV['CONTENT_TYPE']) )
  65. $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
  66. foreach ($_SERVER as $key => $value) {
  67. if (substr($key, 0, 5) == "HTTP_") {
  68. // this is chaos, basically it is just there to capitalize the first
  69. // letter of every word that is not an initial HTTP and strip HTTP
  70. // code from przemek
  71. $key = str_replace(
  72. " ",
  73. "-",
  74. ucwords(strtolower(str_replace("_", " ", substr($key, 5))))
  75. );
  76. $out[$key] = $value;
  77. }
  78. }
  79. }
  80. return $out;
  81. }
  82. // This function takes a input like a=b&a=c&d=e and returns the parsed
  83. // parameters like this
  84. // array('a' => array('b','c'), 'd' => 'e')
  85. public static function parse_parameters( $input ) {
  86. if (!isset($input) || !$input) return array();
  87. $pairs = explode('&', $input);
  88. $parsed_parameters = array();
  89. foreach ($pairs as $pair) {
  90. $split = explode('=', $pair, 2);
  91. $parameter = OAuthUtil::urldecode_rfc3986($split[0]);
  92. $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : '';
  93. if (isset($parsed_parameters[$parameter])) {
  94. // We have already recieved parameter(s) with this name, so add to the list
  95. // of parameters with this name
  96. if (is_scalar($parsed_parameters[$parameter])) {
  97. // This is the first duplicate, so transform scalar (string) into an array
  98. // so we can add the duplicates
  99. $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]);
  100. }
  101. $parsed_parameters[$parameter][] = $value;
  102. } else {
  103. $parsed_parameters[$parameter] = $value;
  104. }
  105. }
  106. return $parsed_parameters;
  107. }
  108. public static function build_http_query($params) {
  109. if (!$params) return '';
  110. // Urlencode both keys and values
  111. $keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
  112. $values = OAuthUtil::urlencode_rfc3986(array_values($params));
  113. $params = array_combine($keys, $values);
  114. // Parameters are sorted by name, using lexicographical byte value ordering.
  115. // Ref: Spec: 9.1.1 (1)
  116. uksort($params, 'strcmp');
  117. $pairs = array();
  118. foreach ($params as $parameter => $value) {
  119. if (is_array($value)) {
  120. // If two or more parameters share the same name, they are sorted by their value
  121. // Ref: Spec: 9.1.1 (1)
  122. // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
  123. sort($value, SORT_STRING);
  124. foreach ($value as $duplicate_value) {
  125. $pairs[] = $parameter . '=' . $duplicate_value;
  126. }
  127. } else {
  128. $pairs[] = $parameter . '=' . $value;
  129. }
  130. }
  131. // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
  132. // Each name-value pair is separated by an '&' character (ASCII code 38)
  133. return implode('&', $pairs);
  134. }
  135. }