GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — develop (#1957)
by
unknown
39:18 queued 26:49
created
classes/xml/xmlquery/tags/column/UpdateColumnsTag.class.php 2 patches
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -38,8 +38,7 @@
 block discarded – undo
38 38
 			if($column->name === 'query')
39 39
 			{
40 40
 				$this->columns[] = new QueryTag($column, true);
41
-			}
42
-			else
41
+			} else
43 42
 			{
44 43
 				$this->columns[] = new UpdateColumnTag($column);
45 44
 			}
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -28,14 +28,14 @@  discard block
 block discarded – undo
28 28
 	{
29 29
 		$this->columns = array();
30 30
 
31
-		if(!is_array($xml_columns))
31
+		if (!is_array($xml_columns))
32 32
 		{
33 33
 			$xml_columns = array($xml_columns);
34 34
 		}
35 35
 
36
-		foreach($xml_columns as $column)
36
+		foreach ($xml_columns as $column)
37 37
 		{
38
-			if($column->name === 'query')
38
+			if ($column->name === 'query')
39 39
 			{
40 40
 				$this->columns[] = new QueryTag($column, true);
41 41
 			}
@@ -53,10 +53,10 @@  discard block
 block discarded – undo
53 53
 	 */
54 54
 	function toString()
55 55
 	{
56
-		$output_columns = 'array(' . PHP_EOL;
57
-		foreach($this->columns as $column)
56
+		$output_columns = 'array('.PHP_EOL;
57
+		foreach ($this->columns as $column)
58 58
 		{
59
-			$output_columns .= $column->getExpressionString() . PHP_EOL . ',';
59
+			$output_columns .= $column->getExpressionString().PHP_EOL.',';
60 60
 		}
61 61
 		$output_columns = substr($output_columns, 0, -1);
62 62
 		$output_columns .= ')';
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
 	function getArguments()
72 72
 	{
73 73
 		$arguments = array();
74
-		foreach($this->columns as $column)
74
+		foreach ($this->columns as $column)
75 75
 		{
76 76
 			$arguments[] = $column->getArgument();
77 77
 		}
Please login to merge, or discard this patch.
classes/xml/xmlquery/tags/condition/ConditionTag.class.php 2 patches
Braces   +8 added lines, -16 removed lines patch added patch discarded remove patch
@@ -78,13 +78,11 @@  discard block
 block discarded – undo
78 78
 		{
79 79
 			$this->query = new QueryTag($condition, TRUE);
80 80
 			$this->default_column = $this->query->toString();
81
-		}
82
-		else if($condition->attrs->var && !strpos($condition->attrs->var, '.'))
81
+		} else if($condition->attrs->var && !strpos($condition->attrs->var, '.'))
83 82
 		{
84 83
 			$this->argument = new QueryArgument($condition);
85 84
 			$this->argument_name = $this->argument->getArgumentName();
86
-		}
87
-		else
85
+		} else
88 86
 		{
89 87
 			if(isset($condition->attrs->default))
90 88
 			{
@@ -95,13 +93,11 @@  discard block
 block discarded – undo
95 93
 					if(strpos($default_value, "'") !== FALSE)
96 94
 					{
97 95
 						$default_value = "\"" . $default_value . "\"";
98
-					}
99
-					else
96
+					} else
100 97
 					{
101 98
 						$default_value = "'" . $default_value . "'";
102 99
 					}
103
-				}
104
-				else
100
+				} else
105 101
 				{
106 102
 					$default_value_object = new DefaultValue($this->column_name, $condition->attrs->default);
107 103
 					$default_value = $default_value_object->toString();
@@ -116,16 +112,14 @@  discard block
 block discarded – undo
116 112
 						if(strpos($default_value, "'") !== FALSE)
117 113
 						{
118 114
 							$default_value = "\"" . $default_value . "\"";
119
-						}
120
-						else
115
+						} else
121 116
 						{
122 117
 							$default_value = "'" . $default_value . "'";
123 118
 						}
124 119
 					}
125 120
 				}
126 121
 				$this->default_column = $default_value;
127
-			}
128
-			else
122
+			} else
129 123
 			{
130 124
 				$this->default_column = "'" . $dbParser->parseColumnName($condition->attrs->var) . "'";
131 125
 			}
@@ -161,8 +155,7 @@  discard block
 block discarded – undo
161 155
 							, '"' . $this->operation . '"'
162 156
 							, $this->pipe ? ", '" . $this->pipe . "'" : ''
163 157
 			);
164
-		}
165
-		else if(isset($this->default_column))
158
+		} else if(isset($this->default_column))
166 159
 		{
167 160
 			return sprintf("new ConditionWithoutArgument('%s',%s,%s%s)"
168 161
 							, $this->column_name
@@ -170,8 +163,7 @@  discard block
 block discarded – undo
170 163
 							, '"' . $this->operation . '"'
171 164
 							, $this->pipe ? ", '" . $this->pipe . "'" : ''
172 165
 			);
173
-		}
174
-		else
166
+		} else
175 167
 		{
176 168
 			return sprintf("new ConditionWithArgument('%s',%s,%s%s)"
177 169
 							, $this->column_name
Please login to merge, or discard this patch.
Spacing   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -67,38 +67,38 @@  discard block
 block discarded – undo
67 67
 		$this->column_name = $dbParser->parseExpression($condition->attrs->column);
68 68
 
69 69
 		// If default value is column name, it should be escaped
70
-		if($isColumnName = (strpos($condition->attrs->default, '.') !== FALSE
70
+		if ($isColumnName = (strpos($condition->attrs->default, '.') !== FALSE
71 71
 				&& strpos($condition->attrs->default, '.') !== 0
72
-				&& strpos($condition->attrs->default, '%') === FALSE ))
72
+				&& strpos($condition->attrs->default, '%') === FALSE))
73 73
 		{
74 74
 			$condition->attrs->default = $dbParser->parseExpression($condition->attrs->default);
75 75
 		}
76 76
 
77
-		if($condition->node_name == 'query')
77
+		if ($condition->node_name == 'query')
78 78
 		{
79 79
 			$this->query = new QueryTag($condition, TRUE);
80 80
 			$this->default_column = $this->query->toString();
81 81
 		}
82
-		else if($condition->attrs->var && !strpos($condition->attrs->var, '.'))
82
+		else if ($condition->attrs->var && !strpos($condition->attrs->var, '.'))
83 83
 		{
84 84
 			$this->argument = new QueryArgument($condition);
85 85
 			$this->argument_name = $this->argument->getArgumentName();
86 86
 		}
87 87
 		else
88 88
 		{
89
-			if(isset($condition->attrs->default))
89
+			if (isset($condition->attrs->default))
90 90
 			{
91 91
 				$operationList = array('in' => 1, 'between' => 1, 'notin' => 1, 'not_in' => 1);
92
-				if(isset($operationList[$this->operation]))
92
+				if (isset($operationList[$this->operation]))
93 93
 				{
94 94
 					$default_value = $condition->attrs->default;
95
-					if(strpos($default_value, "'") !== FALSE)
95
+					if (strpos($default_value, "'") !== FALSE)
96 96
 					{
97
-						$default_value = "\"" . $default_value . "\"";
97
+						$default_value = "\"".$default_value."\"";
98 98
 					}
99 99
 					else
100 100
 					{
101
-						$default_value = "'" . $default_value . "'";
101
+						$default_value = "'".$default_value."'";
102 102
 					}
103 103
 				}
104 104
 				else
@@ -106,20 +106,20 @@  discard block
 block discarded – undo
106 106
 					$default_value_object = new DefaultValue($this->column_name, $condition->attrs->default);
107 107
 					$default_value = $default_value_object->toString();
108 108
 
109
-					if($default_value_object->isStringFromFunction())
109
+					if ($default_value_object->isStringFromFunction())
110 110
 					{
111
-						$default_value = '"\'".' . $default_value . '."\'"';
111
+						$default_value = '"\'".'.$default_value.'."\'"';
112 112
 					}
113 113
 
114
-					if($default_value_object->isString() && !$isColumnName && !is_numeric($condition->attrs->default))
114
+					if ($default_value_object->isString() && !$isColumnName && !is_numeric($condition->attrs->default))
115 115
 					{
116
-						if(strpos($default_value, "'") !== FALSE)
116
+						if (strpos($default_value, "'") !== FALSE)
117 117
 						{
118
-							$default_value = "\"" . $default_value . "\"";
118
+							$default_value = "\"".$default_value."\"";
119 119
 						}
120 120
 						else
121 121
 						{
122
-							$default_value = "'" . $default_value . "'";
122
+							$default_value = "'".$default_value."'";
123 123
 						}
124 124
 					}
125 125
 				}
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
 			}
128 128
 			else
129 129
 			{
130
-				$this->default_column = "'" . $dbParser->parseColumnName($condition->attrs->var) . "'";
130
+				$this->default_column = "'".$dbParser->parseColumnName($condition->attrs->var)."'";
131 131
 			}
132 132
 		}
133 133
 	}
@@ -140,11 +140,11 @@  discard block
 block discarded – undo
140 140
 	function getArguments()
