This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace PHP2WSDL; |
||
4 | |||
5 | use DOMElement; |
||
6 | use InvalidArgumentException; |
||
7 | use Wingu\OctopusCore\Reflection\ReflectionClass; |
||
8 | use Wingu\OctopusCore\Reflection\ReflectionMethod; |
||
9 | |||
10 | /** |
||
11 | * Generate a WSDL from a PHP class. |
||
12 | */ |
||
13 | class PHPClass2WSDL |
||
14 | { |
||
15 | |||
16 | /** |
||
17 | * The class to transform. |
||
18 | * |
||
19 | * @var string |
||
20 | */ |
||
21 | protected $class; |
||
22 | |||
23 | /** |
||
24 | * The URL of the web service. |
||
25 | * |
||
26 | * @var string |
||
27 | */ |
||
28 | protected $uri; |
||
29 | |||
30 | /** |
||
31 | * The URI to the stylesheet file. |
||
32 | * |
||
33 | * @var string |
||
34 | */ |
||
35 | protected $xslUri; |
||
36 | |||
37 | /** |
||
38 | * The WSDL document. |
||
39 | * |
||
40 | * @var \PHP2WSDL\WSDL |
||
41 | */ |
||
42 | protected $wsdl; |
||
43 | |||
44 | /** |
||
45 | * The soap:operation style. |
||
46 | * |
||
47 | * @var array |
||
48 | */ |
||
49 | protected $bindingStyle = array( |
||
50 | 'style' => 'rpc', |
||
51 | 'transport' => 'http://schemas.xmlsoap.org/soap/http' |
||
52 | ); |
||
53 | |||
54 | /** |
||
55 | * The soap:body operation style options. |
||
56 | * |
||
57 | * @var array |
||
58 | */ |
||
59 | protected $operationBodyStyle = array( |
||
60 | 'use' => 'encoded', |
||
61 | 'encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/' |
||
62 | ); |
||
63 | |||
64 | /** |
||
65 | * Constructor. |
||
66 | * |
||
67 | * @param mixed $class The class name from which to generate the WSDL. |
||
68 | * @param string $uri The web service URL. |
||
69 | * @throws InvalidArgumentException If the class is not valid or not an object. |
||
70 | */ |
||
71 | 33 | public function __construct($class, $uri) |
|
72 | { |
||
73 | 33 | if (is_string($class) && class_exists($class)) { |
|
74 | 33 | $this->class = $class; |
|
75 | 33 | } elseif (is_object($class)) { |
|
76 | $this->class = get_class($class); |
||
77 | 3 | } else { |
|
78 | throw new InvalidArgumentException('Invalid class name or object to generate the WSDL for.'); |
||
79 | } |
||
80 | |||
81 | 33 | $this->uri = $uri; |
|
82 | 33 | } |
|
83 | |||
84 | /** |
||
85 | * Set the stylesheet for the WSDL. |
||
86 | * |
||
87 | * @param string $xslUri The URI to the stylesheet. |
||
88 | * @return PHPClass2WSDL |
||
89 | */ |
||
90 | 3 | public function setStylesheet($xslUri) |
|
91 | { |
||
92 | 3 | $this->xslUri = $xslUri; |
|
93 | |||
94 | 3 | return $this; |
|
95 | } |
||
96 | |||
97 | /** |
||
98 | * Set the binding style. |
||
99 | * |
||
100 | * @param string $style The style (rpc or document). |
||
101 | * @param string $transport The transport. |
||
102 | * @return PHPClass2WSDL |
||
103 | */ |
||
104 | 3 | public function setBindingStyle($style, $transport) |
|
105 | { |
||
106 | $this->bindingStyle['style'] = $style; |
||
107 | $this->bindingStyle['transport'] = $transport; |
||
108 | |||
109 | return $this; |
||
110 | 3 | } |
|
111 | |||
112 | /** |
||
113 | * Generate the WSDL DOMDocument. |
||
114 | * |
||
115 | * @param boolean $withAnnotation Flag if only the methods with '@soap' annotation should be added. |
||
116 | */ |
||
117 | 33 | public function generateWSDL($withAnnotation = false) |
|
118 | { |
||
119 | 33 | $qNameClassName = WSDL::typeToQName($this->class); |
|
120 | |||
121 | 33 | $this->wsdl = new WSDL($qNameClassName, $this->uri, $this->xslUri); |
|
122 | |||
123 | 33 | $port = $this->wsdl->addPortType($qNameClassName . 'Port'); |
|
124 | 33 | $binding = $this->wsdl->addBinding($qNameClassName . 'Binding', 'tns:' . $qNameClassName . 'Port'); |
|
125 | |||
126 | 33 | $this->wsdl->addSoapBinding($binding, $this->bindingStyle['style'], $this->bindingStyle['transport']); |
|
127 | 33 | $this->wsdl->addService( |
|
128 | 33 | $qNameClassName . 'Service', $qNameClassName . 'Port', |
|
129 | 33 | 'tns:' . $qNameClassName . 'Binding', |
|
130 | 33 | $this->uri |
|
131 | 33 | ); |
|
132 | |||
133 | 33 | $ref = new ReflectionClass($this->class); |
|
134 | 33 | foreach ($ref->getMethods() as $method) { |
|
135 | 30 | if ($withAnnotation === false || $method->getReflectionDocComment()->getAnnotationsCollection()->hasAnnotationTag('soap')) { |
|
0 ignored issues
–
show
|
|||
136 | 30 | $this->addMethodToWsdl($method, $port, $binding); |
|
0 ignored issues
–
show
$method of type object<ReflectionMethod> is not a sub-type of object<Wingu\OctopusCore...ction\ReflectionMethod> . It seems like you assume a child class of the class ReflectionMethod to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
137 | 30 | } |
|
138 | 33 | } |
|
139 | 33 | } |
|
140 | |||
141 | /** |
||
142 | * Add a method to the WSDL. |
||
143 | * |
||
144 | * @param ReflectionMethod $method The reflection of the method to add. |
||
145 | * @param DOMElement $port The portType element. |
||
146 | * @param DOMElement $binding The binding element. |
||
147 | */ |
||
148 | 30 | protected function addMethodToWsdl(ReflectionMethod $method, DOMElement $port, DOMElement $binding) |
|
149 | { |
||
150 | 30 | $qNameMethodName = WSDL::typeToQName($method->getName()); |
|
151 | |||
152 | 30 | $args = array(); |
|
153 | 30 | $annotations = array(); |
|
154 | 30 | $methodAnnotationsCollection = $method->getReflectionDocComment()->getAnnotationsCollection(); |
|
155 | 30 | if ($methodAnnotationsCollection->hasAnnotationTag('param')) { |
|
156 | /** @var \Wingu\OctopusCore\Reflection\Annotation\Tags\ParamTag $param */ |
||
157 | 30 | foreach ($methodAnnotationsCollection->getAnnotation('param') as $param) { |
|
158 | 30 | $annotations[$param->getParamName()] = $param; |
|
159 | 30 | } |
|
160 | 30 | } |
|
161 | |||
162 | 30 | if ($this->bindingStyle['style'] === 'document') { |
|
163 | $sequence = array(); |
||
164 | /** @var \Wingu\OctopusCore\Reflection\ReflectionParameter $param */ |
||
165 | foreach ($method->getParameters() as $param) { |
||
166 | $type = 'anytype'; |
||
167 | if (isset($annotations['$' . $param->getName()])) { |
||
168 | $type = $annotations['$' . $param->getName()]->getParamType(); |
||
169 | } |
||
170 | |||
171 | $sequenceElement = array('name' => $param->getName(), 'type' => $this->wsdl->getXSDType($type)); |
||
172 | if ($param->isOptional()) { |
||
173 | $sequenceElement['nillable'] = 'true'; |
||
174 | } |
||
175 | |||
176 | $sequence[] = $sequenceElement; |
||
177 | } |
||
178 | |||
179 | $element = array('name' => $qNameMethodName, 'sequence' => $sequence); |
||
180 | $args['parameters'] = array('element' => $this->wsdl->addElement($element)); |
||
181 | } else { |
||
182 | /** @var \Wingu\OctopusCore\Reflection\ReflectionParameter $param */ |
||
183 | 30 | foreach ($method->getParameters() as $param) { |
|
184 | 30 | $type = 'anytype'; |
|
185 | 30 | if (isset($annotations['$' . $param->getName()])) { |
|
186 | 30 | $type = $annotations['$' . $param->getName()]->getParamType(); |
|
187 | 30 | } |
|
188 | |||
189 | 30 | $args[$param->getName()] = array('type' => $this->wsdl->getXSDType($type)); |
|
190 | 30 | } |
|
191 | } |
||
192 | |||
193 | 30 | $this->wsdl->addMessage($qNameMethodName . 'In', $args); |
|
194 | |||
195 | 30 | $returnType = null; |
|
196 | 30 | if ($methodAnnotationsCollection->hasAnnotationTag('return') === true) { |
|
197 | 9 | $annotation = $methodAnnotationsCollection->getAnnotation('return'); |
|
198 | 9 | $annotation = reset($annotation); |
|
199 | 9 | $returnType = $annotation->getReturnType(); |
|
200 | 9 | } |
|
201 | |||
202 | 30 | $isOneWayMessage = ($returnType === null); |
|
203 | |||
204 | 30 | if ($isOneWayMessage === false) { |
|
205 | 9 | $args = array(); |
|
206 | 9 | if ($this->bindingStyle['style'] === 'document') { |
|
207 | $sequence = array(); |
||
208 | if ($returnType !== null) { |
||
209 | $sequence[] = array( |
||
210 | 'name' => $qNameMethodName . 'Result', |
||
211 | 'type' => $this->wsdl->getXSDType($returnType) |
||
212 | ); |
||
213 | } |
||
214 | |||
215 | $element = array('name' => $qNameMethodName . 'Response', 'sequence' => $sequence); |
||
216 | $args['parameters'] = array('element' => $this->wsdl->addElement($element)); |
||
217 | 9 | } elseif ($returnType !== null) { |
|
218 | 9 | $args['return'] = array('type' => $this->wsdl->getXSDType($returnType)); |
|
219 | 9 | } |
|
220 | |||
221 | 9 | $this->wsdl->addMessage($qNameMethodName . 'Out', $args); |
|
222 | 9 | } |
|
223 | |||
224 | // Add the portType operation. |
||
225 | 30 | if ($isOneWayMessage === false) { |
|
226 | 9 | $portOperation = $this->wsdl->addPortOperation( |
|
227 | 9 | $port, |
|
228 | 9 | $qNameMethodName, |
|
229 | 9 | 'tns:' . $qNameMethodName . 'In', |
|
230 | 9 | 'tns:' . $qNameMethodName . 'Out' |
|
231 | 9 | ); |
|
232 | 9 | } else { |
|
233 | 24 | $portOperation = $this->wsdl->addPortOperation($port, $qNameMethodName, 'tns:' . $qNameMethodName . 'In'); |
|
234 | } |
||
235 | |||
236 | // Add any documentation for the operation. |
||
237 | 30 | $description = $method->getReflectionDocComment()->getFullDescription(); |
|
238 | 30 | if (strlen($description) > 0) { |
|
239 | 9 | $this->wsdl->addDocumentation($portOperation, $description); |
|
240 | 9 | } |
|
241 | |||
242 | // When using the RPC style, make sure the operation style includes a 'namespace' attribute (WS-I Basic Profile 1.1 R2717). |
||
243 | 30 | if ($this->bindingStyle['style'] === 'rpc' && isset($this->operationBodyStyle['namespace']) === false) { |
|
244 | 30 | $this->operationBodyStyle['namespace'] = '' . htmlspecialchars($this->uri); |
|
245 | 30 | } |
|
246 | |||
247 | // Add the binding operation. |
||
248 | 30 | $operation = $this->wsdl->addBindingOperation( |
|
249 | 30 | $binding, |
|
250 | 30 | $qNameMethodName, |
|
251 | 30 | $this->operationBodyStyle, |
|
252 | 30 | $this->operationBodyStyle |
|
253 | 30 | ); |
|
254 | 30 | $this->wsdl->addSoapOperation($operation, $this->uri . '#' . $qNameMethodName); |
|
255 | 30 | } |
|
256 | |||
257 | /** |
||
258 | * Dump the WSDL as XML string. |
||
259 | * |
||
260 | * @param bool $formatOutput Format output |
||
261 | * @return mixed |
||
262 | */ |
||
263 | 33 | public function dump($formatOutput = true) |
|
264 | { |
||
265 | 33 | return $this->wsdl->dump($formatOutput); |
|
266 | } |
||
267 | |||
268 | /** |
||
269 | * Dump the WSDL as file. |
||
270 | * |
||
271 | * @param string $filename Filename to dump |
||
272 | * @param bool $formatOutput Format output |
||
273 | * @return mixed |
||
274 | */ |
||
275 | public function save($filename, $formatOutput = true) |
||
276 | { |
||
277 | return $this->wsdl->save($filename, $formatOutput); |
||
278 | } |
||
279 | } |
||
280 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: