| 171 | // ── PROPFIND ───────────────────────────────────────────────────────────────── |
| 172 | |
| 173 | void WebDAVHandler::handlePropfind(WebServer& s) { |
| 174 | String path = getRequestPath(s); |
| 175 | int depth = getDepth(s); |
| 176 | |
| 177 | LOG_DBG("DAV", "PROPFIND %s depth=%d", path.c_str(), depth); |
| 178 | |
| 179 | // Check if path exists |
| 180 | if (!Storage.exists(path.c_str()) && path != "/") { |
| 181 | s.send(404, "text/plain", "Not Found"); |
| 182 | return; |
| 183 | } |
| 184 | |
| 185 | HalFile root = Storage.open(path.c_str()); |
| 186 | if (!root) { |
| 187 | if (path == "/") { |
| 188 | // Root should always work — send minimal response |
| 189 | s.setContentLength(CONTENT_LENGTH_UNKNOWN); |
| 190 | s.send(207, "application/xml; charset=\"utf-8\"", ""); |
| 191 | s.sendContent( |
| 192 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| 193 | "<D:multistatus xmlns:D=\"DAV:\">\n"); |
| 194 | sendPropEntry(s, "/", true, 0, FIXED_DATE); |
| 195 | s.sendContent("</D:multistatus>\n"); |
| 196 | s.sendContent(""); |
| 197 | return; |
| 198 | } |
| 199 | s.send(500, "text/plain", "Failed to open"); |
| 200 | return; |
| 201 | } |
| 202 | |
| 203 | bool isDir = root.isDirectory(); |
| 204 | |
| 205 | s.setContentLength(CONTENT_LENGTH_UNKNOWN); |
| 206 | s.send(207, "application/xml; charset=\"utf-8\"", ""); |
| 207 | s.sendContent( |
| 208 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| 209 | "<D:multistatus xmlns:D=\"DAV:\">\n"); |
| 210 | |
| 211 | // Entry for the resource itself |
| 212 | if (isDir) { |
| 213 | sendPropEntry(s, path, true, 0, FIXED_DATE); |
| 214 | } else { |
| 215 | sendPropEntry(s, path, false, root.size(), FIXED_DATE); |
| 216 | root.close(); |
| 217 | s.sendContent("</D:multistatus>\n"); |
| 218 | s.sendContent(""); |
| 219 | return; |
| 220 | } |
| 221 | |
| 222 | // If depth > 0 and it's a directory, list children |
| 223 | if (depth > 0) { |
| 224 | HalFile file = root.openNextFile(); |
| 225 | char name[500]; |
| 226 | while (file) { |
| 227 | file.getName(name, sizeof(name)); |
| 228 | String fileName(name); |
| 229 | |
| 230 | // Skip hidden/protected items |
nothing calls this directly
no test coverage detected