141 141
 	{
142 142
 		$arguments = array();
143
-		if($this->query)
143
+		if ($this->query)
144 144
 		{
145 145
 			$arguments = array_merge($arguments, $this->query->getArguments());
146 146
 		}
147
-		if($this->argument)
147
+		if ($this->argument)
148 148
 		{
149 149
 			$arguments[] = $this->argument;
150 150
 		}
@@ -153,31 +153,31 @@  discard block
 block discarded – undo
153 153
 
154 154
 	function getConditionString()
155 155
 	{
156
-		if($this->query)
156
+		if ($this->query)
157 157
 		{
158 158
 			return sprintf("new ConditionSubquery('%s',%s,%s%s)"
159 159
 							, $this->column_name
160 160
 							, $this->default_column
161
-							, '"' . $this->operation . '"'
162
-							, $this->pipe ? ", '" . $this->pipe . "'" : ''
161
+							, '"'.$this->operation.'"'
162
+							, $this->pipe ? ", '".$this->pipe."'" : ''
163 163
 			);
164 164
 		}
165
-		else if(isset($this->default_column))
165
+		else if (isset($this->default_column))
166 166
 		{
167 167
 			return sprintf("new ConditionWithoutArgument('%s',%s,%s%s)"
168 168
 							, $this->column_name
169 169
 							, $this->default_column
170
-							, '"' . $this->operation . '"'
171
-							, $this->pipe ? ", '" . $this->pipe . "'" : ''
170
+							, '"'.$this->operation.'"'
171
+							, $this->pipe ? ", '".$this->pipe."'" : ''
172 172
 			);
173 173
 		}
174 174
 		else
175 175
 		{
176 176
 			return sprintf("new ConditionWithArgument('%s',%s,%s%s)"
177 177
 							, $this->column_name
178
-							, '$' . $this->argument_name . '_argument'
179
-							, '"' . $this->operation . '"'
180
-							, $this->pipe ? ", '" . $this->pipe . "'" : ''
178
+							, '$'.$this->argument_name.'_argument'
179
+							, '"'.$this->operation.'"'
180
+							, $this->pipe ? ", '".$this->pipe."'" : ''
181 181
 			);
182 182
 		}
183 183
 	}
Please login to merge, or discard this patch.
classes/xml/xmlquery/tags/navigation/LimitTag.class.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -42,11 +42,11 @@  discard block
 block discarded – undo
42 42
 	 */
43 43
 	function LimitTag($index)
44 44
 	{
45
-		if($index->page && $index->page->attrs && $index->page_count && $index->page_count->attrs)
45
+		if ($index->page && $index->page->attrs && $index->page_count && $index->page_count->attrs)
46 46
 		{
47
-			if(!isset($index->page->attrs->default))
47
+			if (!isset($index->page->attrs->default))
48 48
 				$index->page->attrs->default = 1;
49
-			if(!isset($index->page_count->attrs->default))
49
+			if (!isset($index->page_count->attrs->default))
50 50
 				$index->page_count->attrs->default = 10;
51 51
 			$this->page = new QueryArgument($index->page);
52 52
 			$this->page_count = new QueryArgument($index->page_count);
@@ -54,7 +54,7 @@  discard block
 block discarded – undo
54 54
 			$this->arguments[] = $this->page_count;
55 55
 		}
56 56
 
57
-		if(!isset($index->list_count->attrs->default))
57
+		if (!isset($index->list_count->attrs->default))
58 58
 			$index->list_count->attrs->default = 0;
59 59
 		$this->list_count = new QueryArgument($index->list_count);
60 60
 		$this->arguments[] = $this->list_count;
@@ -62,7 +62,7 @@  discard block
 block discarded – undo
62 62
 
63 63
 	function toString()
64 64
 	{
65
-		if($this->page)
65
+		if ($this->page)
66 66
 		{
67 67
 			return sprintf('new Limit(${\'%s_argument\'}, ${\'%s_argument\'}, ${\'%s_argument\'})', $this->list_count->getArgumentName(), $this->page->getArgumentName(), $this->page_count->getArgumentName());
68 68
 		}
Please login to merge, or discard this patch.
Braces   +10 added lines, -8 removed lines patch added patch discarded remove patch
@@ -44,18 +44,21 @@  discard block
 block discarded – undo
44 44
 	{
45 45
 		if($index->page && $index->page->attrs && $index->page_count && $index->page_count->attrs)
46 46
 		{
47
-			if(!isset($index->page->attrs->default))
48
-				$index->page->attrs->default = 1;
49
-			if(!isset($index->page_count->attrs->default))
50
-				$index->page_count->attrs->default = 10;
47
+			if(!isset($index->page->attrs->default)) {
48
+							$index->page->attrs->default = 1;
49
+			}
50
+			if(!isset($index->page_count->attrs->default)) {
51
+							$index->page_count->attrs->default = 10;
52
+			}
51 53
 			$this->page = new QueryArgument($index->page);
52 54
 			$this->page_count = new QueryArgument($index->page_count);
53 55
 			$this->arguments[] = $this->page;
54 56
 			$this->arguments[] = $this->page_count;
55 57
 		}
56 58
 
57
-		if(!isset($index->list_count->attrs->default))
58
-			$index->list_count->attrs->default = 0;
59
+		if(!isset($index->list_count->attrs->default)) {
60
+					$index->list_count->attrs->default = 0;
61
+		}
59 62
 		$this->list_count = new QueryArgument($index->list_count);
60 63
 		$this->arguments[] = $this->list_count;
61 64
 	}
@@ -65,8 +68,7 @@  discard block
 block discarded – undo
65 68
 		if($this->page)
66 69
 		{
67 70
 			return sprintf('new Limit(${\'%s_argument\'}, ${\'%s_argument\'}, ${\'%s_argument\'})', $this->list_count->getArgumentName(), $this->page->getArgumentName(), $this->page_count->getArgumentName());
68
-		}
69
-		else
71
+		} else
70 72
 		{
71 73
 			return sprintf('new Limit(${\'%s_argument\'})', $this->list_count->getArgumentName());
72 74
 		}
Please login to merge, or discard this patch.
classes/xml/xmlquery/tags/navigation/NavigationTag.class.php 2 patches
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -111,8 +111,7 @@
 block discarded – undo
111 111
 		if($this->limit)
112 112
 		{
113 113
 			return $this->limit->toString();
114
-		}
115
-		else
114
+		} else
116 115
 		{
117 116
 			return "";
118 117
 		}
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -49,36 +49,36 @@  discard block
 block discarded – undo
49 49
 	function NavigationTag($xml_navigation)
50 50
 	{
51 51
 		$this->order = array();
52
-		if($xml_navigation)
52
+		if ($xml_navigation)
53 53
 		{
54 54
 			$order = $xml_navigation->index;
55
-			if($order)
55
+			if ($order)
56 56
 			{
57
-				if(!is_array($order))
57
+				if (!is_array($order))
58 58
 				{
59 59
 					$order = array($order);
60 60
 				}
61
-				foreach($order as $order_info)
61
+				foreach ($order as $order_info)
62 62
 				{
63 63
 					$this->order[] = new IndexTag($order_info);
64 64
 				}
65 65
 
66
-				if($xml_navigation->page && $xml_navigation->page->attrs || $xml_navigation->list_count && $xml_navigation->list_count->attrs)
66
+				if ($xml_navigation->page && $xml_navigation->page->attrs || $xml_navigation->list_count && $xml_navigation->list_count->attrs)
67 67
 				{
68 68
 					$this->limit = new LimitTag($xml_navigation);
69 69
 				}
70 70
 
71
-				if($xml_navigation->list_count)
71
+				if ($xml_navigation->list_count)
72 72
 				{
73 73
 					$this->list_count = $xml_navigation->list_count->attrs;
74 74
 				}
75 75
 
76
-				if($xml_navigation->page_count)
76
+				if ($xml_navigation->page_count)
77 77
 				{
78 78
 					$this->page_count = $xml_navigation->page_count->attrs;
79 79
 				}
80 80
 
81
-				if($xml_navigation->page)
81
+				if ($xml_navigation->page)
82 82
 				{
83 83
 					$this->page = $xml_navigation->page->attrs;
84 84
 				}
@@ -92,10 +92,10 @@  discard block
 block discarded – undo
92 92
 	 */
93 93
 	function getOrderByString()
94 94
 	{
95
-		$output = 'array(' . PHP_EOL;
96
-		foreach($this->order as $order)
95
+		$output = 'array('.PHP_EOL;
96
+		foreach ($this->order as $order)
97 97
 		{
98
-			$output .= $order->toString() . PHP_EOL . ',';
98
+			$output .= $order->toString().PHP_EOL.',';
99 99
 		}
100 100
 		$output = substr($output, 0, -1);
101 101
 		$output .= ')';
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
 	 */
109 109
 	function getLimitString()
110 110
 	{
111
-		if($this->limit)
111
+		if ($this->limit)
112 112
 		{
113 113
 			return $this->limit->toString();
114 114
 		}
@@ -121,11 +121,11 @@  discard block
 block discarded – undo
121 121
 	function getArguments()
122 122
 	{
123 123
 		$arguments = array();
124
-		foreach($this->order as $order)
124
+		foreach ($this->order as $order)
125 125
 		{
126 126
 			$arguments = array_merge($order->getArguments(), $arguments);
127 127
 		}
128
-		if($this->limit)
128
+		if ($this->limit)
129 129
 		{
130 130
 			$arguments = array_merge($this->limit->getArguments(), $arguments);
131 131
 		}
Please login to merge, or discard this patch.
classes/xml/xmlquery/tags/table/TablesTag.class.php 2 patches
Braces   +3 added lines, -6 removed lines patch added patch discarded remove patch
@@ -68,14 +68,12 @@  discard block
 block discarded – undo
68 68
 			if($tag->attrs->query == 'true')
69 69
 			{
70 70
 				$this->tables[] = new QueryTag($tag, true);
71
-			}
72
-			else
71
+			} else
73 72
 			{
74 73
 				if(isset($indexes[$tag->attrs->name]) && $indexes[$tag->attrs->name])
75 74
 				{
76 75
 					$this->tables[] = new HintTableTag($tag, $indexes[$tag->attrs->name]);
77
-				}
78
-				else
76
+				} else
79 77
 				{
80 78
 					$this->tables[] = new TableTag($tag);
81 79
 				}
@@ -96,8 +94,7 @@  discard block
 block discarded – undo
96 94
 			if(is_a($table, 'QueryTag'))
97 95
 			{
98 96
 				$output_tables .= $table->toString() . PHP_EOL . ',';
99
-			}
100
-			else
97
+			} else
101 98
 			{
102 99
 				$output_tables .= $table->getTableString() . PHP_EOL . ',';
103 100
 			}
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -38,21 +38,21 @@  discard block
 block discarded – undo
38 38
 		$this->tables = array();
39 39
 
40 40
 		$xml_tables = $xml_tables_tag->table;
41
-		if(!is_array($xml_tables))
41
+		if (!is_array($xml_tables))
42 42
 		{
43 43
 			$xml_tables = array($xml_tables);
44 44
 		}
45 45
 
46
-		if($xml_index_hints_tag)
46
+		if ($xml_index_hints_tag)
47 47
 		{
48 48
 			$index_nodes = $xml_index_hints_tag->index;
49
-			if(!is_array($index_nodes))
49
+			if (!is_array($index_nodes))
50 50
 			{
51 51
 				$index_nodes = array($index_nodes);
52 52
 			}
53
-			foreach($index_nodes as $index_node)
53
+			foreach ($index_nodes as $index_node)
54 54
 			{
55
-				if(!isset($indexes[$index_node->attrs->table]))
55
+				if (!isset($indexes[$index_node->attrs->table]))
56 56
 				{
57 57
 					$indexes[$index_node->attrs->table] = array();
58 58
 				}
@@ -63,15 +63,15 @@  discard block
 block discarded – undo
63 63
 			}
64 64
 		}
65 65
 
66
-		foreach($xml_tables as $tag)
66
+		foreach ($xml_tables as $tag)
67 67
 		{
68
-			if($tag->attrs->query == 'true')
68
+			if ($tag->attrs->query == 'true')
69 69
 			{
70 70
 				$this->tables[] = new QueryTag($tag, true);
71 71
 			}
72 72
 			else
73 73
 			{
74
-				if(isset($indexes[$tag->attrs->name]) && $indexes[$tag->attrs->name])
74
+				if (isset($indexes[$tag->attrs->name]) && $indexes[$tag->attrs->name])
75 75
 				{
76 76
 					$this->tables[] = new HintTableTag($tag, $indexes[$tag->attrs->name]);
77 77
 				}
@@ -90,16 +90,16 @@  discard block
 block discarded – undo
90 90
 
91 91
 	function toString()
92 92
 	{
93
-		$output_tables = 'array(' . PHP_EOL;
94
-		foreach($this->tables as $table)
93
+		$output_tables = 'array('.PHP_EOL;
94
+		foreach ($this->tables as $table)
95 95
 		{
96
-			if(is_a($table, 'QueryTag'))
96
+			if (is_a($table, 'QueryTag'))
97 97
 			{
98
-				$output_tables .= $table->toString() . PHP_EOL . ',';
98
+				$output_tables .= $table->toString().PHP_EOL.',';
99 99
 			}
100 100
 			else
101 101
 			{
102
-				$output_tables .= $table->getTableString() . PHP_EOL . ',';
102
+				$output_tables .= $table->getTableString().PHP_EOL.',';
103 103
 			}
104 104
 		}
105 105
 		$output_tables = substr($output_tables, 0, -1);
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
 	function getArguments()
111 111
 	{
112 112
 		$arguments = array();
113
-		foreach($this->tables as $table)
113
+		foreach ($this->tables as $table)
114 114
 		{
115 115
 			$arguments = array_merge($arguments, $table->getArguments());
116 116
 		}
Please login to merge, or discard this patch.
config/config.inc.php 2 patches
Braces   +6 added lines, -7 removed lines patch added patch discarded remove patch
@@ -10,8 +10,7 @@  discard block
 block discarded – undo
10 10
 if(version_compare(PHP_VERSION, '5.4.0', '<'))
11 11
 {
12 12
 	@error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED ^ E_WARNING);
13
-}
14
-else
13
+} else
15 14
 {
16 15
 	@error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED ^ E_WARNING ^ E_STRICT);
17 16
 }
@@ -56,8 +55,7 @@  discard block
 block discarded – undo
56 55
 if(file_exists(_XE_PATH_ . 'config/package.inc.php'))
57 56
 {
58 57
 	require _XE_PATH_ . 'config/package.inc.php';
59
-}
60
-else
58
+} else
61 59
 {
62 60
 	/**
63 61
 	 * Package type
@@ -398,12 +396,13 @@  discard block
 block discarded – undo
398 396
 	if(isset($GLOBALS['__xe_autoload_file_map'][strtolower($class_name)]))
399 397
 	{
400 398
 		require _XE_PATH_ . $GLOBALS['__xe_autoload_file_map'][strtolower($class_name)];
401
-	}
402
-	elseif(preg_match('/^([a-zA-Z0-9_]+?)(Admin)?(View|Controller|Model|Api|Wap|Mobile)?$/', $class_name, $matches))
399
+	} elseif(preg_match('/^([a-zA-Z0-9_]+?)(Admin)?(View|Controller|Model|Api|Wap|Mobile)?$/', $class_name, $matches))
403 400
 	{
404 401
 		$candidate_filename = array();
405 402
 		$candidate_filename[] = 'modules/' . $matches[1] . '/' . $matches[1];
406
-		if(isset($matches[2]) && $matches[2]) $candidate_filename[] = 'admin';
403
+		if(isset($matches[2]) && $matches[2]) {
404
+			$candidate_filename[] = 'admin';
405
+		}
407 406
 		$candidate_filename[] = (isset($matches[3]) && $matches[3]) ? strtolower($matches[3]) : 'class';
408 407
 		$candidate_filename[] = 'php';
409 408
 
Please login to merge, or discard this patch.
Spacing   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -7,7 +7,7 @@  discard block
 block discarded – undo
7 7
  * @file   config/config.inc.php
8 8
  * @author NAVER ([email protected])
9 9
  */
10
-if(version_compare(PHP_VERSION, '5.4.0', '<'))
10
+if (version_compare(PHP_VERSION, '5.4.0', '<'))
11 11
 {
12 12
 	@error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED ^ E_WARNING);
13 13
 }
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
 	@error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED ^ E_WARNING ^ E_STRICT);
17 17
 }
18 18
 
19
-if(!defined('__XE__'))
19
+if (!defined('__XE__'))
20 20
 {
21 21
 	exit();
22 22
 }
@@ -53,9 +53,9 @@  discard block
 block discarded – undo
53 53
 ini_set('session.use_only_cookies', 0);
54 54
 
55 55
 
56
-if(file_exists(_XE_PATH_ . 'config/package.inc.php'))
56
+if (file_exists(_XE_PATH_.'config/package.inc.php'))
57 57
 {
58
-	require _XE_PATH_ . 'config/package.inc.php';
58
+	require _XE_PATH_.'config/package.inc.php';
59 59
 }
60 60
 else
61 61
 {
@@ -97,12 +97,12 @@  discard block
 block discarded – undo
97 97
  * define('__ENABLE_PHPUNIT_TEST__', 0);
98 98
  * define('__PROXY_SERVER__', 'http://domain:port/path');
99 99
  */
100
-if(file_exists(_XE_PATH_ . 'config/config.user.inc.php'))
100
+if (file_exists(_XE_PATH_.'config/config.user.inc.php'))
101 101
 {
102
-	require _XE_PATH_ . 'config/config.user.inc.php';
102
+	require _XE_PATH_.'config/config.user.inc.php';
103 103
 }
104 104
 
105
-if(!defined('__DEBUG__'))
105
+if (!defined('__DEBUG__'))
106 106
 {
107 107
 	/**
108 108
 	 * output debug message(bit value)
@@ -117,7 +117,7 @@  discard block
 block discarded – undo
117 117
 	define('__DEBUG__', 0);
118 118
 }
119 119
 
120
-if(!defined('__DEBUG_OUTPUT__'))
120
+if (!defined('__DEBUG_OUTPUT__'))
121 121
 {
122 122
 	/**
123 123
 	 * output location of debug message
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
 	define('__DEBUG_OUTPUT__', 0);
132 132
 }
133 133
 
134
-if(!defined('__DEBUG_PROTECT__'))
134
+if (!defined('__DEBUG_PROTECT__'))
135 135
 {
136 136
 	/**
137 137
 	 * output comments of the firePHP console and browser
@@ -144,7 +144,7 @@  discard block
 block discarded – undo
144 144
 	define('__DEBUG_PROTECT__', 1);
145 145
 }
146 146
 
147
-if(!defined('__DEBUG_PROTECT_IP__'))
147
+if (!defined('__DEBUG_PROTECT_IP__'))
148 148
 {
149 149
 	/**
150 150
 	 * Set a ip address to allow debug
@@ -152,7 +152,7 @@  discard block
 block discarded – undo
152 152
 	define('__DEBUG_PROTECT_IP__', '127.0.0.1');
153 153
 }
154 154
 
155
-if(!defined('__DEBUG_DB_OUTPUT__'))
155
+if (!defined('__DEBUG_DB_OUTPUT__'))
156 156
 {
157 157
 	/**
158 158
 	 * DB error message definition
@@ -165,7 +165,7 @@  discard block
 block discarded – undo
165 165
 	define('__DEBUG_DB_OUTPUT__', 0);
166 166
 }
167 167
 
168
-if(!defined('__LOG_SLOW_QUERY__'))
168
+if (!defined('__LOG_SLOW_QUERY__'))
169 169
 {
170 170
 	/**
171 171
 	 * Query log for only timeout query among DB queries
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 	define('__LOG_SLOW_QUERY__', 0);
180 180
 }
181 181
 
182
-if(!defined('__LOG_SLOW_TRIGGER__'))
182
+if (!defined('__LOG_SLOW_TRIGGER__'))
183 183
 {
184 184
 	/**
185 185
 	 * Trigger excute time log
@@ -193,7 +193,7 @@  discard block
 block discarded – undo
193 193
 	define('__LOG_SLOW_TRIGGER__', 0);
194 194
 }
195 195
 
196
-if(!defined('__LOG_SLOW_ADDON__'))
196
+if (!defined('__LOG_SLOW_ADDON__'))
197 197
 {
198 198
 	/**
199 199
 	 * Addon excute time log
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
 	define('__LOG_SLOW_ADDON__', 0);
208 208
 }
209 209
 
210
-if(!defined('__LOG_SLOW_WIDGET__'))
210
+if (!defined('__LOG_SLOW_WIDGET__'))
211 211
 {
212 212
 	/**
213 213
 	 * Widget excute time log
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
 	define('__LOG_SLOW_WIDGET__', 0);
222 222
 }
223 223
 
224
-if(!defined('__DEBUG_QUERY__'))
224
+if (!defined('__DEBUG_QUERY__'))
225 225
 {
226 226
 	/**
227 227
 	 * Leave DB query information
@@ -234,7 +234,7 @@  discard block
 block discarded – undo
234 234
 	define('__DEBUG_QUERY__', 0);
235 235
 }
236 236
 
237
-if(!defined('__OB_GZHANDLER_ENABLE__'))
237
+if (!defined('__OB_GZHANDLER_ENABLE__'))
238 238
 {
239 239
 	/**
240 240
 	 * option to enable/disable a compression feature using ob_gzhandler
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
 	define('__OB_GZHANDLER_ENABLE__', 1);
249 249
 }
250 250
 
251
-if(!defined('__ENABLE_PHPUNIT_TEST__'))
251
+if (!defined('__ENABLE_PHPUNIT_TEST__'))
252 252
 {
253 253
 	/**
254 254
 	 * decide to use/not use the php unit test (Path/tests/index.php)
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
 	define('__ENABLE_PHPUNIT_TEST__', 0);
262 262
 }
263 263
 
264
-if(!defined('__PROXY_SERVER__'))
264
+if (!defined('__PROXY_SERVER__'))
265 265
 {
266 266
 	/**
267 267
 	 * __PROXY_SERVER__ has server information to request to the external through the target server
@@ -270,7 +270,7 @@  discard block
 block discarded – undo
270 270
 	define('__PROXY_SERVER__', NULL);
271 271
 }
272 272
 
273
-if(!defined('__ERROR_LOG__'))
273
+if (!defined('__ERROR_LOG__'))
274 274
 {
275 275
 	/**
276 276
 	 * __ERROR_LOG__ 는 PHP의 에러로그를 출력하는 기능입니다. 개발시 워닝에러이상의 에러부터 잡기 시작합니다.
@@ -282,25 +282,25 @@  discard block
 block discarded – undo
282 282
 }
283 283
 
284 284
 // Require specific files when using Firebug console output
285
-if((__DEBUG_OUTPUT__ == 2) && version_compare(PHP_VERSION, '6.0.0') === -1)
285
+if ((__DEBUG_OUTPUT__ == 2) && version_compare(PHP_VERSION, '6.0.0') === -1)
286 286
 {
287
-	require _XE_PATH_ . 'libs/FirePHPCore/FirePHP.class.php';
287
+	require _XE_PATH_.'libs/FirePHPCore/FirePHP.class.php';
288 288
 }
289 289
 
290 290
 // Set Timezone as server time
291
-if(version_compare(PHP_VERSION, '5.3.0') >= 0)
291
+if (version_compare(PHP_VERSION, '5.3.0') >= 0)
292 292
 {
293 293
 	date_default_timezone_set(@date_default_timezone_get());
294 294
 }
295 295
 
296 296
 // Require a function-defined-file for simple use
297
-require(_XE_PATH_ . 'config/func.inc.php');
297
+require(_XE_PATH_.'config/func.inc.php');
298 298
 
299
-if(__DEBUG__) {
299
+if (__DEBUG__) {
300 300
 	define('__StartTime__', getMicroTime());
301 301
 }
302 302
 
303
-if(__DEBUG__) {
303
+if (__DEBUG__) {
304 304
 	$GLOBALS['__elapsed_class_load__'] = 0;
305 305
 }
306 306
 
@@ -402,38 +402,38 @@  discard block
 block discarded – undo
402 402
 
403 403
 function __xe_autoload($class_name)
404 404
 {
405
-	if(__DEBUG__) {
405
+	if (__DEBUG__) {
406 406
 		$time_at = getMicroTime();
407 407
 	}
408 408
 
409
-	if(isset($GLOBALS['__xe_autoload_file_map'][strtolower($class_name)]))
409
+	if (isset($GLOBALS['__xe_autoload_file_map'][strtolower($class_name)]))
410 410
 	{
411
-		require _XE_PATH_ . $GLOBALS['__xe_autoload_file_map'][strtolower($class_name)];
411
+		require _XE_PATH_.$GLOBALS['__xe_autoload_file_map'][strtolower($class_name)];
412 412
 	}
413
-	elseif(preg_match('/^([a-zA-Z0-9_]+?)(Admin)?(View|Controller|Model|Api|Wap|Mobile)?$/', $class_name, $matches))
413
+	elseif (preg_match('/^([a-zA-Z0-9_]+?)(Admin)?(View|Controller|Model|Api|Wap|Mobile)?$/', $class_name, $matches))
414 414
 	{
415 415
 		$candidate_filename = array();
416
-		$candidate_filename[] = 'modules/' . $matches[1] . '/' . $matches[1];
417
-		if(isset($matches[2]) && $matches[2]) $candidate_filename[] = 'admin';
416
+		$candidate_filename[] = 'modules/'.$matches[1].'/'.$matches[1];
417
+		if (isset($matches[2]) && $matches[2]) $candidate_filename[] = 'admin';
418 418
 		$candidate_filename[] = (isset($matches[3]) && $matches[3]) ? strtolower($matches[3]) : 'class';
419 419
 		$candidate_filename[] = 'php';
420 420
 
421 421
 		$candidate_filename = implode('.', $candidate_filename);
422 422
 
423
-		if(file_exists(_XE_PATH_ . $candidate_filename))
423
+		if (file_exists(_XE_PATH_.$candidate_filename))
424 424
 		{
425
-			require _XE_PATH_ . $candidate_filename;
425
+			require _XE_PATH_.$candidate_filename;
426 426
 		}
427 427
 	}
428 428
 
429
-	if(__DEBUG__) {
429
+	if (__DEBUG__) {
430 430
 		$GLOBALS['__elapsed_class_load__'] += getMicroTime() - $time_at;
431 431
 	}
432 432
 }
433 433
 spl_autoload_register('__xe_autoload');
434 434
 
435
-if(file_exists(_XE_PATH_  . '/vendor/autoload.php')) {
436
-	require _XE_PATH_  . '/vendor/autoload.php';
435
+if (file_exists(_XE_PATH_.'/vendor/autoload.php')) {
436
+	require _XE_PATH_.'/vendor/autoload.php';
437 437
 }
438 438
 /* End of file config.inc.php */
439 439
 /* Location: ./config/config.inc.php */
Please login to merge, or discard this patch.
index.php 2 patches
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -58,8 +58,7 @@
 block discarded – undo
58 58
 		{
59 59
 			$oModuleHandler->displayContent($oModuleHandler->procModule());
60 60
 		}
61
-	}
62
-	catch(Exception $e)
61
+	} catch(Exception $e)
63 62
 	{
64 63
 		htmlHeader();
65 64
 		echo Context::getLang($e->getMessage());
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -32,11 +32,11 @@  discard block
 block discarded – undo
32 32
 /**
33 33
  * @brief Declare constants for generic use and for checking to avoid a direct call from the Web
34 34
  **/
35
-define('__XE__',   TRUE);
35
+define('__XE__', TRUE);
36 36
 /**
37 37
  * @brief Include the necessary configuration files
38 38
  **/
39
-require dirname(__FILE__) . '/config/config.inc.php';
39
+require dirname(__FILE__).'/config/config.inc.php';
40 40
 
41 41
 /**
42 42
  * @brief Initialize by creating Context object
@@ -48,18 +48,18 @@  discard block
 block discarded – undo
48 48
 /**
49 49
  * @brief If default_url is set and it is different from the current url, attempt to redirect for SSO authentication and then process the module
50 50
  **/
51
-if($oContext->checkSSO())
51
+if ($oContext->checkSSO())
52 52
 {
53 53
 	$oModuleHandler = new ModuleHandler();
54 54
 
55 55
 	try
56 56
 	{
57
-		if($oModuleHandler->init())
57
+		if ($oModuleHandler->init())
58 58
 		{
59 59
 			$oModuleHandler->displayContent($oModuleHandler->procModule());
60 60
 		}
61 61
 	}
62
-	catch(Exception $e)
62
+	catch (Exception $e)
63 63
 	{
64 64
 		htmlHeader();
65 65
 		echo Context::getLang($e->getMessage());
Please login to merge, or discard this patch.
libs/PEAR.1.9.5/HTTP/Request2.php 3 patches
Indentation   +977 added lines, -977 removed lines patch added patch discarded remove patch
@@ -41,990 +41,990 @@
 block discarded – undo
41 41
  */
42 42
 class HTTP_Request2 implements SplSubject
43 43
 {
44
-    /**#@+
44
+	/**#@+
45 45
      * Constants for HTTP request methods
46 46
      *
47 47
      * @link http://tools.ietf.org/html/rfc2616#section-5.1.1
48 48
      */
49
-    const METHOD_OPTIONS = 'OPTIONS';
50
-    const METHOD_GET     = 'GET';
51
-    const METHOD_HEAD    = 'HEAD';
52
-    const METHOD_POST    = 'POST';
53
-    const METHOD_PUT     = 'PUT';
54
-    const METHOD_DELETE  = 'DELETE';
55
-    const METHOD_TRACE   = 'TRACE';
56
-    const METHOD_CONNECT = 'CONNECT';
57
-    /**#@-*/
58
-
59
-    /**#@+
49
+	const METHOD_OPTIONS = 'OPTIONS';
50
+	const METHOD_GET     = 'GET';
51
+	const METHOD_HEAD    = 'HEAD';
52
+	const METHOD_POST    = 'POST';
53
+	const METHOD_PUT     = 'PUT';
54
+	const METHOD_DELETE  = 'DELETE';
55
+	const METHOD_TRACE   = 'TRACE';
56
+	const METHOD_CONNECT = 'CONNECT';
57
+	/**#@-*/
58
+
59
+	/**#@+
60 60
      * Constants for HTTP authentication schemes
61 61
      *
62 62
      * @link http://tools.ietf.org/html/rfc2617
63 63
      */
64
-    const AUTH_BASIC  = 'basic';
65
-    const AUTH_DIGEST = 'digest';
66
-    /**#@-*/
67
-
68
-    /**
69
-     * Regular expression used to check for invalid symbols in RFC 2616 tokens
70
-     * @link http://pear.php.net/bugs/bug.php?id=15630
71
-     */
72
-    const REGEXP_INVALID_TOKEN = '![\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]!';
73
-
74
-    /**
75
-     * Regular expression used to check for invalid symbols in cookie strings
76
-     * @link http://pear.php.net/bugs/bug.php?id=15630
77
-     * @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html
78
-     */
79
-    const REGEXP_INVALID_COOKIE = '/[\s,;]/';
80
-
81
-    /**
82
-     * Fileinfo magic database resource
83
-     * @var  resource
84
-     * @see  detectMimeType()
85
-     */
86
-    private static $_fileinfoDb;
87
-
88
-    /**
89
-     * Observers attached to the request (instances of SplObserver)
90
-     * @var  array
91
-     */
92
-    protected $observers = array();
93
-
94
-    /**
95
-     * Request URL
96
-     * @var  Net_URL2
97
-     */
98
-    protected $url;
99
-
100
-    /**
101
-     * Request method
102
-     * @var  string
103
-     */
104
-    protected $method = self::METHOD_GET;
105
-
106
-    /**
107
-     * Authentication data
108
-     * @var  array
109
-     * @see  getAuth()
110
-     */
111
-    protected $auth;
112
-
113
-    /**
114
-     * Request headers
115
-     * @var  array
116
-     */
117
-    protected $headers = array();
118
-
119
-    /**
120
-     * Configuration parameters
121
-     * @var  array
122
-     * @see  setConfig()
123
-     */
124
-    protected $config = array(
125
-        'adapter'           => 'HTTP_Request2_Adapter_Socket',
126
-        'connect_timeout'   => 10,
127
-        'timeout'           => 0,
128
-        'use_brackets'      => true,
129
-        'protocol_version'  => '1.1',
130
-        'buffer_size'       => 16384,
131
-        'store_body'        => true,
132
-        'local_ip'          => null,
133
-
134
-        'proxy_host'        => '',
135
-        'proxy_port'        => '',
136
-        'proxy_user'        => '',
137
-        'proxy_password'    => '',
138
-        'proxy_auth_scheme' => self::AUTH_BASIC,
139
-        'proxy_type'        => 'http',
140
-
141
-        'ssl_verify_peer'   => true,
142
-        'ssl_verify_host'   => true,
143
-        'ssl_cafile'        => null,
144
-        'ssl_capath'        => null,
145
-        'ssl_local_cert'    => null,
146
-        'ssl_passphrase'    => null,
147
-
148
-        'digest_compat_ie'  => false,
149
-
150
-        'follow_redirects'  => false,
151
-        'max_redirects'     => 5,
152
-        'strict_redirects'  => false
153
-    );
154
-
155
-    /**
156
-     * Last event in request / response handling, intended for observers
157
-     * @var  array
158
-     * @see  getLastEvent()
159
-     */
160
-    protected $lastEvent = array(
161
-        'name' => 'start',
162
-        'data' => null
163
-    );
164
-
165
-    /**
166
-     * Request body
167
-     * @var  string|resource
168
-     * @see  setBody()
169
-     */
170
-    protected $body = '';
171
-
172
-    /**
173
-     * Array of POST parameters
174
-     * @var  array
175
-     */
176
-    protected $postParams = array();
177
-
178
-    /**
179
-     * Array of file uploads (for multipart/form-data POST requests)
180
-     * @var  array
181
-     */
182
-    protected $uploads = array();
183
-
184
-    /**
185
-     * Adapter used to perform actual HTTP request
186
-     * @var  HTTP_Request2_Adapter
187
-     */
188
-    protected $adapter;
189
-
190
-    /**
191
-     * Cookie jar to persist cookies between requests
192
-     * @var HTTP_Request2_CookieJar
193
-     */
194
-    protected $cookieJar = null;
195
-
196
-    /**
197
-     * Constructor. Can set request URL, method and configuration array.
198
-     *
199
-     * Also sets a default value for User-Agent header.
200
-     *
201
-     * @param string|Net_Url2 $url    Request URL
202
-     * @param string          $method Request method
203
-     * @param array           $config Configuration for this Request instance
204
-     */
205
-    public function __construct(
206
-        $url = null, $method = self::METHOD_GET, array $config = array()
207
-    ) {
208
-        $this->setConfig($config);
209
-        if (!empty($url)) {
210
-            $this->setUrl($url);
211
-        }
212
-        if (!empty($method)) {
213
-            $this->setMethod($method);
214
-        }
215
-        $this->setHeader(
216
-            'user-agent', 'HTTP_Request2/2.2.1 ' .
217
-            '(http://pear.php.net/package/http_request2) PHP/' . phpversion()
218
-        );
219
-    }
220
-
221
-    /**
222
-     * Sets the URL for this request
223
-     *
224
-     * If the URL has userinfo part (username & password) these will be removed
225
-     * and converted to auth data. If the URL does not have a path component,
226
-     * that will be set to '/'.
227
-     *
228
-     * @param string|Net_URL2 $url Request URL
229
-     *
230
-     * @return   HTTP_Request2
231
-     * @throws   HTTP_Request2_LogicException
232
-     */
233
-    public function setUrl($url)
234
-    {
235
-        if (is_string($url)) {
236
-            $url = new Net_URL2(
237
-                $url, array(Net_URL2::OPTION_USE_BRACKETS => $this->config['use_brackets'])
238
-            );
239
-        }
240
-        if (!$url instanceof Net_URL2) {
241
-            throw new HTTP_Request2_LogicException(
242
-                'Parameter is not a valid HTTP URL',
243
-                HTTP_Request2_Exception::INVALID_ARGUMENT
244
-            );
245
-        }
246
-        // URL contains username / password?
247
-        if ($url->getUserinfo()) {
248
-            $username = $url->getUser();
249
-            $password = $url->getPassword();
250
-            $this->setAuth(rawurldecode($username), $password? rawurldecode($password): '');
251
-            $url->setUserinfo('');
252
-        }
253
-        if ('' == $url->getPath()) {
254
-            $url->setPath('/');
255
-        }
256
-        $this->url = $url;
257
-
258
-        return $this;
259
-    }
260
-
261
-    /**
262
-     * Returns the request URL
263
-     *
264
-     * @return   Net_URL2
265
-     */
266
-    public function getUrl()
267
-    {
268
-        return $this->url;
269
-    }
270
-
271
-    /**
272
-     * Sets the request method
273
-     *
274
-     * @param string $method one of the methods defined in RFC 2616
275
-     *
276
-     * @return   HTTP_Request2
277
-     * @throws   HTTP_Request2_LogicException if the method name is invalid
278
-     */
279
-    public function setMethod($method)
280
-    {
281
-        // Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1
282
-        if (preg_match(self::REGEXP_INVALID_TOKEN, $method)) {
283
-            throw new HTTP_Request2_LogicException(
284
-                "Invalid request method '{$method}'",
285
-                HTTP_Request2_Exception::INVALID_ARGUMENT
286
-            );
287
-        }
288
-        $this->method = $method;
289
-
290
-        return $this;
291
-    }
292
-
293
-    /**
294
-     * Returns the request method
295
-     *
296
-     * @return   string
297
-     */
298
-    public function getMethod()
299
-    {
300
-        return $this->method;
301
-    }
302
-
303
-    /**
304
-     * Sets the configuration parameter(s)
305
-     *
306
-     * The following parameters are available:
307
-     * <ul>
308
-     *   <li> 'adapter'           - adapter to use (string)</li>
309
-     *   <li> 'connect_timeout'   - Connection timeout in seconds (integer)</li>
310
-     *   <li> 'timeout'           - Total number of seconds a request can take.
311
-     *                              Use 0 for no limit, should be greater than
312
-     *                              'connect_timeout' if set (integer)</li>
313
-     *   <li> 'use_brackets'      - Whether to append [] to array variable names (bool)</li>
314
-     *   <li> 'protocol_version'  - HTTP Version to use, '1.0' or '1.1' (string)</li>
315
-     *   <li> 'buffer_size'       - Buffer size to use for reading and writing (int)</li>
316
-     *   <li> 'store_body'        - Whether to store response body in response object.
317
-     *                              Set to false if receiving a huge response and
318
-     *                              using an Observer to save it (boolean)</li>
319
-     *   <li> 'local_ip'          - Specifies the IP address that will be used for accessing
320
-     *                              the network (string)</li>
321
-     *   <li> 'proxy_type'        - Proxy type, 'http' or 'socks5' (string)</li>
322
-     *   <li> 'proxy_host'        - Proxy server host (string)</li>
323
-     *   <li> 'proxy_port'        - Proxy server port (integer)</li>
324
-     *   <li> 'proxy_user'        - Proxy auth username (string)</li>
325
-     *   <li> 'proxy_password'    - Proxy auth password (string)</li>
326
-     *   <li> 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)</li>
327
-     *   <li> 'proxy'             - Shorthand for proxy_* parameters, proxy given as URL,
328
-     *                              e.g. 'socks5://localhost:1080/' (string)</li>
329
-     *   <li> 'ssl_verify_peer'   - Whether to verify peer's SSL certificate (bool)</li>
330
-     *   <li> 'ssl_verify_host'   - Whether to check that Common Name in SSL
331
-     *                              certificate matches host name (bool)</li>
332
-     *   <li> 'ssl_cafile'        - Cerificate Authority file to verify the peer
333
-     *                              with (use with 'ssl_verify_peer') (string)</li>
334
-     *   <li> 'ssl_capath'        - Directory holding multiple Certificate
335
-     *                              Authority files (string)</li>
336
-     *   <li> 'ssl_local_cert'    - Name of a file containing local cerificate (string)</li>
337
-     *   <li> 'ssl_passphrase'    - Passphrase with which local certificate
338
-     *                              was encoded (string)</li>
339
-     *   <li> 'digest_compat_ie'  - Whether to imitate behaviour of MSIE 5 and 6
340
-     *                              in using URL without query string in digest
341
-     *                              authentication (boolean)</li>
342
-     *   <li> 'follow_redirects'  - Whether to automatically follow HTTP Redirects (boolean)</li>
343
-     *   <li> 'max_redirects'     - Maximum number of redirects to follow (integer)</li>
344
-     *   <li> 'strict_redirects'  - Whether to keep request method on redirects via status 301 and
345
-     *                              302 (true, needed for compatibility with RFC 2616)
346
-     *                              or switch to GET (false, needed for compatibility with most
347
-     *                              browsers) (boolean)</li>
348
-     * </ul>
349
-     *
350
-     * @param string|array $nameOrConfig configuration parameter name or array
351
-     *                                   ('parameter name' => 'parameter value')
352
-     * @param mixed        $value        parameter value if $nameOrConfig is not an array
353
-     *
354
-     * @return   HTTP_Request2
355
-     * @throws   HTTP_Request2_LogicException If the parameter is unknown
356
-     */
357
-    public function setConfig($nameOrConfig, $value = null)
358
-    {
359
-        if (is_array($nameOrConfig)) {
360
-            foreach ($nameOrConfig as $name => $value) {
361
-                $this->setConfig($name, $value);
362
-            }
363
-
364
-        } elseif ('proxy' == $nameOrConfig) {
365
-            $url = new Net_URL2($value);
366
-            $this->setConfig(array(
367
-                'proxy_type'     => $url->getScheme(),
368
-                'proxy_host'     => $url->getHost(),
369
-                'proxy_port'     => $url->getPort(),
370
-                'proxy_user'     => rawurldecode($url->getUser()),
371
-                'proxy_password' => rawurldecode($url->getPassword())
372
-            ));
373
-
374
-        } else {
375
-            if (!array_key_exists($nameOrConfig, $this->config)) {
376
-                throw new HTTP_Request2_LogicException(
377
-                    "Unknown configuration parameter '{$nameOrConfig}'",
378
-                    HTTP_Request2_Exception::INVALID_ARGUMENT
379
-                );
380
-            }
381
-            $this->config[$nameOrConfig] = $value;
382
-        }
383
-
384
-        return $this;
385
-    }
386
-
387
-    /**
388
-     * Returns the value(s) of the configuration parameter(s)
389
-     *
390
-     * @param string $name parameter name
391
-     *
392
-     * @return   mixed   value of $name parameter, array of all configuration
393
-     *                   parameters if $name is not given
394
-     * @throws   HTTP_Request2_LogicException If the parameter is unknown
395
-     */
396
-    public function getConfig($name = null)
397
-    {
398
-        if (null === $name) {
399
-            return $this->config;
400
-        } elseif (!array_key_exists($name, $this->config)) {
401
-            throw new HTTP_Request2_LogicException(
402
-                "Unknown configuration parameter '{$name}'",
403
-                HTTP_Request2_Exception::INVALID_ARGUMENT
404
-            );
405
-        }
406
-        return $this->config[$name];
407
-    }
408
-
409
-    /**
410
-     * Sets the autentification data
411
-     *
412
-     * @param string $user     user name
413
-     * @param string $password password
414
-     * @param string $scheme   authentication scheme
415
-     *
416
-     * @return   HTTP_Request2
417
-     */
418
-    public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC)
419
-    {
420
-        if (empty($user)) {
421
-            $this->auth = null;
422
-        } else {
423
-            $this->auth = array(
424
-                'user'     => (string)$user,
425
-                'password' => (string)$password,
426
-                'scheme'   => $scheme
427
-            );
428
-        }
429
-
430
-        return $this;
431
-    }
432
-
433
-    /**
434
-     * Returns the authentication data
435
-     *
436
-     * The array has the keys 'user', 'password' and 'scheme', where 'scheme'
437
-     * is one of the HTTP_Request2::AUTH_* constants.
438
-     *
439
-     * @return   array
440
-     */
441
-    public function getAuth()
442
-    {
443
-        return $this->auth;
444
-    }
445
-
446
-    /**
447
-     * Sets request header(s)
448
-     *
449
-     * The first parameter may be either a full header string 'header: value' or
450
-     * header name. In the former case $value parameter is ignored, in the latter
451
-     * the header's value will either be set to $value or the header will be
452
-     * removed if $value is null. The first parameter can also be an array of
453
-     * headers, in that case method will be called recursively.
454
-     *
455
-     * Note that headers are treated case insensitively as per RFC 2616.
456
-     *
457
-     * <code>
458
-     * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar'
459
-     * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz'
460
-     * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux'
461
-     * $req->setHeader('FOO'); // removes 'Foo' header from request
462
-     * </code>
463
-     *
464
-     * @param string|array      $name    header name, header string ('Header: value')
465
-     *                                   or an array of headers
466
-     * @param string|array|null $value   header value if $name is not an array,
467
-     *                                   header will be removed if value is null
468
-     * @param bool              $replace whether to replace previous header with the
469
-     *                                   same name or append to its value
470
-     *
471
-     * @return   HTTP_Request2
472
-     * @throws   HTTP_Request2_LogicException
473
-     */
474
-    public function setHeader($name, $value = null, $replace = true)
475
-    {
476
-        if (is_array($name)) {
477
-            foreach ($name as $k => $v) {
478
-                if (is_string($k)) {
479
-                    $this->setHeader($k, $v, $replace);
480
-                } else {
481
-                    $this->setHeader($v, null, $replace);
482
-                }
483
-            }
484
-        } else {
485
-            if (null === $value && strpos($name, ':')) {
486
-                list($name, $value) = array_map('trim', explode(':', $name, 2));
487
-            }
488
-            // Header name should be a token: http://tools.ietf.org/html/rfc2616#section-4.2
489
-            if (preg_match(self::REGEXP_INVALID_TOKEN, $name)) {
490
-                throw new HTTP_Request2_LogicException(
491
-                    "Invalid header name '{$name}'",
492
-                    HTTP_Request2_Exception::INVALID_ARGUMENT
493
-                );
494
-            }
495
-            // Header names are case insensitive anyway
496
-            $name = strtolower($name);
497
-            if (null === $value) {
498
-                unset($this->headers[$name]);
499
-
500
-            } else {
501
-                if (is_array($value)) {
502
-                    $value = implode(', ', array_map('trim', $value));
503
-                } elseif (is_string($value)) {
504
-                    $value = trim($value);
505
-                }
506
-                if (!isset($this->headers[$name]) || $replace) {
507
-                    $this->headers[$name] = $value;
508
-                } else {
509
-                    $this->headers[$name] .= ', ' . $value;
510
-                }
511
-            }
512
-        }
513
-
514
-        return $this;
515
-    }
516
-
517
-    /**
518
-     * Returns the request headers
519
-     *
520
-     * The array is of the form ('header name' => 'header value'), header names
521
-     * are lowercased
522
-     *
523
-     * @return   array
524
-     */
525
-    public function getHeaders()
526
-    {
527
-        return $this->headers;
528
-    }
529
-
530
-    /**
531
-     * Adds a cookie to the request
532
-     *
533
-     * If the request does not have a CookieJar object set, this method simply
534
-     * appends a cookie to "Cookie:" header.
535
-     *
536
-     * If a CookieJar object is available, the cookie is stored in that object.
537
-     * Data from request URL will be used for setting its 'domain' and 'path'
538
-     * parameters, 'expires' and 'secure' will be set to null and false,
539
-     * respectively. If you need further control, use CookieJar's methods.
540
-     *
541
-     * @param string $name  cookie name
542
-     * @param string $value cookie value
543
-     *
544
-     * @return   HTTP_Request2
545
-     * @throws   HTTP_Request2_LogicException
546
-     * @see      setCookieJar()
547
-     */
548
-    public function addCookie($name, $value)
549
-    {
550
-        if (!empty($this->cookieJar)) {
551
-            $this->cookieJar->store(
552
-                array('name' => $name, 'value' => $value), $this->url
553
-            );
554
-
555
-        } else {
556
-            $cookie = $name . '=' . $value;
557
-            if (preg_match(self::REGEXP_INVALID_COOKIE, $cookie)) {
558
-                throw new HTTP_Request2_LogicException(
559
-                    "Invalid cookie: '{$cookie}'",
560
-                    HTTP_Request2_Exception::INVALID_ARGUMENT
561
-                );
562
-            }
563
-            $cookies = empty($this->headers['cookie'])? '': $this->headers['cookie'] . '; ';
564
-            $this->setHeader('cookie', $cookies . $cookie);
565
-        }
566
-
567
-        return $this;
568
-    }
569
-
570
-    /**
571
-     * Sets the request body
572
-     *
573
-     * If you provide file pointer rather than file name, it should support
574
-     * fstat() and rewind() operations.
575
-     *
576
-     * @param string|resource|HTTP_Request2_MultipartBody $body       Either a
577
-     *               string with the body or filename containing body or
578
-     *               pointer to an open file or object with multipart body data
579
-     * @param bool                                        $isFilename Whether
580
-     *               first parameter is a filename
581
-     *
582
-     * @return   HTTP_Request2
583
-     * @throws   HTTP_Request2_LogicException
584
-     */
585
-    public function setBody($body, $isFilename = false)
586
-    {
587
-        if (!$isFilename && !is_resource($body)) {
588
-            if (!$body instanceof HTTP_Request2_MultipartBody) {
589
-                $this->body = (string)$body;
590
-            } else {
591
-                $this->body = $body;
592
-            }
593
-        } else {
594
-            $fileData = $this->fopenWrapper($body, empty($this->headers['content-type']));
595
-            $this->body = $fileData['fp'];
596
-            if (empty($this->headers['content-type'])) {
597
-                $this->setHeader('content-type', $fileData['type']);
598
-            }
599
-        }
600
-        $this->postParams = $this->uploads = array();
601
-
602
-        return $this;
603
-    }
604
-
605
-    /**
606
-     * Returns the request body
607
-     *
608
-     * @return   string|resource|HTTP_Request2_MultipartBody
609
-     */
610
-    public function getBody()
611
-    {
612
-        if (self::METHOD_POST == $this->method
613
-            && (!empty($this->postParams) || !empty($this->uploads))
614
-        ) {
615
-            if (0 === strpos($this->headers['content-type'], 'application/x-www-form-urlencoded')) {
616
-                $body = http_build_query($this->postParams, '', '&');
617
-                if (!$this->getConfig('use_brackets')) {
618
-                    $body = preg_replace('/%5B\d+%5D=/', '=', $body);
619
-                }
620
-                // support RFC 3986 by not encoding '~' symbol (request #15368)
621
-                return str_replace('%7E', '~', $body);
622
-
623
-            } elseif (0 === strpos($this->headers['content-type'], 'multipart/form-data')) {
624
-                require_once 'HTTP/Request2/MultipartBody.php';
625
-                return new HTTP_Request2_MultipartBody(
626
-                    $this->postParams, $this->uploads, $this->getConfig('use_brackets')
627
-                );
628
-            }
629
-        }
630
-        return $this->body;
631
-    }
632
-
633
-    /**
634
-     * Adds a file to form-based file upload
635
-     *
636
-     * Used to emulate file upload via a HTML form. The method also sets
637
-     * Content-Type of HTTP request to 'multipart/form-data'.
638
-     *
639
-     * If you just want to send the contents of a file as the body of HTTP
640
-     * request you should use setBody() method.
641
-     *
642
-     * If you provide file pointers rather than file names, they should support
643
-     * fstat() and rewind() operations.
644
-     *
645
-     * @param string                $fieldName    name of file-upload field
646
-     * @param string|resource|array $filename     full name of local file,
647
-     *               pointer to open file or an array of files
648
-     * @param string                $sendFilename filename to send in the request
649
-     * @param string                $contentType  content-type of file being uploaded
650
-     *
651
-     * @return   HTTP_Request2
652
-     * @throws   HTTP_Request2_LogicException
653
-     */
654
-    public function addUpload(
655
-        $fieldName, $filename, $sendFilename = null, $contentType = null
656
-    ) {
657
-        if (!is_array($filename)) {
658
-            $fileData = $this->fopenWrapper($filename, empty($contentType));
659
-            $this->uploads[$fieldName] = array(
660
-                'fp'        => $fileData['fp'],
661
-                'filename'  => !empty($sendFilename)? $sendFilename
662
-                                :(is_string($filename)? basename($filename): 'anonymous.blob') ,
663
-                'size'      => $fileData['size'],
664
-                'type'      => empty($contentType)? $fileData['type']: $contentType
665
-            );
666
-        } else {
667
-            $fps = $names = $sizes = $types = array();
668
-            foreach ($filename as $f) {
669
-                if (!is_array($f)) {
670
-                    $f = array($f);
671
-                }
672
-                $fileData = $this->fopenWrapper($f[0], empty($f[2]));
673
-                $fps[]   = $fileData['fp'];
674
-                $names[] = !empty($f[1])? $f[1]
675
-                            :(is_string($f[0])? basename($f[0]): 'anonymous.blob');
676
-                $sizes[] = $fileData['size'];
677
-                $types[] = empty($f[2])? $fileData['type']: $f[2];
678
-            }
679
-            $this->uploads[$fieldName] = array(
680
-                'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types
681
-            );
682
-        }
683
-        if (empty($this->headers['content-type'])
684
-            || 'application/x-www-form-urlencoded' == $this->headers['content-type']
685
-        ) {
686
-            $this->setHeader('content-type', 'multipart/form-data');
687
-        }
688
-
689
-        return $this;
690
-    }
691
-
692
-    /**
693
-     * Adds POST parameter(s) to the request.
694
-     *
695
-     * @param string|array $name  parameter name or array ('name' => 'value')
696
-     * @param mixed        $value parameter value (can be an array)
697
-     *
698
-     * @return   HTTP_Request2
699
-     */
700
-    public function addPostParameter($name, $value = null)
701
-    {
702
-        if (!is_array($name)) {
703
-            $this->postParams[$name] = $value;
704
-        } else {
705
-            foreach ($name as $k => $v) {
706
-                $this->addPostParameter($k, $v);
707
-            }
708
-        }
709
-        if (empty($this->headers['content-type'])) {
710
-            $this->setHeader('content-type', 'application/x-www-form-urlencoded');
711
-        }
712
-
713
-        return $this;
714
-    }
715
-
716
-    /**
717
-     * Attaches a new observer
718
-     *
719
-     * @param SplObserver $observer any object implementing SplObserver
720
-     */
721
-    public function attach(SplObserver $observer)
722
-    {
723
-        foreach ($this->observers as $attached) {
724
-            if ($attached === $observer) {
725
-                return;
726
-            }
727
-        }
728
-        $this->observers[] = $observer;
729
-    }
730
-
731
-    /**
732
-     * Detaches an existing observer
733
-     *
734
-     * @param SplObserver $observer any object implementing SplObserver
735
-     */
736
-    public function detach(SplObserver $observer)
737
-    {
738
-        foreach ($this->observers as $key => $attached) {
739
-            if ($attached === $observer) {
740
-                unset($this->observers[$key]);
741
-                return;
742
-            }
743
-        }
744
-    }
745
-
746
-    /**
747
-     * Notifies all observers
748
-     */
749
-    public function notify()
750
-    {
751
-        foreach ($this->observers as $observer) {
752
-            $observer->update($this);
753
-        }
754
-    }
755
-
756
-    /**
757
-     * Sets the last event
758
-     *
759
-     * Adapters should use this method to set the current state of the request
760
-     * and notify the observers.
761
-     *
762
-     * @param string $name event name
763
-     * @param mixed  $data event data
764
-     */
765
-    public function setLastEvent($name, $data = null)
766
-    {
767
-        $this->lastEvent = array(
768
-            'name' => $name,
769
-            'data' => $data
770
-        );
771
-        $this->notify();
772
-    }
773
-
774
-    /**
775
-     * Returns the last event
776
-     *
777
-     * Observers should use this method to access the last change in request.
778
-     * The following event names are possible:
779
-     * <ul>
780
-     *   <li>'connect'                 - after connection to remote server,
781
-     *                                   data is the destination (string)</li>
782
-     *   <li>'disconnect'              - after disconnection from server</li>
783
-     *   <li>'sentHeaders'             - after sending the request headers,
784
-     *                                   data is the headers sent (string)</li>
785
-     *   <li>'sentBodyPart'            - after sending a part of the request body,
786
-     *                                   data is the length of that part (int)</li>
787
-     *   <li>'sentBody'                - after sending the whole request body,
788
-     *                                   data is request body length (int)</li>
789
-     *   <li>'receivedHeaders'         - after receiving the response headers,
790
-     *                                   data is HTTP_Request2_Response object</li>
791
-     *   <li>'receivedBodyPart'        - after receiving a part of the response
792
-     *                                   body, data is that part (string)</li>
793
-     *   <li>'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still
794
-     *                                   encoded by Content-Encoding</li>
795
-     *   <li>'receivedBody'            - after receiving the complete response
796
-     *                                   body, data is HTTP_Request2_Response object</li>
797
-     * </ul>
798
-     * Different adapters may not send all the event types. Mock adapter does
799
-     * not send any events to the observers.
800
-     *
801
-     * @return   array   The array has two keys: 'name' and 'data'
802
-     */
803
-    public function getLastEvent()
804
-    {
805
-        return $this->lastEvent;
806
-    }
807
-
808
-    /**
809
-     * Sets the adapter used to actually perform the request
810
-     *
811
-     * You can pass either an instance of a class implementing HTTP_Request2_Adapter
812
-     * or a class name. The method will only try to include a file if the class
813
-     * name starts with HTTP_Request2_Adapter_, it will also try to prepend this
814
-     * prefix to the class name if it doesn't contain any underscores, so that
815
-     * <code>
816
-     * $request->setAdapter('curl');
817
-     * </code>
818
-     * will work.
819
-     *
820
-     * @param string|HTTP_Request2_Adapter $adapter Adapter to use
821
-     *
822
-     * @return   HTTP_Request2
823
-     * @throws   HTTP_Request2_LogicException
824
-     */
825
-    public function setAdapter($adapter)
826
-    {
827
-        if (is_string($adapter)) {
828
-            if (!class_exists($adapter, false)) {
829
-                if (false === strpos($adapter, '_')) {
830
-                    $adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter);
831
-                }
832
-                if (!class_exists($adapter, false)
833
-                    && preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)
834
-                ) {
835
-                    include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php';
836
-                }
837
-                if (!class_exists($adapter, false)) {
838
-                    throw new HTTP_Request2_LogicException(
839
-                        "Class {$adapter} not found",
840
-                        HTTP_Request2_Exception::MISSING_VALUE
841
-                    );
842
-                }
843
-            }
844
-            $adapter = new $adapter;
845
-        }
846
-        if (!$adapter instanceof HTTP_Request2_Adapter) {
847
-            throw new HTTP_Request2_LogicException(
848
-                'Parameter is not a HTTP request adapter',
849
-                HTTP_Request2_Exception::INVALID_ARGUMENT
850
-            );
851
-        }
852
-        $this->adapter = $adapter;
853
-
854
-        return $this;
855
-    }
856
-
857
-    /**
858
-     * Sets the cookie jar
859
-     *
860
-     * A cookie jar is used to maintain cookies across HTTP requests and
861
-     * responses. Cookies from jar will be automatically added to the request
862
-     * headers based on request URL.
863
-     *
864
-     * @param HTTP_Request2_CookieJar|bool $jar Existing CookieJar object, true to
865
-     *                                          create a new one, false to remove
866
-     *
867
-     * @return HTTP_Request2
868
-     * @throws HTTP_Request2_LogicException
869
-     */
870
-    public function setCookieJar($jar = true)
871
-    {
872
-        if (!class_exists('HTTP_Request2_CookieJar', false)) {
873
-            require_once 'HTTP/Request2/CookieJar.php';
874
-        }
875
-
876
-        if ($jar instanceof HTTP_Request2_CookieJar) {
877
-            $this->cookieJar = $jar;
878
-        } elseif (true === $jar) {
879
-            $this->cookieJar = new HTTP_Request2_CookieJar();
880
-        } elseif (!$jar) {
881
-            $this->cookieJar = null;
882
-        } else {
883
-            throw new HTTP_Request2_LogicException(
884
-                'Invalid parameter passed to setCookieJar()',
885
-                HTTP_Request2_Exception::INVALID_ARGUMENT
886
-            );
887
-        }
888
-
889
-        return $this;
890
-    }
891
-
892
-    /**
893
-     * Returns current CookieJar object or null if none
894
-     *
895
-     * @return HTTP_Request2_CookieJar|null
896
-     */
897
-    public function getCookieJar()
898
-    {
899
-        return $this->cookieJar;
900
-    }
901
-
902
-    /**
903
-     * Sends the request and returns the response
904
-     *
905
-     * @throws   HTTP_Request2_Exception
906
-     * @return   HTTP_Request2_Response
907
-     */
908
-    public function send()
909
-    {
910
-        // Sanity check for URL
911
-        if (!$this->url instanceof Net_URL2
912
-            || !$this->url->isAbsolute()
913
-            || !in_array(strtolower($this->url->getScheme()), array('https', 'http'))
914
-        ) {
915
-            throw new HTTP_Request2_LogicException(
916
-                'HTTP_Request2 needs an absolute HTTP(S) request URL, '
917
-                . ($this->url instanceof Net_URL2
918
-                   ? "'" . $this->url->__toString() . "'" : 'none')
919
-                . ' given',
920
-                HTTP_Request2_Exception::INVALID_ARGUMENT
921
-            );
922
-        }
923
-        if (empty($this->adapter)) {
924
-            $this->setAdapter($this->getConfig('adapter'));
925
-        }
926
-        // magic_quotes_runtime may break file uploads and chunked response
927
-        // processing; see bug #4543. Don't use ini_get() here; see bug #16440.
928
-        if ($magicQuotes = get_magic_quotes_runtime()) {
929
-            set_magic_quotes_runtime(false);
930
-        }
931
-        // force using single byte encoding if mbstring extension overloads
932
-        // strlen() and substr(); see bug #1781, bug #10605
933
-        if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
934
-            $oldEncoding = mb_internal_encoding();
935
-            mb_internal_encoding('8bit');
936
-        }
937
-
938
-        try {
939
-            $response = $this->adapter->sendRequest($this);
940
-        } catch (Exception $e) {
941
-        }
942
-        // cleanup in either case (poor man's "finally" clause)
943
-        if ($magicQuotes) {
944
-            set_magic_quotes_runtime(true);
945
-        }
946
-        if (!empty($oldEncoding)) {
947
-            mb_internal_encoding($oldEncoding);
948
-        }
949
-        // rethrow the exception
950
-        if (!empty($e)) {
951
-            throw $e;
952
-        }
953
-        return $response;
954
-    }
955
-
956
-    /**
957
-     * Wrapper around fopen()/fstat() used by setBody() and addUpload()
958
-     *
959
-     * @param string|resource $file       file name or pointer to open file
960
-     * @param bool            $detectType whether to try autodetecting MIME
961
-     *                        type of file, will only work if $file is a
962
-     *                        filename, not pointer
963
-     *
964
-     * @return array array('fp' => file pointer, 'size' => file size, 'type' => MIME type)
965
-     * @throws HTTP_Request2_LogicException
966
-     */
967
-    protected function fopenWrapper($file, $detectType = false)
968
-    {
969
-        if (!is_string($file) && !is_resource($file)) {
970
-            throw new HTTP_Request2_LogicException(
971
-                "Filename or file pointer resource expected",
972
-                HTTP_Request2_Exception::INVALID_ARGUMENT
973
-            );
974
-        }
975
-        $fileData = array(
976
-            'fp'   => is_string($file)? null: $file,
977
-            'type' => 'application/octet-stream',
978
-            'size' => 0
979
-        );
980
-        if (is_string($file)) {
981
-            if (!($fileData['fp'] = @fopen($file, 'rb'))) {
982
-                $error = error_get_last();
983
-                throw new HTTP_Request2_LogicException(
984
-                    $error['message'], HTTP_Request2_Exception::READ_ERROR
985
-                );
986
-            }
987
-            if ($detectType) {
988
-                $fileData['type'] = self::detectMimeType($file);
989
-            }
990
-        }
991
-        if (!($stat = fstat($fileData['fp']))) {
992
-            throw new HTTP_Request2_LogicException(
993
-                "fstat() call failed", HTTP_Request2_Exception::READ_ERROR
994
-            );
995
-        }
996
-        $fileData['size'] = $stat['size'];
997
-
998
-        return $fileData;
999
-    }
1000
-
1001
-    /**
1002
-     * Tries to detect MIME type of a file
1003
-     *
1004
-     * The method will try to use fileinfo extension if it is available,
1005
-     * deprecated mime_content_type() function in the other case. If neither
1006
-     * works, default 'application/octet-stream' MIME type is returned
1007
-     *
1008
-     * @param string $filename file name
1009
-     *
1010
-     * @return   string  file MIME type
1011
-     */
1012
-    protected static function detectMimeType($filename)
1013
-    {
1014
-        // finfo extension from PECL available
1015
-        if (function_exists('finfo_open')) {
1016
-            if (!isset(self::$_fileinfoDb)) {
1017
-                self::$_fileinfoDb = @finfo_open(FILEINFO_MIME);
1018
-            }
1019
-            if (self::$_fileinfoDb) {
1020
-                $info = finfo_file(self::$_fileinfoDb, $filename);
1021
-            }
1022
-        }
1023
-        // (deprecated) mime_content_type function available
1024
-        if (empty($info) && function_exists('mime_content_type')) {
1025
-            return mime_content_type($filename);
1026
-        }
1027
-        return empty($info)? 'application/octet-stream': $info;
1028
-    }
64
+	const AUTH_BASIC  = 'basic';
65
+	const AUTH_DIGEST = 'digest';
66
+	/**#@-*/
67
+
68
+	/**
69
+	 * Regular expression used to check for invalid symbols in RFC 2616 tokens
70
+	 * @link http://pear.php.net/bugs/bug.php?id=15630
71
+	 */
72
+	const REGEXP_INVALID_TOKEN = '![\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]!';
73
+
74
+	/**
75
+	 * Regular expression used to check for invalid symbols in cookie strings
76
+	 * @link http://pear.php.net/bugs/bug.php?id=15630
77
+	 * @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html
78
+	 */
79
+	const REGEXP_INVALID_COOKIE = '/[\s,;]/';
80
+
81
+	/**
82
+	 * Fileinfo magic database resource
83
+	 * @var  resource
84
+	 * @see  detectMimeType()
85
+	 */
86
+	private static $_fileinfoDb;
87
+
88
+	/**
89
+	 * Observers attached to the request (instances of SplObserver)
90
+	 * @var  array
91
+	 */
92
+	protected $observers = array();
93
+
94
+	/**
95
+	 * Request URL
96
+	 * @var  Net_URL2
97
+	 */
98
+	protected $url;
99
+
100
+	/**
101
+	 * Request method
102
+	 * @var  string
103
+	 */
104
+	protected $method = self::METHOD_GET;
105
+
106
+	/**
107
+	 * Authentication data
108
+	 * @var  array
109
+	 * @see  getAuth()
110
+	 */
111
+	protected $auth;
112
+
113
+	/**
114
+	 * Request headers
115
+	 * @var  array
116
+	 */
117
+	protected $headers = array();
118
+
119
+	/**
120
+	 * Configuration parameters
121
+	 * @var  array
122
+	 * @see  setConfig()
123
+	 */
124
+	protected $config = array(
125
+		'adapter'           => 'HTTP_Request2_Adapter_Socket',
126
+		'connect_timeout'   => 10,
127
+		'timeout'           => 0,
128
+		'use_brackets'      => true,
129
+		'protocol_version'  => '1.1',
130
+		'buffer_size'       => 16384,
131
+		'store_body'        => true,
132
+		'local_ip'          => null,
133
+
134
+		'proxy_host'        => '',
135
+		'proxy_port'        => '',
136
+		'proxy_user'        => '',
137
+		'proxy_password'    => '',
138
+		'proxy_auth_scheme' => self::AUTH_BASIC,
139
+		'proxy_type'        => 'http',
140
+
141
+		'ssl_verify_peer'   => true,
142
+		'ssl_verify_host'   => true,
143
+		'ssl_cafile'        => null,
144
+		'ssl_capath'        => null,
145
+		'ssl_local_cert'    => null,
146
+		'ssl_passphrase'    => null,
147
+
148
+		'digest_compat_ie'  => false,
149
+
150
+		'follow_redirects'  => false,
151
+		'max_redirects'     => 5,
152
+		'strict_redirects'  => false
153
+	);
154
+
155
+	/**
156
+	 * Last event in request / response handling, intended for observers
157
+	 * @var  array
158
+	 * @see  getLastEvent()
159
+	 */
160
+	protected $lastEvent = array(
161
+		'name' => 'start',
162
+		'data' => null
163
+	);
164
+
165
+	/**
166
+	 * Request body
167
+	 * @var  string|resource
168
+	 * @see  setBody()
169
+	 */
170
+	protected $body = '';
171
+
172
+	/**
173
+	 * Array of POST parameters
174
+	 * @var  array
175
+	 */
176
+	protected $postParams = array();
177
+
178
+	/**
179
+	 * Array of file uploads (for multipart/form-data POST requests)
180
+	 * @var  array
181
+	 */
182
+	protected $uploads = array();
183
+
184
+	/**
185
+	 * Adapter used to perform actual HTTP request
186
+	 * @var  HTTP_Request2_Adapter
187
+	 */
188
+	protected $adapter;
189
+
190
+	/**
191
+	 * Cookie jar to persist cookies between requests
192
+	 * @var HTTP_Request2_CookieJar
193
+	 */
194
+	protected $cookieJar = null;
195
+
196
+	/**
197
+	 * Constructor. Can set request URL, method and configuration array.
198
+	 *
199
+	 * Also sets a default value for User-Agent header.
200
+	 *
201
+	 * @param string|Net_Url2 $url    Request URL
202
+	 * @param string          $method Request method
203
+	 * @param array           $config Configuration for this Request instance
204
+	 */
205
+	public function __construct(
206
+		$url = null, $method = self::METHOD_GET, array $config = array()
207
+	) {
208
+		$this->setConfig($config);
209
+		if (!empty($url)) {
210
+			$this->setUrl($url);
211
+		}
212
+		if (!empty($method)) {
213
+			$this->setMethod($method);
214
+		}
215
+		$this->setHeader(
216
+			'user-agent', 'HTTP_Request2/2.2.1 ' .
217
+			'(http://pear.php.net/package/http_request2) PHP/' . phpversion()
218
+		);
219
+	}
220
+
221
+	/**
222
+	 * Sets the URL for this request
223
+	 *
224
+	 * If the URL has userinfo part (username & password) these will be removed
225
+	 * and converted to auth data. If the URL does not have a path component,
226
+	 * that will be set to '/'.
227
+	 *
228
+	 * @param string|Net_URL2 $url Request URL
229
+	 *
230
+	 * @return   HTTP_Request2
231
+	 * @throws   HTTP_Request2_LogicException
232
+	 */
233
+	public function setUrl($url)
234
+	{
235
+		if (is_string($url)) {
236
+			$url = new Net_URL2(
237
+				$url, array(Net_URL2::OPTION_USE_BRACKETS => $this->config['use_brackets'])
238
+			);
239
+		}
240
+		if (!$url instanceof Net_URL2) {
241
+			throw new HTTP_Request2_LogicException(
242
+				'Parameter is not a valid HTTP URL',
243
+				HTTP_Request2_Exception::INVALID_ARGUMENT
244
+			);
245
+		}
246
+		// URL contains username / password?
247
+		if ($url->getUserinfo()) {
248
+			$username = $url->getUser();
249
+			$password = $url->getPassword();
250
+			$this->setAuth(rawurldecode($username), $password? rawurldecode($password): '');
251
+			$url->setUserinfo('');
252
+		}
253
+		if ('' == $url->getPath()) {
254
+			$url->setPath('/');
255
+		}
256
+		$this->url = $url;
257
+
258
+		return $this;
259
+	}
260
+
261
+	/**
262
+	 * Returns the request URL
263
+	 *
264
+	 * @return   Net_URL2
265
+	 */
266
+	public function getUrl()
267
+	{
268
+		return $this->url;
269
+	}
270
+
271
+	/**
272
+	 * Sets the request method
273
+	 *
274
+	 * @param string $method one of the methods defined in RFC 2616
275
+	 *
276
+	 * @return   HTTP_Request2
277
+	 * @throws   HTTP_Request2_LogicException if the method name is invalid
278
+	 */
279
+	public function setMethod($method)
280
+	{
281
+		// Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1
282
+		if (preg_match(self::REGEXP_INVALID_TOKEN, $method)) {
283
+			throw new HTTP_Request2_LogicException(
284
+				"Invalid request method '{$method}'",
285
+				HTTP_Request2_Exception::INVALID_ARGUMENT
286
+			);
287
+		}
288
+		$this->method = $method;
289
+
290
+		return $this;
291
+	}
292
+
293
+	/**
294
+	 * Returns the request method
295
+	 *
296
+	 * @return   string
297
+	 */
298
+	public function getMethod()
299
+	{
300
+		return $this->method;
301
+	}
302
+
303
+	/**
304
+	 * Sets the configuration parameter(s)
305
+	 *
306
+	 * The following parameters are available:
307
+	 * <ul>
308
+	 *   <li> 'adapter'           - adapter to use (string)</li>
309
+	 *   <li> 'connect_timeout'   - Connection timeout in seconds (integer)</li>
310
+	 *   <li> 'timeout'           - Total number of seconds a request can take.
311
+	 *                              Use 0 for no limit, should be greater than
312
+	 *                              'connect_timeout' if set (integer)</li>
313
+	 *   <li> 'use_brackets'      - Whether to append [] to array variable names (bool)</li>
314
+	 *   <li> 'protocol_version'  - HTTP Version to use, '1.0' or '1.1' (string)</li>
315
+	 *   <li> 'buffer_size'       - Buffer size to use for reading and writing (int)</li>
316
+	 *   <li> 'store_body'        - Whether to store response body in response object.
317
+	 *                              Set to false if receiving a huge response and
318
+	 *                              using an Observer to save it (boolean)</li>
319
+	 *   <li> 'local_ip'          - Specifies the IP address that will be used for accessing
320
+	 *                              the network (string)</li>
321
+	 *   <li> 'proxy_type'        - Proxy type, 'http' or 'socks5' (string)</li>
322
+	 *   <li> 'proxy_host'        - Proxy server host (string)</li>
323
+	 *   <li> 'proxy_port'        - Proxy server port (integer)</li>
324
+	 *   <li> 'proxy_user'        - Proxy auth username (string)</li>
325
+	 *   <li> 'proxy_password'    - Proxy auth password (string)</li>
326
+	 *   <li> 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)</li>
327
+	 *   <li> 'proxy'             - Shorthand for proxy_* parameters, proxy given as URL,
328
+	 *                              e.g. 'socks5://localhost:1080/' (string)</li>
329
+	 *   <li> 'ssl_verify_peer'   - Whether to verify peer's SSL certificate (bool)</li>
330
+	 *   <li> 'ssl_verify_host'   - Whether to check that Common Name in SSL
331
+	 *                              certificate matches host name (bool)</li>
332
+	 *   <li> 'ssl_cafile'        - Cerificate Authority file to verify the peer
333
+	 *                              with (use with 'ssl_verify_peer') (string)</li>
334
+	 *   <li> 'ssl_capath'        - Directory holding multiple Certificate
335
+	 *                              Authority files (string)</li>
336
+	 *   <li> 'ssl_local_cert'    - Name of a file containing local cerificate (string)</li>
337
+	 *   <li> 'ssl_passphrase'    - Passphrase with which local certificate
338
+	 *                              was encoded (string)</li>
339
+	 *   <li> 'digest_compat_ie'  - Whether to imitate behaviour of MSIE 5 and 6
340
+	 *                              in using URL without query string in digest
341
+	 *                              authentication (boolean)</li>
342
+	 *   <li> 'follow_redirects'  - Whether to automatically follow HTTP Redirects (boolean)</li>
343
+	 *   <li> 'max_redirects'     - Maximum number of redirects to follow (integer)</li>
344
+	 *   <li> 'strict_redirects'  - Whether to keep request method on redirects via status 301 and
345
+	 *                              302 (true, needed for compatibility with RFC 2616)
346
+	 *                              or switch to GET (false, needed for compatibility with most
347
+	 *                              browsers) (boolean)</li>
348
+	 * </ul>
349
+	 *
350
+	 * @param string|array $nameOrConfig configuration parameter name or array
351
+	 *                                   ('parameter name' => 'parameter value')
352
+	 * @param mixed        $value        parameter value if $nameOrConfig is not an array
353
+	 *
354
+	 * @return   HTTP_Request2
355
+	 * @throws   HTTP_Request2_LogicException If the parameter is unknown
356
+	 */
357
+	public function setConfig($nameOrConfig, $value = null)
358
+	{
359
+		if (is_array($nameOrConfig)) {
360
+			foreach ($nameOrConfig as $name => $value) {
361
+				$this->setConfig($name, $value);
362
+			}
363
+
364
+		} elseif ('proxy' == $nameOrConfig) {
365
+			$url = new Net_URL2($value);
366
+			$this->setConfig(array(
367
+				'proxy_type'     => $url->getScheme(),
368
+				'proxy_host'     => $url->getHost(),
369
+				'proxy_port'     => $url->getPort(),
370
+				'proxy_user'     => rawurldecode($url->getUser()),
371
+				'proxy_password' => rawurldecode($url->getPassword())
372
+			));
373
+
374
+		} else {
375
+			if (!array_key_exists($nameOrConfig, $this->config)) {
376
+				throw new HTTP_Request2_LogicException(
377
+					"Unknown configuration parameter '{$nameOrConfig}'",
378
+					HTTP_Request2_Exception::INVALID_ARGUMENT
379
+				);
380
+			}
381
+			$this->config[$nameOrConfig] = $value;
382
+		}
383
+
384
+		return $this;
385
+	}
386
+
387
+	/**
388
+	 * Returns the value(s) of the configuration parameter(s)
389
+	 *
390
+	 * @param string $name parameter name
391
+	 *
392
+	 * @return   mixed   value of $name parameter, array of all configuration
393
+	 *                   parameters if $name is not given
394
+	 * @throws   HTTP_Request2_LogicException If the parameter is unknown
395
+	 */
396
+	public function getConfig($name = null)
397
+	{
398
+		if (null === $name) {
399
+			return $this->config;
400
+		} elseif (!array_key_exists($name, $this->config)) {
401
+			throw new HTTP_Request2_LogicException(
402
+				"Unknown configuration parameter '{$name}'",
403
+				HTTP_Request2_Exception::INVALID_ARGUMENT
404
+			);
405
+		}
406
+		return $this->config[$name];
407
+	}
408
+
409
+	/**
410
+	 * Sets the autentification data
411
+	 *
412
+	 * @param string $user     user name
413
+	 * @param string $password password
414
+	 * @param string $scheme   authentication scheme
415
+	 *
416
+	 * @return   HTTP_Request2
417
+	 */
418
+	public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC)
419
+	{
420
+		if (empty($user)) {
421
+			$this->auth = null;
422
+		} else {
423
+			$this->auth = array(
424
+				'user'     => (string)$user,
425
+				'password' => (string)$password,
426
+				'scheme'   => $scheme
427
+			);
428
+		}
429
+
430
+		return $this;
431
+	}
432
+
433
+	/**
434
+	 * Returns the authentication data
435
+	 *
436
+	 * The array has the keys 'user', 'password' and 'scheme', where 'scheme'
437
+	 * is one of the HTTP_Request2::AUTH_* constants.
438
+	 *
439
+	 * @return   array
440
+	 */
441
+	public function getAuth()
442
+	{
443
+		return $this->auth;
444
+	}
445
+
446
+	/**
447
+	 * Sets request header(s)
448
+	 *
449
+	 * The first parameter may be either a full header string 'header: value' or
450
+	 * header name. In the former case $value parameter is ignored, in the latter
451
+	 * the header's value will either be set to $value or the header will be
452
+	 * removed if $value is null. The first parameter can also be an array of
453
+	 * headers, in that case method will be called recursively.
454
+	 *
455
+	 * Note that headers are treated case insensitively as per RFC 2616.
456
+	 *
457
+	 * <code>
458
+	 * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar'
459
+	 * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz'
460
+	 * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux'
461
+	 * $req->setHeader('FOO'); // removes 'Foo' header from request
462
+	 * </code>
463
+	 *
464
+	 * @param string|array      $name    header name, header string ('Header: value')
465
+	 *                                   or an array of headers
466
+	 * @param string|array|null $value   header value if $name is not an array,
467
+	 *                                   header will be removed if value is null
468
+	 * @param bool              $replace whether to replace previous header with the
469
+	 *                                   same name or append to its value
470
+	 *
471
+	 * @return   HTTP_Request2
472
+	 * @throws   HTTP_Request2_LogicException
473
+	 */
474
+	public function setHeader($name, $value = null, $replace = true)
475
+	{
476
+		if (is_array($name)) {
477
+			foreach ($name as $k => $v) {
478
+				if (is_string($k)) {
479
+					$this->setHeader($k, $v, $replace);
480
+				} else {
481
+					$this->setHeader($v, null, $replace);
482
+				}
483
+			}
484
+		} else {
485
+			if (null === $value && strpos($name, ':')) {
486
+				list($name, $value) = array_map('trim', explode(':', $name, 2));
487
+			}
488
+			// Header name should be a token: http://tools.ietf.org/html/rfc2616#section-4.2
489
+			if (preg_match(self::REGEXP_INVALID_TOKEN, $name)) {
490
+				throw new HTTP_Request2_LogicException(
491
+					"Invalid header name '{$name}'",
492
+					HTTP_Request2_Exception::INVALID_ARGUMENT
493
+				);
494
+			}
495
+			// Header names are case insensitive anyway
496
+			$name = strtolower($name);
497
+			if (null === $value) {
498
+				unset($this->headers[$name]);
499
+
500
+			} else {
501
+				if (is_array($value)) {
502
+					$value = implode(', ', array_map('trim', $value));
503
+				} elseif (is_string($value)) {
504
+					$value = trim($value);
505
+				}
506
+				if (!isset($this->headers[$name]) || $replace) {
507
+					$this->headers[$name] = $value;
508
+				} else {
509
+					$this->headers[$name] .= ', ' . $value;
510
+				}
511
+			}
512
+		}
513
+
514
+		return $this;
515
+	}
516
+
517
+	/**
518
+	 * Returns the request headers
519
+	 *
520
+	 * The array is of the form ('header name' => 'header value'), header names
521
+	 * are lowercased
522
+	 *
523
+	 * @return   array
524
+	 */
525
+	public function getHeaders()
526
+	{
527
+		return $this->headers;
528
+	}
529
+
530
+	/**
531
+	 * Adds a cookie to the request
532
+	 *
533
+	 * If the request does not have a CookieJar object set, this method simply
534
+	 * appends a cookie to "Cookie:" header.
535
+	 *
536
+	 * If a CookieJar object is available, the cookie is stored in that object.
537
+	 * Data from request URL will be used for setting its 'domain' and 'path'
538
+	 * parameters, 'expires' and 'secure' will be set to null and false,
539
+	 * respectively. If you need further control, use CookieJar's methods.
540
+	 *
541
+	 * @param string $name  cookie name
542
+	 * @param string $value cookie value
543
+	 *
544
+	 * @return   HTTP_Request2
545
+	 * @throws   HTTP_Request2_LogicException
546
+	 * @see      setCookieJar()
547
+	 */
548
+	public function addCookie($name, $value)
549
+	{
550
+		if (!empty($this->cookieJar)) {
551
+			$this->cookieJar->store(
552
+				array('name' => $name, 'value' => $value), $this->url
553
+			);
554
+
555
+		} else {
556
+			$cookie = $name . '=' . $value;
557
+			if (preg_match(self::REGEXP_INVALID_COOKIE, $cookie)) {
558
+				throw new HTTP_Request2_LogicException(
559
+					"Invalid cookie: '{$cookie}'",
560
+					HTTP_Request2_Exception::INVALID_ARGUMENT
561
+				);
562
+			}
563
+			$cookies = empty($this->headers['cookie'])? '': $this->headers['cookie'] . '; ';
564
+			$this->setHeader('cookie', $cookies . $cookie);
565
+		}
566
+
567
+		return $this;
568
+	}
569
+
570
+	/**
571
+	 * Sets the request body
572
+	 *
573
+	 * If you provide file pointer rather than file name, it should support
574
+	 * fstat() and rewind() operations.
575
+	 *
576
+	 * @param string|resource|HTTP_Request2_MultipartBody $body       Either a
577
+	 *               string with the body or filename containing body or
578
+	 *               pointer to an open file or object with multipart body data
579
+	 * @param bool                                        $isFilename Whether
580
+	 *               first parameter is a filename
581
+	 *
582
+	 * @return   HTTP_Request2
583
+	 * @throws   HTTP_Request2_LogicException
584
+	 */
585
+	public function setBody($body, $isFilename = false)
586
+	{
587
+		if (!$isFilename && !is_resource($body)) {
588
+			if (!$body instanceof HTTP_Request2_MultipartBody) {
589
+				$this->body = (string)$body;
590
+			} else {
591
+				$this->body = $body;
592
+			}
593
+		} else {
594
+			$fileData = $this->fopenWrapper($body, empty($this->headers['content-type']));
595
+			$this->body = $fileData['fp'];
596
+			if (empty($this->headers['content-type'])) {
597
+				$this->setHeader('content-type', $fileData['type']);
598
+			}
599
+		}
600
+		$this->postParams = $this->uploads = array();
601
+
602
+		return $this;
603
+	}
604
+
605
+	/**
606
+	 * Returns the request body
607
+	 *
608
+	 * @return   string|resource|HTTP_Request2_MultipartBody
609
+	 */
610
+	public function getBody()
611
+	{
612
+		if (self::METHOD_POST == $this->method
613
+			&& (!empty($this->postParams) || !empty($this->uploads))
614
+		) {
615
+			if (0 === strpos($this->headers['content-type'], 'application/x-www-form-urlencoded')) {
616
+				$body = http_build_query($this->postParams, '', '&');
617
+				if (!$this->getConfig('use_brackets')) {
618
+					$body = preg_replace('/%5B\d+%5D=/', '=', $body);
619
+				}
620
+				// support RFC 3986 by not encoding '~' symbol (request #15368)
621
+				return str_replace('%7E', '~', $body);
622
+
623
+			} elseif (0 === strpos($this->headers['content-type'], 'multipart/form-data')) {
624
+				require_once 'HTTP/Request2/MultipartBody.php';
625
+				return new HTTP_Request2_MultipartBody(
626
+					$this->postParams, $this->uploads, $this->getConfig('use_brackets')
627
+				);
628
+			}
629
+		}
630
+		return $this->body;
631
+	}
632
+
633
+	/**
634
+	 * Adds a file to form-based file upload
635
+	 *
636
+	 * Used to emulate file upload via a HTML form. The method also sets
637
+	 * Content-Type of HTTP request to 'multipart/form-data'.
638
+	 *
639
+	 * If you just want to send the contents of a file as the body of HTTP
640
+	 * request you should use setBody() method.
641
+	 *
642
+	 * If you provide file pointers rather than file names, they should support
643
+	 * fstat() and rewind() operations.
644
+	 *
645
+	 * @param string                $fieldName    name of file-upload field
646
+	 * @param string|resource|array $filename     full name of local file,
647
+	 *               pointer to open file or an array of files
648
+	 * @param string                $sendFilename filename to send in the request
649
+	 * @param string                $contentType  content-type of file being uploaded
650
+	 *
651
+	 * @return   HTTP_Request2
652
+	 * @throws   HTTP_Request2_LogicException
653
+	 */
654
+	public function addUpload(
655
+		$fieldName, $filename, $sendFilename = null, $contentType = null
656
+	) {
657
+		if (!is_array($filename)) {
658
+			$fileData = $this->fopenWrapper($filename, empty($contentType));
659
+			$this->uploads[$fieldName] = array(
660
+				'fp'        => $fileData['fp'],
661
+				'filename'  => !empty($sendFilename)? $sendFilename
662
+								:(is_string($filename)? basename($filename): 'anonymous.blob') ,
663
+				'size'      => $fileData['size'],
664
+				'type'      => empty($contentType)? $fileData['type']: $contentType
665
+			);
666
+		} else {
667
+			$fps = $names = $sizes = $types = array();
668
+			foreach ($filename as $f) {
669
+				if (!is_array($f)) {
670
+					$f = array($f);
671
+				}
672
+				$fileData = $this->fopenWrapper($f[0], empty($f[2]));
673
+				$fps[]   = $fileData['fp'];
674
+				$names[] = !empty($f[1])? $f[1]
675
+							:(is_string($f[0])? basename($f[0]): 'anonymous.blob');
676
+				$sizes[] = $fileData['size'];
677
+				$types[] = empty($f[2])? $fileData['type']: $f[2];
678
+			}
679
+			$this->uploads[$fieldName] = array(
680
+				'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types
681
+			);
682
+		}
683
+		if (empty($this->headers['content-type'])
684
+			|| 'application/x-www-form-urlencoded' == $this->headers['content-type']
685
+		) {
686
+			$this->setHeader('content-type', 'multipart/form-data');
687
+		}
688
+
689
+		return $this;
690
+	}
691
+
692
+	/**
693
+	 * Adds POST parameter(s) to the request.
694
+	 *
695
+	 * @param string|array $name  parameter name or array ('name' => 'value')
696
+	 * @param mixed        $value parameter value (can be an array)
697
+	 *
698
+	 * @return   HTTP_Request2
699
+	 */
700
+	public function addPostParameter($name, $value = null)
701
+	{
702
+		if (!is_array($name)) {
703
+			$this->postParams[$name] = $value;
704
+		} else {
705
+			foreach ($name as $k => $v) {
706
+				$this->addPostParameter($k, $v);
707
+			}
708
+		}
709
+		if (empty($this->headers['content-type'])) {
710
+			$this->setHeader('content-type', 'application/x-www-form-urlencoded');
711
+		}
712
+
713
+		return $this;
714
+	}
715
+
716
+	/**
717
+	 * Attaches a new observer
718
+	 *
719
+	 * @param SplObserver $observer any object implementing SplObserver
720
+	 */
721
+	public function attach(SplObserver $observer)
722
+	{
723
+		foreach ($this->observers as $attached) {
724
+			if ($attached === $observer) {
725
+				return;
726
+			}
727
+		}
728
+		$this->observers[] = $observer;
729
+	}
730
+
731
+	/**
732
+	 * Detaches an existing observer
733
+	 *
734
+	 * @param SplObserver $observer any object implementing SplObserver
735
+	 */
736
+	public function detach(SplObserver $observer)
737
+	{
738
+		foreach ($this->observers as $key => $attached) {
739
+			if ($attached === $observer) {
740
+				unset($this->observers[$key]);
741
+				return;
742
+			}
743
+		}
744
+	}
745
+
746
+	/**
747
+	 * Notifies all observers
748
+	 */
749
+	public function notify()
750
+	{
751
+		foreach ($this->observers as $observer) {
752
+			$observer->update($this);
753
+		}
754
+	}
755
+
756
+	/**
757
+	 * Sets the last event
758
+	 *
759
+	 * Adapters should use this method to set the current state of the request
760
+	 * and notify the observers.
761
+	 *
762
+	 * @param string $name event name
763
+	 * @param mixed  $data event data
764
+	 */
765
+	public function setLastEvent($name, $data = null)
766
+	{
767
+		$this->lastEvent = array(
768
+			'name' => $name,
769
+			'data' => $data
770
+		);
771
+		$this->notify();
772
+	}
773
+
774
+	/**
775
+	 * Returns the last event
776
+	 *
777
+	 * Observers should use this method to access the last change in request.
778
+	 * The following event names are possible:
779
+	 * <ul>
780
+	 *   <li>'connect'                 - after connection to remote server,
781
+	 *                                   data is the destination (string)</li>
782
+	 *   <li>'disconnect'              - after disconnection from server</li>
783
+	 *   <li>'sentHeaders'             - after sending the request headers,
784
+	 *                                   data is the headers sent (string)</li>
785
+	 *   <li>'sentBodyPart'            - after sending a part of the request body,
786
+	 *                                   data is the length of that part (int)</li>
787
+	 *   <li>'sentBody'                - after sending the whole request body,
788
+	 *                                   data is request body length (int)</li>
789
+	 *   <li>'receivedHeaders'         - after receiving the response headers,
790
+	 *                                   data is HTTP_Request2_Response object</li>
791
+	 *   <li>'receivedBodyPart'        - after receiving a part of the response
792
+	 *                                   body, data is that part (string)</li>
793
+	 *   <li>'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still
794
+	 *                                   encoded by Content-Encoding</li>
795
+	 *   <li>'receivedBody'            - after receiving the complete response
796
+	 *                                   body, data is HTTP_Request2_Response object</li>
797
+	 * </ul>
798
+	 * Different adapters may not send all the event types. Mock adapter does
799
+	 * not send any events to the observers.
800
+	 *
801
+	 * @return   array   The array has two keys: 'name' and 'data'
802
+	 */
803
+	public function getLastEvent()
804
+	{
805
+		return $this->lastEvent;
806
+	}
807
+
808
+	/**
809
+	 * Sets the adapter used to actually perform the request
810
+	 *
811
+	 * You can pass either an instance of a class implementing HTTP_Request2_Adapter
812
+	 * or a class name. The method will only try to include a file if the class
813
+	 * name starts with HTTP_Request2_Adapter_, it will also try to prepend this
814
+	 * prefix to the class name if it doesn't contain any underscores, so that
815
+	 * <code>
816
+	 * $request->setAdapter('curl');
817
+	 * </code>
818
+	 * will work.
819
+	 *
820
+	 * @param string|HTTP_Request2_Adapter $adapter Adapter to use
821
+	 *
822
+	 * @return   HTTP_Request2
823
+	 * @throws   HTTP_Request2_LogicException
824
+	 */
825
+	public function setAdapter($adapter)
826
+	{
827
+		if (is_string($adapter)) {
828
+			if (!class_exists($adapter, false)) {
829
+				if (false === strpos($adapter, '_')) {
830
+					$adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter);
831
+				}
832
+				if (!class_exists($adapter, false)
833
+					&& preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)
834
+				) {
835
+					include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php';
836
+				}
837
+				if (!class_exists($adapter, false)) {
838
+					throw new HTTP_Request2_LogicException(
839
+						"Class {$adapter} not found",
840
+						HTTP_Request2_Exception::MISSING_VALUE
841
+					);
842
+				}
843
+			}
844
+			$adapter = new $adapter;
845
+		}
846
+		if (!$adapter instanceof HTTP_Request2_Adapter) {
847
+			throw new HTTP_Request2_LogicException(
848
+				'Parameter is not a HTTP request adapter',
849
+				HTTP_Request2_Exception::INVALID_ARGUMENT
850
+			);
851
+		}
852
+		$this->adapter = $adapter;
853
+
854
+		return $this;
855
+	}
856
+
857
+	/**
858
+	 * Sets the cookie jar
859
+	 *
860
+	 * A cookie jar is used to maintain cookies across HTTP requests and
861
+	 * responses. Cookies from jar will be automatically added to the request
862
+	 * headers based on request URL.
863
+	 *
864
+	 * @param HTTP_Request2_CookieJar|bool $jar Existing CookieJar object, true to
865
+	 *                                          create a new one, false to remove
866
+	 *
867
+	 * @return HTTP_Request2
868
+	 * @throws HTTP_Request2_LogicException
869
+	 */
870
+	public function setCookieJar($jar = true)
871
+	{
872
+		if (!class_exists('HTTP_Request2_CookieJar', false)) {
873
+			require_once 'HTTP/Request2/CookieJar.php';
874
+		}
875
+
876
+		if ($jar instanceof HTTP_Request2_CookieJar) {
877
+			$this->cookieJar = $jar;
878
+		} elseif (true === $jar) {
879
+			$this->cookieJar = new HTTP_Request2_CookieJar();
880
+		} elseif (!$jar) {
881
+			$this->cookieJar = null;
882
+		} else {
883
+			throw new HTTP_Request2_LogicException(
884
+				'Invalid parameter passed to setCookieJar()',
885
+				HTTP_Request2_Exception::INVALID_ARGUMENT
886
+			);
887
+		}
888
+
889
+		return $this;
890
+	}
891
+
892
+	/**
893
+	 * Returns current CookieJar object or null if none
894
+	 *
895
+	 * @return HTTP_Request2_CookieJar|null
896
+	 */
897
+	public function getCookieJar()
898
+	{
899
+		return $this->cookieJar;
900
+	}
901
+
902
+	/**
903
+	 * Sends the request and returns the response
904
+	 *
905
+	 * @throws   HTTP_Request2_Exception
906
+	 * @return   HTTP_Request2_Response
907
+	 */
908
+	public function send()
909
+	{
910
+		// Sanity check for URL
911
+		if (!$this->url instanceof Net_URL2
912
+			|| !$this->url->isAbsolute()
913
+			|| !in_array(strtolower($this->url->getScheme()), array('https', 'http'))
914
+		) {
915
+			throw new HTTP_Request2_LogicException(
916
+				'HTTP_Request2 needs an absolute HTTP(S) request URL, '
917
+				. ($this->url instanceof Net_URL2
918
+				   ? "'" . $this->url->__toString() . "'" : 'none')
919
+				. ' given',
920
+				HTTP_Request2_Exception::INVALID_ARGUMENT
921
+			);
922
+		}
923
+		if (empty($this->adapter)) {
924
+			$this->setAdapter($this->getConfig('adapter'));
925
+		}
926
+		// magic_quotes_runtime may break file uploads and chunked response
927
+		// processing; see bug #4543. Don't use ini_get() here; see bug #16440.
928
+		if ($magicQuotes = get_magic_quotes_runtime()) {
929
+			set_magic_quotes_runtime(false);
930
+		}
931
+		// force using single byte encoding if mbstring extension overloads
932
+		// strlen() and substr(); see bug #1781, bug #10605
933
+		if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
934
+			$oldEncoding = mb_internal_encoding();
935
+			mb_internal_encoding('8bit');
936
+		}
937
+
938
+		try {
939
+			$response = $this->adapter->sendRequest($this);
940
+		} catch (Exception $e) {
941
+		}
942
+		// cleanup in either case (poor man's "finally" clause)
943
+		if ($magicQuotes) {
944
+			set_magic_quotes_runtime(true);
945
+		}
946
+		if (!empty($oldEncoding)) {
947
+			mb_internal_encoding($oldEncoding);
948
+		}
949
+		// rethrow the exception
950
+		if (!empty($e)) {
951
+			throw $e;
952
+		}
953
+		return $response;
954
+	}
955
+
956
+	/**
957
+	 * Wrapper around fopen()/fstat() used by setBody() and addUpload()
958
+	 *
959
+	 * @param string|resource $file       file name or pointer to open file
960
+	 * @param bool            $detectType whether to try autodetecting MIME
961
+	 *                        type of file, will only work if $file is a
962
+	 *                        filename, not pointer
963
+	 *
964
+	 * @return array array('fp' => file pointer, 'size' => file size, 'type' => MIME type)
965
+	 * @throws HTTP_Request2_LogicException
966
+	 */
967
+	protected function fopenWrapper($file, $detectType = false)
968
+	{
969
+		if (!is_string($file) && !is_resource($file)) {
970
+			throw new HTTP_Request2_LogicException(
971
+				"Filename or file pointer resource expected",
972
+				HTTP_Request2_Exception::INVALID_ARGUMENT
973
+			);
974
+		}
975
+		$fileData = array(
976
+			'fp'   => is_string($file)? null: $file,
977
+			'type' => 'application/octet-stream',
978
+			'size' => 0
979
+		);
980
+		if (is_string($file)) {
981
+			if (!($fileData['fp'] = @fopen($file, 'rb'))) {
982
+				$error = error_get_last();
983
+				throw new HTTP_Request2_LogicException(
984
+					$error['message'], HTTP_Request2_Exception::READ_ERROR
985
+				);
986
+			}
987
+			if ($detectType) {
988
+				$fileData['type'] = self::detectMimeType($file);
989
+			}
990
+		}
991
+		if (!($stat = fstat($fileData['fp']))) {
992
+			throw new HTTP_Request2_LogicException(
993
+				"fstat() call failed", HTTP_Request2_Exception::READ_ERROR
994
+			);
995
+		}
996
+		$fileData['size'] = $stat['size'];
997
+
998
+		return $fileData;
999
+	}
1000
+
1001
+	/**
1002
+	 * Tries to detect MIME type of a file
1003
+	 *
1004
+	 * The method will try to use fileinfo extension if it is available,
1005
+	 * deprecated mime_content_type() function in the other case. If neither
1006
+	 * works, default 'application/octet-stream' MIME type is returned
1007
+	 *
1008
+	 * @param string $filename file name
1009
+	 *
1010
+	 * @return   string  file MIME type
1011
+	 */
1012
+	protected static function detectMimeType($filename)
1013
+	{
1014
+		// finfo extension from PECL available
1015
+		if (function_exists('finfo_open')) {
1016
+			if (!isset(self::$_fileinfoDb)) {
1017
+				self::$_fileinfoDb = @finfo_open(FILEINFO_MIME);
1018
+			}
1019
+			if (self::$_fileinfoDb) {
1020
+				$info = finfo_file(self::$_fileinfoDb, $filename);
1021
+			}
1022
+		}
1023
+		// (deprecated) mime_content_type function available
1024
+		if (empty($info) && function_exists('mime_content_type')) {
1025
+			return mime_content_type($filename);
1026
+		}
1027
+		return empty($info)? 'application/octet-stream': $info;
1028
+	}
1029 1029
 }
