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 | * @author Arthur Schiwon <[email protected]> |
||
4 | * @author Joas Schilling <[email protected]> |
||
5 | * @author Vincent Petry <[email protected]> |
||
6 | * |
||
7 | * @copyright Copyright (c) 2018, ownCloud GmbH |
||
8 | * @license AGPL-3.0 |
||
9 | * |
||
10 | * This code is free software: you can redistribute it and/or modify |
||
11 | * it under the terms of the GNU Affero General Public License, version 3, |
||
12 | * as published by the Free Software Foundation. |
||
13 | * |
||
14 | * This program is distributed in the hope that it will be useful, |
||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
17 | * GNU Affero General Public License for more details. |
||
18 | * |
||
19 | * You should have received a copy of the GNU Affero General Public License, version 3, |
||
20 | * along with this program. If not, see <http://www.gnu.org/licenses/> |
||
21 | * |
||
22 | */ |
||
23 | |||
24 | namespace OCA\Comments\Dav; |
||
25 | |||
26 | use OCP\Comments\IComment; |
||
27 | use OCP\Comments\ICommentsManager; |
||
28 | use OCP\IUserSession; |
||
29 | use Sabre\DAV\Exception\BadRequest; |
||
30 | use Sabre\DAV\Exception\NotFound; |
||
31 | use Sabre\DAV\Exception\ReportNotSupported; |
||
32 | use Sabre\DAV\Exception\UnsupportedMediaType; |
||
33 | use Sabre\DAV\Server; |
||
34 | use Sabre\DAV\ServerPlugin; |
||
35 | use Sabre\DAV\Xml\Element\Response; |
||
36 | use Sabre\DAV\Xml\Response\MultiStatus; |
||
37 | use Sabre\HTTP\RequestInterface; |
||
38 | use Sabre\HTTP\ResponseInterface; |
||
39 | use Sabre\Xml\Writer; |
||
40 | |||
41 | /** |
||
42 | * Sabre plugin to handle comments: |
||
43 | */ |
||
44 | class CommentsPlugin extends ServerPlugin { |
||
45 | // namespace |
||
46 | const NS_OWNCLOUD = 'http://owncloud.org/ns'; |
||
47 | |||
48 | const REPORT_NAME = '{http://owncloud.org/ns}filter-comments'; |
||
49 | const REPORT_PARAM_LIMIT = '{http://owncloud.org/ns}limit'; |
||
50 | const REPORT_PARAM_OFFSET = '{http://owncloud.org/ns}offset'; |
||
51 | const REPORT_PARAM_TIMESTAMP = '{http://owncloud.org/ns}datetime'; |
||
52 | |||
53 | /** @var ICommentsManager */ |
||
54 | protected $commentsManager; |
||
55 | |||
56 | /** @var \Sabre\DAV\Server $server */ |
||
57 | private $server; |
||
58 | |||
59 | /** @var \OCP\IUserSession */ |
||
60 | protected $userSession; |
||
61 | |||
62 | /** |
||
63 | * Comments plugin |
||
64 | * |
||
65 | * @param ICommentsManager $commentsManager |
||
66 | * @param IUserSession $userSession |
||
67 | */ |
||
68 | public function __construct(ICommentsManager $commentsManager, IUserSession $userSession) { |
||
69 | $this->commentsManager = $commentsManager; |
||
70 | $this->userSession = $userSession; |
||
71 | } |
||
72 | |||
73 | /** |
||
74 | * This initializes the plugin. |
||
75 | * |
||
76 | * This function is called by Sabre\DAV\Server, after |
||
77 | * addPlugin is called. |
||
78 | * |
||
79 | * This method should set up the required event subscriptions. |
||
80 | * |
||
81 | * @param Server $server |
||
82 | * @return void |
||
83 | */ |
||
84 | public function initialize(Server $server) { |
||
85 | $this->server = $server; |
||
86 | if (\strpos($this->server->getRequestUri(), 'comments/') !== 0) { |
||
87 | return; |
||
88 | } |
||
89 | |||
90 | if ($this->userSession === null || $this->userSession->getUser() === null) { |
||
91 | return; |
||
92 | } |
||
93 | |||
94 | $this->server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc'; |
||
95 | |||
96 | $this->server->xml->classMap['DateTime'] = function (Writer $writer, \DateTime $value) { |
||
97 | $writer->write(\Sabre\HTTP\toDate($value)); |
||
98 | }; |
||
99 | |||
100 | $this->server->on('report', [$this, 'onReport']); |
||
101 | $this->server->on('method:POST', [$this, 'httpPost']); |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * POST operation on Comments collections |
||
106 | * |
||
107 | * @param RequestInterface $request request object |
||
108 | * @param ResponseInterface $response response object |
||
109 | * @return null|false |
||
110 | */ |
||
111 | public function httpPost(RequestInterface $request, ResponseInterface $response) { |
||
112 | $path = $request->getPath(); |
||
113 | $node = $this->server->tree->getNodeForPath($path); |
||
114 | if (!$node instanceof EntityCollection) { |
||
115 | return null; |
||
116 | } |
||
117 | |||
118 | $data = $request->getBodyAsString(); |
||
119 | $comment = $this->createComment( |
||
120 | $node->getName(), |
||
121 | $node->getId(), |
||
122 | $data, |
||
123 | $request->getHeader('Content-Type') |
||
124 | ); |
||
125 | |||
126 | // update read marker for the current user/poster to avoid |
||
127 | // having their own comments marked as unread |
||
128 | $node->setReadMarker(null); |
||
0 ignored issues
–
show
|
|||
129 | |||
130 | $url = \rtrim($request->getUrl(), '/') . '/' . \urlencode($comment->getId()); |
||
131 | |||
132 | $response->setHeader('Content-Location', $url); |
||
133 | |||
134 | // created |
||
135 | $response->setStatus(201); |
||
136 | return false; |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * Returns a list of reports this plugin supports. |
||
141 | * |
||
142 | * This will be used in the {DAV:}supported-report-set property. |
||
143 | * |
||
144 | * @param string $uri |
||
145 | * @return array |
||
146 | */ |
||
147 | public function getSupportedReportSet($uri) { |
||
148 | return [self::REPORT_NAME]; |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * REPORT operations to look for comments |
||
153 | * |
||
154 | * @param string $reportName |
||
155 | * @param [] $report |
||
0 ignored issues
–
show
The doc-type
[] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.
Loading history...
|
|||
156 | * @param string $uri |
||
157 | * @return bool |
||
158 | * @throws NotFound |
||
159 | * @throws ReportNotSupported |
||
160 | */ |
||
161 | public function onReport($reportName, $report, $uri) { |
||
162 | $node = $this->server->tree->getNodeForPath($uri); |
||
163 | if (!$node instanceof EntityCollection || $reportName !== self::REPORT_NAME) { |
||
164 | throw new ReportNotSupported(); |
||
165 | } |
||
166 | $args = ['limit' => 0, 'offset' => 0, 'datetime' => null]; |
||
167 | $acceptableParameters = [ |
||
168 | $this::REPORT_PARAM_LIMIT, |
||
169 | $this::REPORT_PARAM_OFFSET, |
||
170 | $this::REPORT_PARAM_TIMESTAMP |
||
171 | ]; |
||
172 | $ns = '{' . $this::NS_OWNCLOUD . '}'; |
||
173 | foreach ($report as $parameter) { |
||
174 | if (!\in_array($parameter['name'], $acceptableParameters) || empty($parameter['value'])) { |
||
175 | continue; |
||
176 | } |
||
177 | $args[\str_replace($ns, '', $parameter['name'])] = $parameter['value']; |
||
178 | } |
||
179 | |||
180 | if ($args['datetime'] !== null) { |
||
181 | $args['datetime'] = new \DateTime($args['datetime']); |
||
182 | } |
||
183 | |||
184 | $results = $node->findChildren($args['limit'], $args['offset'], $args['datetime']); |
||
185 | |||
186 | $responses = []; |
||
187 | foreach ($results as $node) { |
||
188 | $nodePath = $this->server->getRequestUri() . '/' . $node->comment->getId(); |
||
189 | $resultSet = $this->server->getPropertiesForPath($nodePath, CommentNode::getPropertyNames()); |
||
190 | if (isset($resultSet[0], $resultSet[0][200])) { |
||
191 | $responses[] = new Response( |
||
192 | $this->server->getBaseUri() . $nodePath, |
||
193 | [200 => $resultSet[0][200]], |
||
194 | 200 |
||
195 | ); |
||
196 | } |
||
197 | } |
||
198 | |||
199 | $xml = $this->server->xml->write( |
||
200 | '{DAV:}multistatus', |
||
201 | new MultiStatus($responses) |
||
202 | ); |
||
203 | |||
204 | $this->server->httpResponse->setStatus(207); |
||
205 | $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); |
||
206 | $this->server->httpResponse->setBody($xml); |
||
207 | |||
208 | return false; |
||
209 | } |
||
210 | |||
211 | /** |
||
212 | * Creates a new comment |
||
213 | * |
||
214 | * @param string $objectType e.g. "files" |
||
215 | * @param string $objectId e.g. the file id |
||
216 | * @param string $data JSON encoded string containing the properties of the tag to create |
||
217 | * @param string $contentType content type of the data |
||
218 | * @return IComment newly created comment |
||
219 | * |
||
220 | * @throws BadRequest if a field was missing |
||
221 | * @throws UnsupportedMediaType if the content type is not supported |
||
222 | */ |
||
223 | private function createComment($objectType, $objectId, $data, $contentType = 'application/json') { |
||
224 | View Code Duplication | if (\explode(';', $contentType)[0] === 'application/json') { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
225 | $data = \json_decode($data, true); |
||
226 | } else { |
||
227 | throw new UnsupportedMediaType(); |
||
228 | } |
||
229 | |||
230 | $actorType = $data['actorType']; |
||
231 | $actorId = null; |
||
232 | if ($actorType === 'users') { |
||
233 | $user = $this->userSession->getUser(); |
||
234 | if ($user !== null) { |
||
235 | $actorId = $user->getUID(); |
||
236 | } |
||
237 | } |
||
238 | if ($actorId === null) { |
||
239 | throw new BadRequest('Invalid actor "' . $actorType .'"'); |
||
240 | } |
||
241 | |||
242 | try { |
||
243 | $comment = $this->commentsManager->create($actorType, $actorId, $objectType, $objectId); |
||
244 | $comment->setMessage($data['message']); |
||
245 | $comment->setVerb($data['verb']); |
||
246 | $this->commentsManager->save($comment); |
||
247 | return $comment; |
||
248 | } catch (\InvalidArgumentException $e) { |
||
249 | throw new BadRequest('Invalid input values', 0, $e); |
||
250 | } catch (\OCP\Comments\MessageTooLongException $e) { |
||
251 | $msg = 'Message exceeds allowed character limit of '; |
||
252 | throw new BadRequest($msg . \OCP\Comments\IComment::MAX_MESSAGE_LENGTH, 0, $e); |
||
253 | } |
||
254 | } |
||
255 | } |
||
256 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: