| 6378 | /* ── cbm_parse_file_uri ──────────────────────────────────────── */ |
| 6379 | |
| 6380 | bool cbm_parse_file_uri(const char *uri, char *out_path, int out_size) { |
| 6381 | if (!uri || !out_path || out_size <= 0) { |
| 6382 | if (out_path && out_size > 0) { |
| 6383 | out_path[0] = '\0'; |
| 6384 | } |
| 6385 | return false; |
| 6386 | } |
| 6387 | |
| 6388 | /* Must start with file:// */ |
| 6389 | if (strncmp(uri, "file://", SLEN("file://")) != 0) { |
| 6390 | out_path[0] = '\0'; |
| 6391 | return false; |
| 6392 | } |
| 6393 | |
| 6394 | const char *path = uri + MCP_URI_PREFIX; |
| 6395 | |
| 6396 | /* On Windows, file:///C:/path → /C:/path. Strip leading / before drive letter. */ |
| 6397 | if (path[0] == '/' && path[SKIP_ONE] && |
| 6398 | ((path[SKIP_ONE] >= 'A' && path[SKIP_ONE] <= 'Z') || |
| 6399 | (path[SKIP_ONE] >= 'a' && path[SKIP_ONE] <= 'z')) && |
| 6400 | path[PAIR_LEN] == ':') { |
| 6401 | path++; /* skip the leading / */ |
| 6402 | } |
| 6403 | |
| 6404 | snprintf(out_path, out_size, "%s", path); |
| 6405 | return true; |
| 6406 | } |