1030 1030
 ?>
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -213,8 +213,8 @@  discard block
 block discarded – undo
213 213
             $this->setMethod($method);
214 214
         }
215 215
         $this->setHeader(
216
-            'user-agent', 'HTTP_Request2/2.2.1 ' .
217
-            '(http://pear.php.net/package/http_request2) PHP/' . phpversion()
216
+            'user-agent', 'HTTP_Request2/2.2.1 '.
217
+            '(http://pear.php.net/package/http_request2) PHP/'.phpversion()
218 218
         );
219 219
     }
220 220
 
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
         if ($url->getUserinfo()) {
248 248
             $username = $url->getUser();
249 249
             $password = $url->getPassword();
250
-            $this->setAuth(rawurldecode($username), $password? rawurldecode($password): '');
250
+            $this->setAuth(rawurldecode($username), $password ? rawurldecode($password) : '');
251 251
             $url->setUserinfo('');
252 252
         }
253 253
         if ('' == $url->getPath()) {
@@ -421,8 +421,8 @@  discard block
 block discarded – undo
421 421
             $this->auth = null;
422 422
         } else {
423 423
             $this->auth = array(
424
-                'user'     => (string)$user,
425
-                'password' => (string)$password,
424
+                'user'     => (string) $user,
425
+                'password' => (string) $password,
426 426
                 'scheme'   => $scheme
427 427
             );
428 428
         }
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
                 if (!isset($this->headers[$name]) || $replace) {
507 507
                     $this->headers[$name] = $value;
508 508
                 } else {
509
-                    $this->headers[$name] .= ', ' . $value;
509
+                    $this->headers[$name] .= ', '.$value;
510 510
                 }
