~ubuntu-branches/ubuntu/vivid/phabricator/vivid-proposed

« back to all changes in this revision

Viewing changes to libphutil/src/parser/PhutilURI.php

  • Committer: Package Import Robot
  • Author(s): Richard Sellam
  • Date: 2014-10-23 20:49:26 UTC
  • mfrom: (0.2.1) (0.1.1)
  • Revision ID: package-import@ubuntu.com-20141023204926-vq80u1op4df44azb
Tags: 0~git20141023-1
Initial release (closes: #703046)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
/**
 
4
 * Basic URI parser object.
 
5
 */
 
6
final class PhutilURI {
 
7
 
 
8
  private $protocol;
 
9
  private $user;
 
10
  private $pass;
 
11
  private $domain;
 
12
  private $port;
 
13
  private $path;
 
14
  private $query = array();
 
15
  private $fragment;
 
16
 
 
17
  public function __construct($uri) {
 
18
    $uri = (string)$uri;
 
19
 
 
20
    $matches = null;
 
21
    if (preg_match('(^([^/:]*://[^/]*)(\\?.*)\z)', $uri, $matches)) {
 
22
      // If the URI is something like `idea://open?file=/path/to/file`, the
 
23
      // `parse_url()` function will parse `open?file=` as the host. This is
 
24
      // not the expected result. Break the URI into two pieces, stick a slash
 
25
      // in between them, parse that, then remove the path. See T6106.
 
26
 
 
27
      $parts = parse_url($matches[1].'/'.$matches[2]);
 
28
      unset($parts['path']);
 
29
    } else {
 
30
      $parts = parse_url($uri);
 
31
    }
 
32
 
 
33
    // The parse_url() call will accept URIs with leading whitespace, but many
 
34
    // other tools (like git) will not. See T4913 for a specific example. If
 
35
    // the input string has leading whitespace, fail the parse.
 
36
    if ($parts) {
 
37
      if (ltrim($uri) != $uri) {
 
38
        $parts = false;
 
39
      }
 
40
    }
 
41
 
 
42
 
 
43
    // NOTE: `parse_url()` is very liberal about host names; fail the parse if
 
44
    // the host looks like garbage.
 
45
    if ($parts) {
 
46
      $host = idx($parts, 'host', '');
 
47
      if (!preg_match('/^([a-zA-Z0-9\\.\\-]*)$/', $host)) {
 
48
        $parts = false;
 
49
      }
 
50
    }
 
51
 
 
52
    if (!$parts) {
 
53
      $parts = array();
 
54
    }
 
55
 
 
56
    // stringyness is to preserve API compatibility and
 
57
    // allow the tests to continue passing
 
58
    $this->protocol = idx($parts, 'scheme', '');
 
59
    $this->user     = rawurldecode(idx($parts, 'user', ''));
 
60
    $this->pass     = rawurldecode(idx($parts, 'pass', ''));
 
61
    $this->domain   = idx($parts, 'host', '');
 
62
    $this->port     = (string)idx($parts, 'port', '');
 
63
    $this->path     = idx($parts, 'path', '');
 
64
    $query = idx($parts, 'query');
 
65
    if ($query) {
 
66
      $this->query = id(new PhutilQueryStringParser())->parseQueryString(
 
67
        $query);
 
68
    }
 
69
    $this->fragment = idx($parts, 'fragment', '');
 
70
  }
 
71
 
 
72
  public function __toString() {
 
73
    $prefix = null;
 
74
    if ($this->protocol || $this->domain || $this->port) {
 
75
      $protocol = nonempty($this->protocol, 'http');
 
76
 
 
77
      $auth = '';
 
78
      if (strlen($this->user) && strlen($this->pass)) {
 
79
        $auth = phutil_escape_uri($this->user).':'.
 
80
                phutil_escape_uri($this->pass).'@';
 
81
      } else if (strlen($this->user)) {
 
82
        $auth = phutil_escape_uri($this->user).'@';
 
83
      }
 
84
 
 
85
      $prefix = $protocol.'://'.$auth.$this->domain;
 
86
      if ($this->port) {
 
87
        $prefix .= ':'.$this->port;
 
88
      }
 
89
    }
 
90
 
 
91
    if ($this->query) {
 
92
      $query = '?'.http_build_query($this->query);
 
93
    } else {
 
94
      $query = null;
 
95
    }
 
96
 
 
97
    if (strlen($this->getFragment())) {
 
98
      $fragment = '#'.$this->getFragment();
 
99
    } else {
 
100
      $fragment = null;
 
101
    }
 
102
 
 
103
 
 
104
    return $prefix.$this->getPath().$query.$fragment;
 
105
  }
 
106
 
 
107
  public function setQueryParam($key, $value) {
 
108
    if ($value === null) {
 
109
      unset($this->query[$key]);
 
110
    } else {
 
111
      $this->query[$key] = $value;
 
112
    }
 
113
    return $this;
 
114
  }
 
115
 
 
116
  public function setQueryParams(array $params) {
 
117
    $this->query = $params;
 
118
    return $this;
 
119
  }
 
120
 
 
121
  public function getQueryParams() {
 
122
    return $this->query;
 
123
  }
 
124
 
 
125
  public function setProtocol($protocol) {
 
126
    $this->protocol = $protocol;
 
127
    return $this;
 
128
  }
 
129
  public function getProtocol() {
 
130
    return $this->protocol;
 
131
  }
 
132
 
 
133
  public function setDomain($domain) {
 
134
    $this->domain = $domain;
 
135
    return $this;
 
136
  }
 
137
 
 
138
  public function getDomain() {
 
139
    return $this->domain;
 
140
  }
 
141
 
 
142
  public function setPort($port) {
 
143
    $this->port = $port;
 
144
    return $this;
 
145
  }
 
146
  public function getPort() {
 
147
    return $this->port;
 
148
  }
 
149
 
 
150
  public function setPath($path) {
 
151
    if ($this->domain && strlen($path) && $path[0] !== '/') {
 
152
      $path = '/'.$path;
 
153
    }
 
154
    $this->path = $path;
 
155
    return $this;
 
156
  }
 
157
 
 
158
  public function appendPath($path) {
 
159
    $first = strlen($path) ? $path[0] : null;
 
160
    $last  = strlen($this->path) ? $this->path[strlen($this->path) - 1] : null;
 
161
 
 
162
    if (!$this->path) {
 
163
      return $this->setPath($path);
 
164
    } else if ($first === '/' && $last === '/') {
 
165
      $path = substr($path, 1);
 
166
    } else if ($first !== '/' && $last !== '/') {
 
167
      $path = '/'.$path;
 
168
    }
 
169
 
 
170
    $this->path .= $path;
 
171
    return $this;
 
172
  }
 
173
 
 
174
  public function getPath() {
 
175
    return $this->path;
 
176
  }
 
177
 
 
178
  public function setFragment($fragment) {
 
179
    $this->fragment = $fragment;
 
180
    return $this;
 
181
  }
 
182
 
 
183
  public function getFragment() {
 
184
    return $this->fragment;
 
185
  }
 
186
 
 
187
  public function setUser($user) {
 
188
    $this->user = $user;
 
189
    return $this;
 
190
  }
 
191
 
 
192
  public function getUser() {
 
193
    return $this->user;
 
194
  }
 
195
 
 
196
  public function setPass($pass) {
 
197
    $this->pass = $pass;
 
198
    return $this;
 
199
  }
 
200
 
 
201
  public function getPass() {
 
202
    return $this->pass;
 
203
  }
 
204
 
 
205
  public function alter($key, $value) {
 
206
    $altered = clone $this;
 
207
    $altered->setQueryParam($key, $value);
 
208
    return $altered;
 
209
  }
 
210
 
 
211
}