Skip to content

Commit af84f21

Browse files
author
epriestley
committedFeb 12, 2020
Move lingering "Aphront" classes to Phabricator
Summary: Ref T13395. Moves some Aphront classes from libphutil to Phabricator. Test Plan: Grepped for symbols in libphutil and Arcanist. Maniphest Tasks: T13395 Differential Revision: https://secure.phabricator.com/D20975
1 parent 2327578 commit af84f21

10 files changed

+1037
-0
lines changed
 

‎src/__phutil_library_map__.php

+16
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@
224224
'AphrontFormView' => 'view/form/AphrontFormView.php',
225225
'AphrontGlyphBarView' => 'view/widget/bars/AphrontGlyphBarView.php',
226226
'AphrontHTMLResponse' => 'aphront/response/AphrontHTMLResponse.php',
227+
'AphrontHTTPHeaderParser' => 'aphront/headerparser/AphrontHTTPHeaderParser.php',
228+
'AphrontHTTPHeaderParserTestCase' => 'aphront/headerparser/__tests__/AphrontHTTPHeaderParserTestCase.php',
227229
'AphrontHTTPParameterType' => 'aphront/httpparametertype/AphrontHTTPParameterType.php',
228230
'AphrontHTTPProxyResponse' => 'aphront/response/AphrontHTTPProxyResponse.php',
229231
'AphrontHTTPSink' => 'aphront/sink/AphrontHTTPSink.php',
@@ -242,6 +244,9 @@
242244
'AphrontMalformedRequestException' => 'aphront/exception/AphrontMalformedRequestException.php',
243245
'AphrontMoreView' => 'view/layout/AphrontMoreView.php',
244246
'AphrontMultiColumnView' => 'view/layout/AphrontMultiColumnView.php',
247+
'AphrontMultipartParser' => 'aphront/multipartparser/AphrontMultipartParser.php',
248+
'AphrontMultipartParserTestCase' => 'aphront/multipartparser/__tests__/AphrontMultipartParserTestCase.php',
249+
'AphrontMultipartPart' => 'aphront/multipartparser/AphrontMultipartPart.php',
245250
'AphrontMySQLDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php',
246251
'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontMySQLDatabaseConnectionTestCase.php',
247252
'AphrontMySQLiDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php',
@@ -265,12 +270,14 @@
265270
'AphrontReloadResponse' => 'aphront/response/AphrontReloadResponse.php',
266271
'AphrontRequest' => 'aphront/AphrontRequest.php',
267272
'AphrontRequestExceptionHandler' => 'aphront/handler/AphrontRequestExceptionHandler.php',
273+
'AphrontRequestStream' => 'aphront/requeststream/AphrontRequestStream.php',
268274
'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php',
269275
'AphrontResponse' => 'aphront/response/AphrontResponse.php',
270276
'AphrontResponseProducerInterface' => 'aphront/interface/AphrontResponseProducerInterface.php',
271277
'AphrontRoutingMap' => 'aphront/site/AphrontRoutingMap.php',
272278
'AphrontRoutingResult' => 'aphront/site/AphrontRoutingResult.php',
273279
'AphrontSchemaQueryException' => 'infrastructure/storage/exception/AphrontSchemaQueryException.php',
280+
'AphrontScopedUnguardedWriteCapability' => 'aphront/writeguard/AphrontScopedUnguardedWriteCapability.php',
274281
'AphrontSelectHTTPParameterType' => 'aphront/httpparametertype/AphrontSelectHTTPParameterType.php',
275282
'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php',
276283
'AphrontSite' => 'aphront/site/AphrontSite.php',
@@ -286,6 +293,7 @@
286293
'AphrontUserListHTTPParameterType' => 'aphront/httpparametertype/AphrontUserListHTTPParameterType.php',
287294
'AphrontView' => 'view/AphrontView.php',
288295
'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php',
296+
'AphrontWriteGuard' => 'aphront/writeguard/AphrontWriteGuard.php',
289297
'ArcanistConduitAPIMethod' => 'applications/arcanist/conduit/ArcanistConduitAPIMethod.php',
290298
'AuditConduitAPIMethod' => 'applications/audit/conduit/AuditConduitAPIMethod.php',
291299
'AuditQueryConduitAPIMethod' => 'applications/audit/conduit/AuditQueryConduitAPIMethod.php',
@@ -6170,6 +6178,8 @@
61706178
'AphrontFormView' => 'AphrontView',
61716179
'AphrontGlyphBarView' => 'AphrontBarView',
61726180
'AphrontHTMLResponse' => 'AphrontResponse',
6181+
'AphrontHTTPHeaderParser' => 'Phobject',
6182+
'AphrontHTTPHeaderParserTestCase' => 'PhutilTestCase',
61736183
'AphrontHTTPParameterType' => 'Phobject',
61746184
'AphrontHTTPProxyResponse' => 'AphrontResponse',
61756185
'AphrontHTTPSink' => 'Phobject',
@@ -6188,6 +6198,9 @@
61886198
'AphrontMalformedRequestException' => 'AphrontException',
61896199
'AphrontMoreView' => 'AphrontView',
61906200
'AphrontMultiColumnView' => 'AphrontView',
6201+
'AphrontMultipartParser' => 'Phobject',
6202+
'AphrontMultipartParserTestCase' => 'PhutilTestCase',
6203+
'AphrontMultipartPart' => 'Phobject',
61916204
'AphrontMySQLDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection',
61926205
'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase',
61936206
'AphrontMySQLiDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection',
@@ -6214,11 +6227,13 @@
62146227
'AphrontReloadResponse' => 'AphrontRedirectResponse',
62156228
'AphrontRequest' => 'Phobject',
62166229
'AphrontRequestExceptionHandler' => 'Phobject',
6230+
'AphrontRequestStream' => 'Phobject',
62176231
'AphrontRequestTestCase' => 'PhabricatorTestCase',
62186232
'AphrontResponse' => 'Phobject',
62196233
'AphrontRoutingMap' => 'Phobject',
62206234
'AphrontRoutingResult' => 'Phobject',
62216235
'AphrontSchemaQueryException' => 'AphrontQueryException',
6236+
'AphrontScopedUnguardedWriteCapability' => 'Phobject',
62226237
'AphrontSelectHTTPParameterType' => 'AphrontHTTPParameterType',
62236238
'AphrontSideNavFilterView' => 'AphrontView',
62246239
'AphrontSite' => 'Phobject',
@@ -6237,6 +6252,7 @@
62376252
'PhutilSafeHTMLProducerInterface',
62386253
),
62396254
'AphrontWebpageResponse' => 'AphrontHTMLResponse',
6255+
'AphrontWriteGuard' => 'Phobject',
62406256
'ArcanistConduitAPIMethod' => 'ConduitAPIMethod',
62416257
'AuditConduitAPIMethod' => 'ConduitAPIMethod',
62426258
'AuditQueryConduitAPIMethod' => 'AuditConduitAPIMethod',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
<?php
2+
3+
final class AphrontHTTPHeaderParser extends Phobject {
4+
5+
private $name;
6+
private $content;
7+
private $pairs;
8+
9+
public function parseRawHeader($raw_header) {
10+
$this->name = null;
11+
$this->content = null;
12+
13+
$parts = explode(':', $raw_header, 2);
14+
$this->name = trim($parts[0]);
15+
if (count($parts) > 1) {
16+
$this->content = trim($parts[1]);
17+
}
18+
19+
$this->pairs = null;
20+
21+
return $this;
22+
}
23+
24+
public function getHeaderName() {
25+
$this->requireParse();
26+
return $this->name;
27+
}
28+
29+
public function getHeaderContent() {
30+
$this->requireParse();
31+
return $this->content;
32+
}
33+
34+
public function getHeaderContentAsPairs() {
35+
$content = $this->getHeaderContent();
36+
37+
38+
$state = 'prekey';
39+
$length = strlen($content);
40+
41+
$pair_name = null;
42+
$pair_value = null;
43+
44+
$pairs = array();
45+
$ii = 0;
46+
while ($ii < $length) {
47+
$c = $content[$ii];
48+
49+
switch ($state) {
50+
case 'prekey';
51+
// We're eating space in front of a key.
52+
if ($c == ' ') {
53+
$ii++;
54+
break;
55+
}
56+
$pair_name = '';
57+
$state = 'key';
58+
break;
59+
case 'key';
60+
// We're parsing a key name until we find "=" or ";".
61+
if ($c == ';') {
62+
$state = 'done';
63+
break;
64+
}
65+
66+
if ($c == '=') {
67+
$ii++;
68+
$state = 'value';
69+
break;
70+
}
71+
72+
$ii++;
73+
$pair_name .= $c;
74+
break;
75+
case 'value':
76+
// We found an "=", so now figure out if the value is quoted
77+
// or not.
78+
if ($c == '"') {
79+
$ii++;
80+
$state = 'quoted';
81+
break;
82+
}
83+
$state = 'unquoted';
84+
break;
85+
case 'quoted':
86+
// We're in a quoted string, parse until we find the closing quote.
87+
if ($c == '"') {
88+
$ii++;
89+
$state = 'done';
90+
break;
91+
}
92+
93+
$ii++;
94+
$pair_value .= $c;
95+
break;
96+
case 'unquoted':
97+
// We're in an unquoted string, parse until we find a space or a
98+
// semicolon.
99+
if ($c == ' ' || $c == ';') {
100+
$state = 'done';
101+
break;
102+
}
103+
$ii++;
104+
$pair_value .= $c;
105+
break;
106+
case 'done':
107+
// We parsed something, so eat any trailing whitespace and semicolons
108+
// and look for a new value.
109+
if ($c == ' ' || $c == ';') {
110+
$ii++;
111+
break;
112+
}
113+
114+
$pairs[] = array(
115+
$pair_name,
116+
$pair_value,
117+
);
118+
119+
$pair_name = null;
120+
$pair_value = null;
121+
122+
$state = 'prekey';
123+
break;
124+
}
125+
}
126+
127+
if ($state == 'quoted') {
128+
throw new Exception(
129+
pht(
130+
'Header has unterminated double quote for key "%s".',
131+
$pair_name));
132+
}
133+
134+
if ($pair_name !== null) {
135+
$pairs[] = array(
136+
$pair_name,
137+
$pair_value,
138+
);
139+
}
140+
141+
return $pairs;
142+
}
143+
144+
private function requireParse() {
145+
if ($this->name === null) {
146+
throw new PhutilInvalidStateException('parseRawHeader');
147+
}
148+
}
149+
150+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
final class AphrontHTTPHeaderParserTestCase extends PhutilTestCase {
4+
5+
public function testHeaderParser() {
6+
$cases = array(
7+
array(
8+
'Key: x; y; z',
9+
'Key',
10+
'x; y; z',
11+
array(
12+
array('x', null),
13+
array('y', null),
14+
array('z', null),
15+
),
16+
),
17+
array(
18+
'Content-Disposition: form-data; name="label"',
19+
'Content-Disposition',
20+
'form-data; name="label"',
21+
array(
22+
array('form-data', null),
23+
array('name', 'label'),
24+
),
25+
),
26+
array(
27+
'Content-Type: multipart/form-data; charset=utf-8',
28+
'Content-Type',
29+
'multipart/form-data; charset=utf-8',
30+
array(
31+
array('multipart/form-data', null),
32+
array('charset', 'utf-8'),
33+
),
34+
),
35+
array(
36+
'Content-Type: application/octet-stream; charset="ut',
37+
'Content-Type',
38+
'application/octet-stream; charset="ut',
39+
false,
40+
),
41+
array(
42+
'Content-Type: multipart/form-data; boundary=ABCDEFG',
43+
'Content-Type',
44+
'multipart/form-data; boundary=ABCDEFG',
45+
array(
46+
array('multipart/form-data', null),
47+
array('boundary', 'ABCDEFG'),
48+
),
49+
),
50+
array(
51+
'Content-Type: multipart/form-data; boundary="ABCDEFG"',
52+
'Content-Type',
53+
'multipart/form-data; boundary="ABCDEFG"',
54+
array(
55+
array('multipart/form-data', null),
56+
array('boundary', 'ABCDEFG'),
57+
),
58+
),
59+
);
60+
61+
foreach ($cases as $case) {
62+
$input = $case[0];
63+
$expect_name = $case[1];
64+
$expect_content = $case[2];
65+
66+
$parser = id(new AphrontHTTPHeaderParser())
67+
->parseRawHeader($input);
68+
69+
$actual_name = $parser->getHeaderName();
70+
$actual_content = $parser->getHeaderContent();
71+
72+
$this->assertEqual(
73+
$expect_name,
74+
$actual_name,
75+
pht('Header name for: %s', $input));
76+
77+
$this->assertEqual(
78+
$expect_content,
79+
$actual_content,
80+
pht('Header content for: %s', $input));
81+
82+
if (isset($case[3])) {
83+
$expect_pairs = $case[3];
84+
85+
$caught = null;
86+
try {
87+
$actual_pairs = $parser->getHeaderContentAsPairs();
88+
} catch (Exception $ex) {
89+
$caught = $ex;
90+
}
91+
92+
if ($expect_pairs === false) {
93+
$this->assertEqual(
94+
true,
95+
($caught instanceof Exception),
96+
pht('Expect exception for header pairs of: %s', $input));
97+
} else {
98+
$this->assertEqual(
99+
$expect_pairs,
100+
$actual_pairs,
101+
pht('Header pairs for: %s', $input));
102+
}
103+
}
104+
}
105+
}
106+
107+
108+
}

0 commit comments

Comments
 (0)
Failed to load comments.