511 511
             }
512 512
         }
@@ -553,15 +553,15 @@  discard block
 block discarded – undo
553 553
             );
554 554
 
555 555
         } else {
556
-            $cookie = $name . '=' . $value;
556
+            $cookie = $name.'='.$value;
557 557
             if (preg_match(self::REGEXP_INVALID_COOKIE, $cookie)) {
558 558
                 throw new HTTP_Request2_LogicException(
559 559
                     "Invalid cookie: '{$cookie}'",
560 560
                     HTTP_Request2_Exception::INVALID_ARGUMENT
561 561
                 );
562 562
             }
563
-            $cookies = empty($this->headers['cookie'])? '': $this->headers['cookie'] . '; ';
564
-            $this->setHeader('cookie', $cookies . $cookie);
563
+            $cookies = empty($this->headers['cookie']) ? '' : $this->headers['cookie'].'; ';
564
+            $this->setHeader('cookie', $cookies.$cookie);
565 565
         }
566 566
 
567 567
         return $this;
@@ -586,7 +586,7 @@  discard block
 block discarded – undo
586 586
     {
587 587
         if (!$isFilename && !is_resource($body)) {
588 588
             if (!$body instanceof HTTP_Request2_MultipartBody) {
589
-                $this->body = (string)$body;
589
+                $this->body = (string) $body;
590 590
             } else {
591 591
                 $this->body = $body;
592 592
             }
@@ -658,10 +658,10 @@  discard block
 block discarded – undo
658 658
             $fileData = $this->fopenWrapper($filename, empty($contentType));
659 659
             $this->uploads[$fieldName] = array(
660 660
                 'fp'        => $fileData['fp'],
661
-                'filename'  => !empty($sendFilename)? $sendFilename
662
-                                :(is_string($filename)? basename($filename): 'anonymous.blob') ,
661
+                'filename'  => !empty($sendFilename) ? $sendFilename
662
+                                :(is_string($filename) ? basename($filename) : 'anonymous.blob'),
663 663
                 'size'      => $fileData['size'],
664
-                'type'      => empty($contentType)? $fileData['type']: $contentType
664
+                'type'      => empty($contentType) ? $fileData['type'] : $contentType
665 665
             );
666 666
         } else {
667 667
             $fps = $names = $sizes = $types = array();
@@ -671,10 +671,10 @@  discard block
 block discarded – undo
671 671
                 }
672 672
                 $fileData = $this->fopenWrapper($f[0], empty($f[2]));
673 673
                 $fps[]   = $fileData['fp'];
674
-                $names[] = !empty($f[1])? $f[1]
675
-                            :(is_string($f[0])? basename($f[0]): 'anonymous.blob');
674
+                $names[] = !empty($f[1]) ? $f[1]
675
+                            :(is_string($f[0]) ? basename($f[0]) : 'anonymous.blob');
676 676
                 $sizes[] = $fileData['size'];
677
-                $types[] = empty($f[2])? $fileData['type']: $f[2];
677
+                $types[] = empty($f[2]) ? $fileData['type'] : $f[2];
678 678
             }
679 679
             $this->uploads[$fieldName] = array(
680 680
                 'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types
@@ -827,12 +827,12 @@  discard block
 block discarded – undo
827 827
         if (is_string($adapter)) {
828 828
             if (!class_exists($adapter, false)) {
829 829
                 if (false === strpos($adapter, '_')) {
830
-                    $adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter);
830
+                    $adapter = 'HTTP_Request2_Adapter_'.ucfirst($adapter);
831 831
                 }
832 832
                 if (!class_exists($adapter, false)
833 833
                     && preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)
834 834
                 ) {
835
-                    include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php';
835
+                    include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter).'.php';
836 836
                 }
837 837
                 if (!class_exists($adapter, false)) {
838 838
                     throw new HTTP_Request2_LogicException(
@@ -915,7 +915,7 @@  discard block
 block discarded – undo
915 915
             throw new HTTP_Request2_LogicException(
916 916
                 'HTTP_Request2 needs an absolute HTTP(S) request URL, '
917 917
                 . ($this->url instanceof Net_URL2
918
-                   ? "'" . $this->url->__toString() . "'" : 'none')
918
+                   ? "'".$this->url->__toString()."'" : 'none')
919 919
                 . ' given',
920 920
                 HTTP_Request2_Exception::INVALID_ARGUMENT
921 921
             );
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
             );
974 974
         }
975 975
         $fileData = array(
976
-            'fp'   => is_string($file)? null: $file,
976
+            'fp'   => is_string($file) ? null : $file,
977 977
             'type' => 'application/octet-stream',
978 978
             'size' => 0
979 979
         );
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
         if (empty($info) && function_exists('mime_content_type')) {
1025 1025
             return mime_content_type($filename);
1026 1026
         }
1027
-        return empty($info)? 'application/octet-stream': $info;
1027
+        return empty($info) ? 'application/octet-stream' : $info;
1028 1028
     }
1029 1029
 }
1030 1030
 ?>
Please login to merge, or discard this patch.
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
     /**
262 262
      * Returns the request URL
263 263
      *
264
-     * @return   Net_URL2
264
+     * @return   string
265 265
      */
266 266
     public function getUrl()
267 267
     {
@@ -573,7 +573,7 @@  discard block
 block discarded – undo
573 573
      * If you provide file pointer rather than file name, it should support
574 574
      * fstat() and rewind() operations.
575 575
      *
576
-     * @param string|resource|HTTP_Request2_MultipartBody $body       Either a
576
+     * @param string $body       Either a
577 577
      *               string with the body or filename containing body or
578 578
      *               pointer to an open file or object with multipart body data
579 579
      * @param bool                                        $isFilename Whether
Please login to merge, or discard this patch.
libs/PEAR.1.9.5/HTTP/Request2/Adapter/Curl.php 3 patches
Switch Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -268,29 +268,29 @@  discard block
 block discarded – undo
268 268
 
269 269
         // set HTTP version
270 270
         switch ($this->request->getConfig('protocol_version')) {
271
-        case '1.0':
272
-            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
273
-            break;
274
-        case '1.1':
275
-            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
271
+        	case '1.0':
272
+            	curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
273
+            	break;
274
+        	case '1.1':
275
+            	curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
276 276
         }
277 277
 
278 278
         // set request method
279 279
         switch ($this->request->getMethod()) {
280
-        case HTTP_Request2::METHOD_GET:
281
-            curl_setopt($ch, CURLOPT_HTTPGET, true);
282
-            break;
283
-        case HTTP_Request2::METHOD_POST:
284
-            curl_setopt($ch, CURLOPT_POST, true);
285
-            break;
286
-        case HTTP_Request2::METHOD_HEAD:
287
-            curl_setopt($ch, CURLOPT_NOBODY, true);
288
-            break;
289
-        case HTTP_Request2::METHOD_PUT:
290
-            curl_setopt($ch, CURLOPT_UPLOAD, true);
291
-            break;
292
-        default:
293
-            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());
280
+        	case HTTP_Request2::METHOD_GET:
281
+            	curl_setopt($ch, CURLOPT_HTTPGET, true);
282
+            	break;
283
+        	case HTTP_Request2::METHOD_POST:
284
+            	curl_setopt($ch, CURLOPT_POST, true);
285
+            	break;
286
+        	case HTTP_Request2::METHOD_HEAD:
287
+            	curl_setopt($ch, CURLOPT_NOBODY, true);
288
+            	break;
289
+        	case HTTP_Request2::METHOD_PUT:
290
+            	curl_setopt($ch, CURLOPT_UPLOAD, true);
291
+            	break;
292
+        	default:
293
+            	curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());
294 294
         }
295 295
 
296 296
         // set proxy, if needed
@@ -307,25 +307,25 @@  discard block
 block discarded – undo
307 307
                     $user . ':' . $this->request->getConfig('proxy_password')
308 308
                 );
309 309
                 switch ($this->request->getConfig('proxy_auth_scheme')) {
310
-                case HTTP_Request2::AUTH_BASIC:
311
-                    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
312
-                    break;
313
-                case HTTP_Request2::AUTH_DIGEST:
314
-                    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
310
+                	case HTTP_Request2::AUTH_BASIC:
311
+                    	curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
312
+                    	break;
313
+                	case HTTP_Request2::AUTH_DIGEST:
314
+                    	curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
315 315
                 }
316 316
             }
317 317
             if ($type = $this->request->getConfig('proxy_type')) {
318 318
                 switch ($type) {
319
-                case 'http':
320
-                    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
321
-                    break;
322
-                case 'socks5':
323
-                    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
324
-                    break;
325
-                default:
326
-                    throw new HTTP_Request2_NotImplementedException(
327
-                        "Proxy type '{$type}' is not supported"
328
-                    );
319
+                	case 'http':
320
+                    	curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
321
+                    	break;
322
+                	case 'socks5':
323
+                    	curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
324
+                    	break;
325
+                	default:
326
+                    	throw new HTTP_Request2_NotImplementedException(
327
+                        	"Proxy type '{$type}' is not supported"
328
+                    	);
329 329
                 }
330 330
             }
331 331
         }
@@ -334,11 +334,11 @@  discard block
 block discarded – undo
334 334
         if ($auth = $this->request->getAuth()) {
335 335
             curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']);
336 336
             switch ($auth['scheme']) {
337
-            case HTTP_Request2::AUTH_BASIC:
338
-                curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
339
-                break;
340
-            case HTTP_Request2::AUTH_DIGEST:
341
-                curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
337
+            	case HTTP_Request2::AUTH_BASIC:
338
+                	curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
339
+                	break;
340
+            	case HTTP_Request2::AUTH_DIGEST:
341
+                	curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
342 342
             }
343 343
         }
344 344
 
Please login to merge, or discard this patch.
Indentation   +528 added lines, -528 removed lines patch added patch discarded remove patch
@@ -35,533 +35,533 @@
 block discarded – undo
35 35
  */
36 36
 class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
37 37
 {
38
-    /**
39
-     * Mapping of header names to cURL options
40
-     * @var  array
41
-     */
42
-    protected static $headerMap = array(
43
-        'accept-encoding' => CURLOPT_ENCODING,
44
-        'cookie'          => CURLOPT_COOKIE,
45
-        'referer'         => CURLOPT_REFERER,
46
-        'user-agent'      => CURLOPT_USERAGENT
47
-    );
48
-
49
-    /**
50
-     * Mapping of SSL context options to cURL options
51
-     * @var  array
52
-     */
53
-    protected static $sslContextMap = array(
54
-        'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER,
55
-        'ssl_cafile'      => CURLOPT_CAINFO,
56
-        'ssl_capath'      => CURLOPT_CAPATH,
57
-        'ssl_local_cert'  => CURLOPT_SSLCERT,
58
-        'ssl_passphrase'  => CURLOPT_SSLCERTPASSWD
59
-    );
60
-
61
-    /**
62
-     * Mapping of CURLE_* constants to Exception subclasses and error codes
63
-     * @var  array
64
-     */
65
-    protected static $errorMap = array(
66
-        CURLE_UNSUPPORTED_PROTOCOL  => array('HTTP_Request2_MessageException',
67
-                                             HTTP_Request2_Exception::NON_HTTP_REDIRECT),
68
-        CURLE_COULDNT_RESOLVE_PROXY => array('HTTP_Request2_ConnectionException'),
69
-        CURLE_COULDNT_RESOLVE_HOST  => array('HTTP_Request2_ConnectionException'),
70
-        CURLE_COULDNT_CONNECT       => array('HTTP_Request2_ConnectionException'),
71
-        // error returned from write callback
72
-        CURLE_WRITE_ERROR           => array('HTTP_Request2_MessageException',
73
-                                             HTTP_Request2_Exception::NON_HTTP_REDIRECT),
74
-        CURLE_OPERATION_TIMEOUTED   => array('HTTP_Request2_MessageException',
75
-                                             HTTP_Request2_Exception::TIMEOUT),
76
-        CURLE_HTTP_RANGE_ERROR      => array('HTTP_Request2_MessageException'),
77
-        CURLE_SSL_CONNECT_ERROR     => array('HTTP_Request2_ConnectionException'),
78
-        CURLE_LIBRARY_NOT_FOUND     => array('HTTP_Request2_LogicException',
79
-                                             HTTP_Request2_Exception::MISCONFIGURATION),
80
-        CURLE_FUNCTION_NOT_FOUND    => array('HTTP_Request2_LogicException',
81
-                                             HTTP_Request2_Exception::MISCONFIGURATION),
82
-        CURLE_ABORTED_BY_CALLBACK   => array('HTTP_Request2_MessageException',
83
-                                             HTTP_Request2_Exception::NON_HTTP_REDIRECT),
84
-        CURLE_TOO_MANY_REDIRECTS    => array('HTTP_Request2_MessageException',
85
-                                             HTTP_Request2_Exception::TOO_MANY_REDIRECTS),
86
-        CURLE_SSL_PEER_CERTIFICATE  => array('HTTP_Request2_ConnectionException'),
87
-        CURLE_GOT_NOTHING           => array('HTTP_Request2_MessageException'),
88
-        CURLE_SSL_ENGINE_NOTFOUND   => array('HTTP_Request2_LogicException',
89
-                                             HTTP_Request2_Exception::MISCONFIGURATION),
90
-        CURLE_SSL_ENGINE_SETFAILED  => array('HTTP_Request2_LogicException',
91
-                                             HTTP_Request2_Exception::MISCONFIGURATION),
92
-        CURLE_SEND_ERROR            => array('HTTP_Request2_MessageException'),
93
-        CURLE_RECV_ERROR            => array('HTTP_Request2_MessageException'),
94
-        CURLE_SSL_CERTPROBLEM       => array('HTTP_Request2_LogicException',
95
-                                             HTTP_Request2_Exception::INVALID_ARGUMENT),
96
-        CURLE_SSL_CIPHER            => array('HTTP_Request2_ConnectionException'),
97
-        CURLE_SSL_CACERT            => array('HTTP_Request2_ConnectionException'),
98
-        CURLE_BAD_CONTENT_ENCODING  => array('HTTP_Request2_MessageException'),
99
-    );
100
-
101
-    /**
102
-     * Response being received
103
-     * @var  HTTP_Request2_Response
104
-     */
105
-    protected $response;
106
-
107
-    /**
108
-     * Whether 'sentHeaders' event was sent to observers
109
-     * @var  boolean
110
-     */
111
-    protected $eventSentHeaders = false;
112
-
113
-    /**
114
-     * Whether 'receivedHeaders' event was sent to observers
115
-     * @var boolean
116
-     */
117
-    protected $eventReceivedHeaders = false;
118
-
119
-    /**
120
-     * Position within request body
121
-     * @var  integer
122
-     * @see  callbackReadBody()
123
-     */
124
-    protected $position = 0;
125
-
126
-    /**
127
-     * Information about last transfer, as returned by curl_getinfo()
128
-     * @var  array
129
-     */
130
-    protected $lastInfo;
131
-
132
-    /**
133
-     * Creates a subclass of HTTP_Request2_Exception from curl error data
134
-     *
135
-     * @param resource $ch curl handle
136
-     *
137
-     * @return HTTP_Request2_Exception
138
-     */
139
-    protected static function wrapCurlError($ch)
140
-    {
141
-        $nativeCode = curl_errno($ch);
142
-        $message    = 'Curl error: ' . curl_error($ch);
143
-        if (!isset(self::$errorMap[$nativeCode])) {
144
-            return new HTTP_Request2_Exception($message, 0, $nativeCode);
145
-        } else {
146
-            $class = self::$errorMap[$nativeCode][0];
147
-            $code  = empty(self::$errorMap[$nativeCode][1])
148
-                     ? 0 : self::$errorMap[$nativeCode][1];
149
-            return new $class($message, $code, $nativeCode);
150
-        }
151
-    }
152
-
153
-    /**
154
-     * Sends request to the remote server and returns its response
155
-     *
156
-     * @param HTTP_Request2 $request HTTP request message
157
-     *
158
-     * @return   HTTP_Request2_Response
159
-     * @throws   HTTP_Request2_Exception
160
-     */
161
-    public function sendRequest(HTTP_Request2 $request)
162
-    {
163
-        if (!extension_loaded('curl')) {
164
-            throw new HTTP_Request2_LogicException(
165
-                'cURL extension not available', HTTP_Request2_Exception::MISCONFIGURATION
166
-            );
167
-        }
168
-
169
-        $this->request              = $request;
170
-        $this->response             = null;
171
-        $this->position             = 0;
172
-        $this->eventSentHeaders     = false;
173
-        $this->eventReceivedHeaders = false;
174
-
175
-        try {
176
-            if (false === curl_exec($ch = $this->createCurlHandle())) {
177
-                $e = self::wrapCurlError($ch);
178
-            }
179
-        } catch (Exception $e) {
180
-        }
181
-        if (isset($ch)) {
182
-            $this->lastInfo = curl_getinfo($ch);
183
-            curl_close($ch);
184
-        }
185
-
186
-        $response = $this->response;
187
-        unset($this->request, $this->requestBody, $this->response);
188
-
189
-        if (!empty($e)) {
190
-            throw $e;
191
-        }
192
-
193
-        if ($jar = $request->getCookieJar()) {
194
-            $jar->addCookiesFromResponse($response, $request->getUrl());
195
-        }
196
-
197
-        if (0 < $this->lastInfo['size_download']) {
198
-            $request->setLastEvent('receivedBody', $response);
199
-        }
200
-        return $response;
201
-    }
202
-
203
-    /**
204
-     * Returns information about last transfer
205
-     *
206
-     * @return   array   associative array as returned by curl_getinfo()
207
-     */
208
-    public function getInfo()
209
-    {
210
-        return $this->lastInfo;
211
-    }
212
-
213
-    /**
214
-     * Creates a new cURL handle and populates it with data from the request
215
-     *
216
-     * @return   resource    a cURL handle, as created by curl_init()
217
-     * @throws   HTTP_Request2_LogicException
218
-     * @throws   HTTP_Request2_NotImplementedException
219
-     */
220
-    protected function createCurlHandle()
221
-    {
222
-        $ch = curl_init();
223
-
224
-        curl_setopt_array($ch, array(
225
-            // setup write callbacks
226
-            CURLOPT_HEADERFUNCTION => array($this, 'callbackWriteHeader'),
227
-            CURLOPT_WRITEFUNCTION  => array($this, 'callbackWriteBody'),
228
-            // buffer size
229
-            CURLOPT_BUFFERSIZE     => $this->request->getConfig('buffer_size'),
230
-            // connection timeout
231
-            CURLOPT_CONNECTTIMEOUT => $this->request->getConfig('connect_timeout'),
232
-            // save full outgoing headers, in case someone is interested
233
-            CURLINFO_HEADER_OUT    => true,
234
-            // request url
235
-            CURLOPT_URL            => $this->request->getUrl()->getUrl()
236
-        ));
237
-
238
-        // set up redirects
239
-        if (!$this->request->getConfig('follow_redirects')) {
240
-            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
241
-        } else {
242
-            if (!@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)) {
243
-                throw new HTTP_Request2_LogicException(
244
-                    'Redirect support in curl is unavailable due to open_basedir or safe_mode setting',
245
-                    HTTP_Request2_Exception::MISCONFIGURATION
246
-                );
247
-            }
248
-            curl_setopt($ch, CURLOPT_MAXREDIRS, $this->request->getConfig('max_redirects'));
249
-            // limit redirects to http(s), works in 5.2.10+
250
-            if (defined('CURLOPT_REDIR_PROTOCOLS')) {
251
-                curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
252
-            }
253
-            // works in 5.3.2+, http://bugs.php.net/bug.php?id=49571
254
-            if ($this->request->getConfig('strict_redirects') && defined('CURLOPT_POSTREDIR')) {
255
-                curl_setopt($ch, CURLOPT_POSTREDIR, 3);
256
-            }
257
-        }
258
-
259
-        // set local IP via CURLOPT_INTERFACE (request #19515)
260
-        if ($ip = $this->request->getConfig('local_ip')) {
261
-            curl_setopt($ch, CURLOPT_INTERFACE, $ip);
262
-        }
263
-
264
-        // request timeout
265
-        if ($timeout = $this->request->getConfig('timeout')) {
266
-            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
267
-        }
268
-
269
-        // set HTTP version
270
-        switch ($this->request->getConfig('protocol_version')) {
271
-        case '1.0':
272
-            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
273
-            break;
274
-        case '1.1':
275
-            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
276
-        }
277
-
278
-        // set request method
279
-        switch ($this->request->getMethod()) {
280
-        case HTTP_Request2::METHOD_GET:
281
-            curl_setopt($ch, CURLOPT_HTTPGET, true);
282
-            break;
283
-        case HTTP_Request2::METHOD_POST:
284
-            curl_setopt($ch, CURLOPT_POST, true);
285
-            break;
286
-        case HTTP_Request2::METHOD_HEAD:
287
-            curl_setopt($ch, CURLOPT_NOBODY, true);
288
-            break;
289
-        case HTTP_Request2::METHOD_PUT:
290
-            curl_setopt($ch, CURLOPT_UPLOAD, true);
291
-            break;
292
-        default:
293
-            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());
294
-        }
295
-
296
-        // set proxy, if needed
297
-        if ($host = $this->request->getConfig('proxy_host')) {
298
-            if (!($port = $this->request->getConfig('proxy_port'))) {
299
-                throw new HTTP_Request2_LogicException(
300
-                    'Proxy port not provided', HTTP_Request2_Exception::MISSING_VALUE
301
-                );
302
-            }
303
-            curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port);
304
-            if ($user = $this->request->getConfig('proxy_user')) {
305
-                curl_setopt(
306
-                    $ch, CURLOPT_PROXYUSERPWD,
307
-                    $user . ':' . $this->request->getConfig('proxy_password')
308
-                );
309
-                switch ($this->request->getConfig('proxy_auth_scheme')) {
310
-                case HTTP_Request2::AUTH_BASIC:
311
-                    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
312
-                    break;
313
-                case HTTP_Request2::AUTH_DIGEST:
314
-                    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
315
-                }
316
-            }
317
-            if ($type = $this->request->getConfig('proxy_type')) {
318
-                switch ($type) {
319
-                case 'http':
320
-                    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
321
-                    break;
322
-                case 'socks5':
323
-                    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
324
-                    break;
325
-                default:
326
-                    throw new HTTP_Request2_NotImplementedException(
327
-                        "Proxy type '{$type}' is not supported"
328
-                    );
329
-                }
330
-            }
331
-        }
332
-
333
-        // set authentication data
334
-        if ($auth = $this->request->getAuth()) {
335
-            curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']);
336
-            switch ($auth['scheme']) {
337
-            case HTTP_Request2::AUTH_BASIC:
338
-                curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
339
-                break;
340
-            case HTTP_Request2::AUTH_DIGEST:
341
-                curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
342
-            }
343
-        }
344
-
345
-        // set SSL options
346
-        foreach ($this->request->getConfig() as $name => $value) {
347
-            if ('ssl_verify_host' == $name && null !== $value) {
348
-                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0);
349
-            } elseif (isset(self::$sslContextMap[$name]) && null !== $value) {
350
-                curl_setopt($ch, self::$sslContextMap[$name], $value);
351
-            }
352
-        }
353
-
354
-        $headers = $this->request->getHeaders();
355
-        // make cURL automagically send proper header
356
-        if (!isset($headers['accept-encoding'])) {
357
-            $headers['accept-encoding'] = '';
358
-        }
359
-
360
-        if (($jar = $this->request->getCookieJar())
361
-            && ($cookies = $jar->getMatching($this->request->getUrl(), true))
362
-        ) {
363
-            $headers['cookie'] = (empty($headers['cookie'])? '': $headers['cookie'] . '; ') . $cookies;
364
-        }
365
-
366
-        // set headers having special cURL keys
367
-        foreach (self::$headerMap as $name => $option) {
368
-            if (isset($headers[$name])) {
369
-                curl_setopt($ch, $option, $headers[$name]);
370
-                unset($headers[$name]);
371
-            }
372
-        }
373
-
374
-        $this->calculateRequestLength($headers);
375
-        if (isset($headers['content-length']) || isset($headers['transfer-encoding'])) {
376
-            $this->workaroundPhpBug47204($ch, $headers);
377
-        }
378
-
379
-        // set headers not having special keys
380
-        $headersFmt = array();
381
-        foreach ($headers as $name => $value) {
382
-            $canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
383
-            $headersFmt[]  = $canonicalName . ': ' . $value;
384
-        }
385
-        curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt);
386
-
387
-        return $ch;
388
-    }
389
-
390
-    /**
391
-     * Workaround for PHP bug #47204 that prevents rewinding request body
392
-     *
393
-     * The workaround consists of reading the entire request body into memory
394
-     * and setting it as CURLOPT_POSTFIELDS, so it isn't recommended for large
395
-     * file uploads, use Socket adapter instead.
396
-     *
397
-     * @param resource $ch       cURL handle
398
-     * @param array    &$headers Request headers
399
-     */
400
-    protected function workaroundPhpBug47204($ch, &$headers)
401
-    {
402
-        // no redirects, no digest auth -> probably no rewind needed
403
-        if (!$this->request->getConfig('follow_redirects')
404
-            && (!($auth = $this->request->getAuth())
405
-                || HTTP_Request2::AUTH_DIGEST != $auth['scheme'])
406
-        ) {
407
-            curl_setopt($ch, CURLOPT_READFUNCTION, array($this, 'callbackReadBody'));
408
-
409
-        } else {
410
-            // rewind may be needed, read the whole body into memory
411
-            if ($this->requestBody instanceof HTTP_Request2_MultipartBody) {
412
-                $this->requestBody = $this->requestBody->__toString();
413
-
414
-            } elseif (is_resource($this->requestBody)) {
415
-                $fp = $this->requestBody;
416
-                $this->requestBody = '';
417
-                while (!feof($fp)) {
418
-                    $this->requestBody .= fread($fp, 16384);
419
-                }
420
-            }
421
-            // curl hangs up if content-length is present
422
-            unset($headers['content-length']);
423
-            curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody);
424
-        }
425
-    }
426
-
427
-    /**
428
-     * Callback function called by cURL for reading the request body
429
-     *
430
-     * @param resource $ch     cURL handle
431
-     * @param resource $fd     file descriptor (not used)
432
-     * @param integer  $length maximum length of data to return
433
-     *
434
-     * @return   string      part of the request body, up to $length bytes
435
-     */
436
-    protected function callbackReadBody($ch, $fd, $length)
437
-    {
438
-        if (!$this->eventSentHeaders) {
439
-            $this->request->setLastEvent(
440
-                'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
441
-            );
442
-            $this->eventSentHeaders = true;
443
-        }
444
-        if (in_array($this->request->getMethod(), self::$bodyDisallowed)
445
-            || 0 == $this->contentLength || $this->position >= $this->contentLength
446
-        ) {
447
-            return '';
448
-        }
449
-        if (is_string($this->requestBody)) {
450
-            $string = substr($this->requestBody, $this->position, $length);
451
-        } elseif (is_resource($this->requestBody)) {
452
-            $string = fread($this->requestBody, $length);
453
-        } else {
454
-            $string = $this->requestBody->read($length);
455
-        }
456
-        $this->request->setLastEvent('sentBodyPart', strlen($string));
457
-        $this->position += strlen($string);
458
-        return $string;
459
-    }
460
-
461
-    /**
462
-     * Callback function called by cURL for saving the response headers
463
-     *
464
-     * @param resource $ch     cURL handle
465
-     * @param string   $string response header (with trailing CRLF)
466
-     *
467
-     * @return   integer     number of bytes saved
468
-     * @see      HTTP_Request2_Response::parseHeaderLine()
469
-     */
470
-    protected function callbackWriteHeader($ch, $string)
471
-    {
472
-        // we may receive a second set of headers if doing e.g. digest auth
473
-        if ($this->eventReceivedHeaders || !$this->eventSentHeaders) {
474
-            // don't bother with 100-Continue responses (bug #15785)
475
-            if (!$this->eventSentHeaders
476
-                || $this->response->getStatus() >= 200
477
-            ) {
478
-                $this->request->setLastEvent(
479
-                    'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
480
-                );
481
-            }
482
-            $upload = curl_getinfo($ch, CURLINFO_SIZE_UPLOAD);
483
-            // if body wasn't read by a callback, send event with total body size
484
-            if ($upload > $this->position) {
485
-                $this->request->setLastEvent(
486
-                    'sentBodyPart', $upload - $this->position
487
-                );
488
-                $this->position = $upload;
489
-            }
490
-            if ($upload && (!$this->eventSentHeaders
491
-                            || $this->response->getStatus() >= 200)
492
-            ) {
493
-                $this->request->setLastEvent('sentBody', $upload);
494
-            }
495
-            $this->eventSentHeaders = true;
496
-            // we'll need a new response object
497
-            if ($this->eventReceivedHeaders) {
498
-                $this->eventReceivedHeaders = false;
499
-                $this->response             = null;
500
-            }
501
-        }
502
-        if (empty($this->response)) {
503
-            $this->response = new HTTP_Request2_Response(
504
-                $string, false, curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)
505
-            );
506
-        } else {
507
-            $this->response->parseHeaderLine($string);
508
-            if ('' == trim($string)) {
509
-                // don't bother with 100-Continue responses (bug #15785)
510
-                if (200 <= $this->response->getStatus()) {
511
-                    $this->request->setLastEvent('receivedHeaders', $this->response);
512
-                }
513
-
514
-                if ($this->request->getConfig('follow_redirects') && $this->response->isRedirect()) {
515
-                    $redirectUrl = new Net_URL2($this->response->getHeader('location'));
516
-
517
-                    // for versions lower than 5.2.10, check the redirection URL protocol
518
-                    if (!defined('CURLOPT_REDIR_PROTOCOLS') && $redirectUrl->isAbsolute()
519
-                        && !in_array($redirectUrl->getScheme(), array('http', 'https'))
520
-                    ) {
521
-                        return -1;
522
-                    }
523
-
524
-                    if ($jar = $this->request->getCookieJar()) {
525
-                        $jar->addCookiesFromResponse($this->response, $this->request->getUrl());
526
-                        if (!$redirectUrl->isAbsolute()) {
527
-                            $redirectUrl = $this->request->getUrl()->resolve($redirectUrl);
528
-                        }
529
-                        if ($cookies = $jar->getMatching($redirectUrl, true)) {
530
-                            curl_setopt($ch, CURLOPT_COOKIE, $cookies);
531
-                        }
532
-                    }
533
-                }
534
-                $this->eventReceivedHeaders = true;
535
-            }
536
-        }
537
-        return strlen($string);
538
-    }
539
-
540
-    /**
541
-     * Callback function called by cURL for saving the response body
542
-     *
543
-     * @param resource $ch     cURL handle (not used)
544
-     * @param string   $string part of the response body
545
-     *
546
-     * @return   integer     number of bytes saved
547
-     * @throws   HTTP_Request2_MessageException
548
-     * @see      HTTP_Request2_Response::appendBody()
549
-     */
550
-    protected function callbackWriteBody($ch, $string)
551
-    {
552
-        // cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if
553
-        // response doesn't start with proper HTTP status line (see bug #15716)
554
-        if (empty($this->response)) {
555
-            throw new HTTP_Request2_MessageException(
556
-                "Malformed response: {$string}",
557
-                HTTP_Request2_Exception::MALFORMED_RESPONSE
558
-            );
559
-        }
560
-        if ($this->request->getConfig('store_body')) {
561
-            $this->response->appendBody($string);
562
-        }
563
-        $this->request->setLastEvent('receivedBodyPart', $string);
564
-        return strlen($string);
565
-    }
38
+	/**
39
+	 * Mapping of header names to cURL options
40
+	 * @var  array
41
+	 */
42
+	protected static $headerMap = array(
43
+		'accept-encoding' => CURLOPT_ENCODING,
44
+		'cookie'          => CURLOPT_COOKIE,
45
+		'referer'         => CURLOPT_REFERER,
46
+		'user-agent'      => CURLOPT_USERAGENT
47
+	);
48
+
49
+	/**
50
+	 * Mapping of SSL context options to cURL options
51
+	 * @var  array
52
+	 */
53
+	protected static $sslContextMap = array(
54
+		'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER,
55
+		'ssl_cafile'      => CURLOPT_CAINFO,
56
+		'ssl_capath'      => CURLOPT_CAPATH,
57
+		'ssl_local_cert'  => CURLOPT_SSLCERT,
58
+		'ssl_passphrase'  => CURLOPT_SSLCERTPASSWD
59
+	);
60
+
61
+	/**
62
+	 * Mapping of CURLE_* constants to Exception subclasses and error codes
63
+	 * @var  array
64
+	 */
65
+	protected static $errorMap = array(
66
+		CURLE_UNSUPPORTED_PROTOCOL  => array('HTTP_Request2_MessageException',
67
+											 HTTP_Request2_Exception::NON_HTTP_REDIRECT),
68
+		CURLE_COULDNT_RESOLVE_PROXY => array('HTTP_Request2_ConnectionException'),
69
+		CURLE_COULDNT_RESOLVE_HOST  => array('HTTP_Request2_ConnectionException'),
70
+		CURLE_COULDNT_CONNECT       => array('HTTP_Request2_ConnectionException'),
71
+		// error returned from write callback
72
+		CURLE_WRITE_ERROR           => array('HTTP_Request2_MessageException',
73
+											 HTTP_Request2_Exception::NON_HTTP_REDIRECT),
74
+		CURLE_OPERATION_TIMEOUTED   => array('HTTP_Request2_MessageException',
75
+											 HTTP_Request2_Exception::TIMEOUT),
76
+		CURLE_HTTP_RANGE_ERROR      => array('HTTP_Request2_MessageException'),
77
+		CURLE_SSL_CONNECT_ERROR     => array('HTTP_Request2_ConnectionException'),
78
+		CURLE_LIBRARY_NOT_FOUND     => array('HTTP_Request2_LogicException',
79
+											 HTTP_Request2_Exception::MISCONFIGURATION),
80
+		CURLE_FUNCTION_NOT_FOUND    => array('HTTP_Request2_LogicException',
81
+											 HTTP_Request2_Exception::MISCONFIGURATION),
82
+		CURLE_ABORTED_BY_CALLBACK   => array('HTTP_Request2_MessageException',
83
+											 HTTP_Request2_Exception::NON_HTTP_REDIRECT),
84
+		CURLE_TOO_MANY_REDIRECTS    => array('HTTP_Request2_MessageException',
85
+											 HTTP_Request2_Exception::TOO_MANY_REDIRECTS),
86
+		CURLE_SSL_PEER_CERTIFICATE  => array('HTTP_Request2_ConnectionException'),
87
+		CURLE_GOT_NOTHING           => array('HTTP_Request2_MessageException'),
88
+		CURLE_SSL_ENGINE_NOTFOUND   => array('HTTP_Request2_LogicException',
89
+											 HTTP_Request2_Exception::MISCONFIGURATION),
90
+		CURLE_SSL_ENGINE_SETFAILED  => array('HTTP_Request2_LogicException',
91
+											 HTTP_Request2_Exception::MISCONFIGURATION),
92
+		CURLE_SEND_ERROR            => array('HTTP_Request2_MessageException'),
93
+		CURLE_RECV_ERROR            => array('HTTP_Request2_MessageException'),
94
+		CURLE_SSL_CERTPROBLEM       => array('HTTP_Request2_LogicException',
95
+											 HTTP_Request2_Exception::INVALID_ARGUMENT),
96
+		CURLE_SSL_CIPHER            => array('HTTP_Request2_ConnectionException'),
97
+		CURLE_SSL_CACERT            => array('HTTP_Request2_ConnectionException'),
98
+		CURLE_BAD_CONTENT_ENCODING  => array('HTTP_Request2_MessageException'),
99
+	);
100
+
101
+	/**
102
+	 * Response being received
103
+	 * @var  HTTP_Request2_Response
104
+	 */
105
+	protected $response;
106
+
107
+	/**
108
+	 * Whether 'sentHeaders' event was sent to observers
109
+	 * @var  boolean
110
+	 */
111
+	protected $eventSentHeaders = false;
112
+
113
+	/**
114
+	 * Whether 'receivedHeaders' event was sent to observers
115
+	 * @var boolean
116
+	 */
117
+	protected $eventReceivedHeaders = false;
118
+
119
+	/**
120
+	 * Position within request body
121
+	 * @var  integer
122
+	 * @see  callbackReadBody()
123
+	 */
124
+	protected $position = 0;
125
+
126
+	/**
127
+	 * Information about last transfer, as returned by curl_getinfo()
128
+	 * @var  array
129
+	 */
130
+	protected $lastInfo;
131
+
132
+	/**
133
+	 * Creates a subclass of HTTP_Request2_Exception from curl error data
134
+	 *
135
+	 * @param resource $ch curl handle
136
+	 *
137
+	 * @return HTTP_Request2_Exception
138
+	 */
139
+	protected static function wrapCurlError($ch)
140
+	{
141
+		$nativeCode = curl_errno($ch);
142
+		$message    = 'Curl error: ' . curl_error($ch);
143
+		if (!isset(self::$errorMap[$nativeCode])) {
144
+			return new HTTP_Request2_Exception($message, 0, $nativeCode);
145
+		} else {
146
+			$class = self::$errorMap[$nativeCode][0];
147
+			$code  = empty(self::$errorMap[$nativeCode][1])
148
+					 ? 0 : self::$errorMap[$nativeCode][1];
149
+			return new $class($message, $code, $nativeCode);
150
+		}
151
+	}
152
+
153
+	/**
154
+	 * Sends request to the remote server and returns its response
155
+	 *
156
+	 * @param HTTP_Request2 $request HTTP request message
157
+	 *
158
+	 * @return   HTTP_Request2_Response
159
+	 * @throws   HTTP_Request2_Exception
160
+	 */
161
+	public function sendRequest(HTTP_Request2 $request)
162
+	{
163
+		if (!extension_loaded('curl')) {
164
+			throw new HTTP_Request2_LogicException(
165
+				'cURL extension not available', HTTP_Request2_Exception::MISCONFIGURATION
166
+			);
167
+		}
168
+
169
+		$this->request              = $request;
170
+		$this->response             = null;
171
+		$this->position             = 0;
172
+		$this->eventSentHeaders     = false;
173
+		$this->eventReceivedHeaders = false;
174
+
175
+		try {
176
+			if (false === curl_exec($ch = $this->createCurlHandle())) {
177
+				$e = self::wrapCurlError($ch);
178
+			}
179
+		} catch (Exception $e) {
180
+		}
181
+		if (isset($ch)) {
182
+			$this->lastInfo = curl_getinfo($ch);
183
+			curl_close($ch);
184
+		}
185
+
186
+		$response = $this->response;
187
+		unset($this->request, $this->requestBody, $this->response);
188
+
189
+		if (!empty($e)) {
190
+			throw $e;
191
+		}
192
+
193
+		if ($jar = $request->getCookieJar()) {
194
+			$jar->addCookiesFromResponse($response, $request->getUrl());
195
+		}
196
+
197
+		if (0 < $this->lastInfo['size_download']) {
198
+			$request->setLastEvent('receivedBody', $response);
199
+		}
200
+		return $response;
201
+	}
202
+
203
+	/**
204
+	 * Returns information about last transfer
205
+	 *
206
+	 * @return   array   associative array as returned by curl_getinfo()
207
+	 */
208
+	public function getInfo()
209
+	{
210
+		return $this->lastInfo;
211
+	}
212
+
213
+	/**
214
+	 * Creates a new cURL handle and populates it with data from the request
215
+	 *
216
+	 * @return   resource    a cURL handle, as created by curl_init()
217
+	 * @throws   HTTP_Request2_LogicException
218
+	 * @throws   HTTP_Request2_NotImplementedException
219
+	 */
220
+	protected function createCurlHandle()
221
+	{
222
+		$ch = curl_init();
223
+
224
+		curl_setopt_array($ch, array(
225
+			// setup write callbacks
226
+			CURLOPT_HEADERFUNCTION => array($this, 'callbackWriteHeader'),
227
+			CURLOPT_WRITEFUNCTION  => array($this, 'callbackWriteBody'),
228
+			// buffer size
229
+			CURLOPT_BUFFERSIZE     => $this->request->getConfig('buffer_size'),
230
+			// connection timeout
231
+			CURLOPT_CONNECTTIMEOUT => $this->request->getConfig('connect_timeout'),
232
+			// save full outgoing headers, in case someone is interested
233
+			CURLINFO_HEADER_OUT    => true,
234
+			// request url
235
+			CURLOPT_URL            => $this->request->getUrl()->getUrl()
236
+		));
237
+
238
+		// set up redirects
239
+		if (!$this->request->getConfig('follow_redirects')) {
240
+			curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
241
+		} else {
242
+			if (!@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)) {
243
+				throw new HTTP_Request2_LogicException(
244
+					'Redirect support in curl is unavailable due to open_basedir or safe_mode setting',
245
+					HTTP_Request2_Exception::MISCONFIGURATION
246
+				);
247
+			}
248
+			curl_setopt($ch, CURLOPT_MAXREDIRS, $this->request->getConfig('max_redirects'));
249
+			// limit redirects to http(s), works in 5.2.10+
250
+			if (defined('CURLOPT_REDIR_PROTOCOLS')) {
251
+				curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
252
+			}
253
+			// works in 5.3.2+, http://bugs.php.net/bug.php?id=49571
254
+			if ($this->request->getConfig('strict_redirects') && defined('CURLOPT_POSTREDIR')) {
255
+				curl_setopt($ch, CURLOPT_POSTREDIR, 3);
256
+			}
257
+		}
258
+
259
+		// set local IP via CURLOPT_INTERFACE (request #19515)
260
+		if ($ip = $this->request->getConfig('local_ip')) {
261
+			curl_setopt($ch, CURLOPT_INTERFACE, $ip);
262
+		}
263
+
264
+		// request timeout
265
+		if ($timeout = $this->request->getConfig('timeout')) {
266
+			curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
267
+		}
268
+
269
+		// set HTTP version
270
+		switch ($this->request->getConfig('protocol_version')) {
271
+		case '1.0':
272
+			curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
273
+			break;
274
+		case '1.1':
275
+			curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
276
+		}
277
+
278
+		// set request method
279
+		switch ($this->request->getMethod()) {
280
+		case HTTP_Request2::METHOD_GET:
281
+			curl_setopt($ch, CURLOPT_HTTPGET, true);
282
+			break;
283
+		case HTTP_Request2::METHOD_POST:
284
+			curl_setopt($ch, CURLOPT_POST, true);
285
+			break;
286
+		case HTTP_Request2::METHOD_HEAD:
287
+			curl_setopt($ch, CURLOPT_NOBODY, true);
288
+			break;
289
+		case HTTP_Request2::METHOD_PUT:
290
+			curl_setopt($ch, CURLOPT_UPLOAD, true);
291
+			break;
292
+		default:
293
+			curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());
294
+		}
295
+
296
+		// set proxy, if needed
297
+		if ($host = $this->request->getConfig('proxy_host')) {
298
+			if (!($port = $this->request->getConfig('proxy_port'))) {
299
+				throw new HTTP_Request2_LogicException(
300
+					'Proxy port not provided', HTTP_Request2_Exception::MISSING_VALUE
301
+				);
302
+			}
303
+			curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port);
304
+			if ($user = $this->request->getConfig('proxy_user')) {
305
+				curl_setopt(
306
+					$ch, CURLOPT_PROXYUSERPWD,
307
+					$user . ':' . $this->request->getConfig('proxy_password')
308
+				);
309
+				switch ($this->request->getConfig('proxy_auth_scheme')) {
310
+				case HTTP_Request2::AUTH_BASIC:
311
+					curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
312
+					break;
313
+				case HTTP_Request2::AUTH_DIGEST:
314
+					curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
315
+				}
316
+			}
317
+			if ($type = $this->request->getConfig('proxy_type')) {
318
+				switch ($type) {
319
+				case 'http':
320
+					curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
321
+					break;
322
+				case 'socks5':
323
+					curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
324
+					break;
325
+				default:
326
+					throw new HTTP_Request2_NotImplementedException(
327
+						"Proxy type '{$type}' is not supported"
328
+					);
329
+				}
330
+			}
331
+		}
332
+
333
+		// set authentication data
334
+		if ($auth = $this->request->getAuth()) {
335
+			curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']);
336
+			switch ($auth['scheme']) {
337
+			case HTTP_Request2::AUTH_BASIC:
338
+				curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
339
+				break;
340
+			case HTTP_Request2::AUTH_DIGEST:
341
+				curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
342
+			}
343
+		}
344
+
345
+		// set SSL options
346
+		foreach ($this->request->getConfig() as $name => $value) {
347
+			if ('ssl_verify_host' == $name && null !== $value) {
348
+				curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0);
349
+			} elseif (isset(self::$sslContextMap[$name]) && null !== $value) {
350
+				curl_setopt($ch, self::$sslContextMap[$name], $value);
351
+			}
352
+		}
353
+
354
+		$headers = $this->request->getHeaders();
355
+		// make cURL automagically send proper header
356
+		if (!isset($headers['accept-encoding'])) {
357
+			$headers['accept-encoding'] = '';
358
+		}
359
+
360
+		if (($jar = $this->request->getCookieJar())
361
+			&& ($cookies = $jar->getMatching($this->request->getUrl(), true))
362
+		) {
363
+			$headers['cookie'] = (empty($headers['cookie'])? '': $headers['cookie'] . '; ') . $cookies;
364
+		}
365
+
366
+		// set headers having special cURL keys
367
+		foreach (self::$headerMap as $name => $option) {
368
+			if (isset($headers[$name])) {
369
+				curl_setopt($ch, $option, $headers[$name]);
370
+				unset($headers[$name]);
371
+			}
372
+		}
373
+
374
+		$this->calculateRequestLength($headers);
375
+		if (isset($headers['content-length']) || isset($headers['transfer-encoding'])) {
376
+			$this->workaroundPhpBug47204($ch, $headers);
377
+		}
378
+
379
+		// set headers not having special keys
380
+		$headersFmt = array();
381
+		foreach ($headers as $name => $value) {
382
+			$canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
383
+			$headersFmt[]  = $canonicalName . ': ' . $value;
384
+		}
385
+		curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt);
386
+
387
+		return $ch;
388
+	}
389
+
390
+	/**
391
+	 * Workaround for PHP bug #47204 that prevents rewinding request body
392
+	 *
393
+	 * The workaround consists of reading the entire request body into memory
394
+	 * and setting it as CURLOPT_POSTFIELDS, so it isn't recommended for large
395
+	 * file uploads, use Socket adapter instead.
396
+	 *
397
+	 * @param resource $ch       cURL handle
398
+	 * @param array    &$headers Request headers
399
+	 */
400
+	protected function workaroundPhpBug47204($ch, &$headers)
401
+	{
402
+		// no redirects, no digest auth -> probably no rewind needed
403
+		if (!$this->request->getConfig('follow_redirects')
404
+			&& (!($auth = $this->request->getAuth())
405
+				|| HTTP_Request2::AUTH_DIGEST != $auth['scheme'])
406
+		) {
407
+			curl_setopt($ch, CURLOPT_READFUNCTION, array($this, 'callbackReadBody'));
408
+
409
+		} else {
410
+			// rewind may be needed, read the whole body into memory
411
+			if ($this->requestBody instanceof HTTP_Request2_MultipartBody) {
412
+				$this->requestBody = $this->requestBody->__toString();
413
+
414
+			} elseif (is_resource($this->requestBody)) {
415
+				$fp = $this->requestBody;
416
+				$this->requestBody = '';
417
+				while (!feof($fp)) {
418
+					$this->requestBody .= fread($fp, 16384);
419
+				}
420
+			}
421
+			// curl hangs up if content-length is present
422
+			unset($headers['content-length']);
423
+			curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody);
424
+		}
425
+	}
426
+
427
+	/**
428
+	 * Callback function called by cURL for reading the request body
429
+	 *
430
+	 * @param resource $ch     cURL handle
431
+	 * @param resource $fd     file descriptor (not used)
432
+	 * @param integer  $length maximum length of data to return
433
+	 *
434
+	 * @return   string      part of the request body, up to $length bytes
435
+	 */
436
+	protected function callbackReadBody($ch, $fd, $length)
437
+	{
438
+		if (!$this->eventSentHeaders) {
439
+			$this->request->setLastEvent(
440
+				'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
441
+			);
442
+			$this->eventSentHeaders = true;
443
+		}
444
+		if (in_array($this->request->getMethod(), self::$bodyDisallowed)
445
+			|| 0 == $this->contentLength || $this->position >= $this->contentLength
446
+		) {
447
+			return '';
448
+		}
449
+		if (is_string($this->requestBody)) {
450
+			$string = substr($this->requestBody, $this->position, $length);
451
+		} elseif (is_resource($this->requestBody)) {
452
+			$string = fread($this->requestBody, $length);
453
+		} else {
454
+			$string = $this->requestBody->read($length);
455
+		}
456
+		$this->request->setLastEvent('sentBodyPart', strlen($string));
457
+		$this->position += strlen($string);
458
+		return $string;
459
+	}
460
+
461
+	/**
462
+	 * Callback function called by cURL for saving the response headers
463
+	 *
464
+	 * @param resource $ch     cURL handle
465
+	 * @param string   $string response header (with trailing CRLF)
466
+	 *
467
+	 * @return   integer     number of bytes saved
468
+	 * @see      HTTP_Request2_Response::parseHeaderLine()
469
+	 */
470
+	protected function callbackWriteHeader($ch, $string)
471
+	{
472
+		// we may receive a second set of headers if doing e.g. digest auth
473
+		if ($this->eventReceivedHeaders || !$this->eventSentHeaders) {
474
+			// don't bother with 100-Continue responses (bug #15785)
475
+			if (!$this->eventSentHeaders
476
+				|| $this->response->getStatus() >= 200
477
+			) {
478
+				$this->request->setLastEvent(
479
+					'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
480
+				);
481
+			}
482
+			$upload = curl_getinfo($ch, CURLINFO_SIZE_UPLOAD);
483
+			// if body wasn't read by a callback, send event with total body size
484
+			if ($upload > $this->position) {
485
+				$this->request->setLastEvent(
486
+					'sentBodyPart', $upload - $this->position
487
+				);
488
+				$this->position = $upload;
489
+			}
490
+			if ($upload && (!$this->eventSentHeaders
491
+							|| $this->response->getStatus() >= 200)
492
+			) {
493
+				$this->request->setLastEvent('sentBody', $upload);
494
+			}
495
+			$this->eventSentHeaders = true;
496
+			// we'll need a new response object
497
+			if ($this->eventReceivedHeaders) {
498
+				$this->eventReceivedHeaders = false;
499
+				$this->response             = null;
500
+			}
501
+		}
502
+		if (empty($this->response)) {
503
+			$this->response = new HTTP_Request2_Response(
504
+				$string, false, curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)
505
+			);
506
+		} else {
507
+			$this->response->parseHeaderLine($string);
508
+			if ('' == trim($string)) {
509
+				// don't bother with 100-Continue responses (bug #15785)
510
+				if (200 <= $this->response->getStatus()) {
511
+					$this->request->setLastEvent('receivedHeaders', $this->response);
512
+				}
513
+
514
+				if ($this->request->getConfig('follow_redirects') && $this->response->isRedirect()) {
515
+					$redirectUrl = new Net_URL2($this->response->getHeader('location'));
516
+
517
+					// for versions lower than 5.2.10, check the redirection URL protocol
518
+					if (!defined('CURLOPT_REDIR_PROTOCOLS') && $redirectUrl->isAbsolute()
519
+						&& !in_array($redirectUrl->getScheme(), array('http', 'https'))
520
+					) {
521
+						return -1;
522
+					}
523
+
524
+					if ($jar = $this->request->getCookieJar()) {
525
+						$jar->addCookiesFromResponse($this->response, $this->request->getUrl());
526
+						if (!$redirectUrl->isAbsolute()) {
527
+							$redirectUrl = $this->request->getUrl()->resolve($redirectUrl);
528
+						}
529
+						if ($cookies = $jar->getMatching($redirectUrl, true)) {
530
+							curl_setopt($ch, CURLOPT_COOKIE, $cookies);
531
+						}
532
+					}
533
+				}
534
+				$this->eventReceivedHeaders = true;
535
+			}
536
+		}
537
+		return strlen($string);
538
+	}
539
+
540
+	/**
541
+	 * Callback function called by cURL for saving the response body
542
+	 *
543
+	 * @param resource $ch     cURL handle (not used)
544
+	 * @param string   $string part of the response body
545
+	 *
546
+	 * @return   integer     number of bytes saved
547
+	 * @throws   HTTP_Request2_MessageException
548
+	 * @see      HTTP_Request2_Response::appendBody()
549
+	 */
550
+	protected function callbackWriteBody($ch, $string)
551
+	{
552
+		// cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if
553
+		// response doesn't start with proper HTTP status line (see bug #15716)
554
+		if (empty($this->response)) {
555
+			throw new HTTP_Request2_MessageException(
556
+				"Malformed response: {$string}",
557
+				HTTP_Request2_Exception::MALFORMED_RESPONSE
558
+			);
559
+		}
560
+		if ($this->request->getConfig('store_body')) {
561
+			$this->response->appendBody($string);
562
+		}
563
+		$this->request->setLastEvent('receivedBodyPart', $string);
564
+		return strlen($string);
565
+	}
566 566
 }
567 567
 ?>
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
     protected static function wrapCurlError($ch)
140 140
     {
141 141
         $nativeCode = curl_errno($ch);
142
-        $message    = 'Curl error: ' . curl_error($ch);
142
+        $message    = 'Curl error: '.curl_error($ch);
143 143
         if (!isset(self::$errorMap[$nativeCode])) {
144 144
             return new HTTP_Request2_Exception($message, 0, $nativeCode);
145 145
         } else {
@@ -300,11 +300,11 @@  discard block
 block discarded – undo
300 300
                     'Proxy port not provided', HTTP_Request2_Exception::MISSING_VALUE
301 301
                 );
302 302
             }
303
-            curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port);
303
+            curl_setopt($ch, CURLOPT_PROXY, $host.':'.$port);
304 304
             if ($user = $this->request->getConfig('proxy_user')) {
305 305
                 curl_setopt(
306 306
                     $ch, CURLOPT_PROXYUSERPWD,
307
-                    $user . ':' . $this->request->getConfig('proxy_password')
307
+                    $user.':'.$this->request->getConfig('proxy_password')
308 308
                 );
309 309
                 switch ($this->request->getConfig('proxy_auth_scheme')) {
310 310
                 case HTTP_Request2::AUTH_BASIC:
@@ -332,7 +332,7 @@  discard block
 block discarded – undo
332 332
 
333 333
         // set authentication data
334 334
         if ($auth = $this->request->getAuth()) {
335
-            curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']);
335
+            curl_setopt($ch, CURLOPT_USERPWD, $auth['user'].':'.$auth['password']);
336 336
             switch ($auth['scheme']) {
337 337
             case HTTP_Request2::AUTH_BASIC:
338 338
                 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
         // set SSL options
346 346
         foreach ($this->request->getConfig() as $name => $value) {
347 347
             if ('ssl_verify_host' == $name && null !== $value) {
348
-                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0);
348
+                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value ? 2 : 0);
349 349
             } elseif (isset(self::$sslContextMap[$name]) && null !== $value) {
350 350
                 curl_setopt($ch, self::$sslContextMap[$name], $value);
351 351
             }
@@ -360,7 +360,7 @@  discard block
 block discarded – undo
360 360
         if (($jar = $this->request->getCookieJar())
361 361
             && ($cookies = $jar->getMatching($this->request->getUrl(), true))
362 362
         ) {
363
-            $headers['cookie'] = (empty($headers['cookie'])? '': $headers['cookie'] . '; ') . $cookies;
363
+            $headers['cookie'] = (empty($headers['cookie']) ? '' : $headers['cookie'].'; ').$cookies;
364 364
         }
365 365
 
366 366
         // set headers having special cURL keys
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
         $headersFmt = array();
381 381
         foreach ($headers as $name => $value) {
382 382
             $canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
383
-            $headersFmt[]  = $canonicalName . ': ' . $value;
383
+            $headersFmt[]  = $canonicalName.': '.$value;
384 384
         }
385 385
         curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt);
386 386
 
Please login to merge, or discard this patch.