15 #include <mach-o/dyld.h>
17 #include <CoreServices/CoreServices.h>
18 #include "VuoUrlParser.h"
25 "description" :
"Uniform Resource Locator.",
26 "keywords" : [
"link" ],
29 "CoreServices.framework",
44 const char *textString =
"";
45 if (json_object_get_type(js) == json_type_string)
46 textString = json_object_get_string(js);
50 url = strdup(textString);
64 return json_object_new_string(
"");
66 return json_object_new_string(value);
76 char *summary = strdup(t);
91 struct http_parser_url parsedUrl;
92 size_t urlLen = strlen(url);
93 if (http_parser_parse_url(url, urlLen,
false, &parsedUrl))
96 if (strncmp(url,
"data:", 5) == 0)
117 else if (strncmp(url,
"file:/", 6) == 0 && urlLen > 6 && url[6] !=
'/')
119 char *urlWithEmptyAuthority = malloc(urlLen + 2 + 1);
120 strcpy(urlWithEmptyAuthority,
"file://");
121 strcat(urlWithEmptyAuthority, url + 5);
122 if (http_parser_parse_url(urlWithEmptyAuthority, urlLen + 2,
false, &parsedUrl))
124 free(urlWithEmptyAuthority);
127 free(urlWithEmptyAuthority);
136 if (parsedUrl.field_set & (1 << UF_SCHEMA))
144 if (parsedUrl.field_set & (1 << UF_USERINFO))
152 if (parsedUrl.field_set & (1 << UF_HOST))
160 if (parsedUrl.field_set & (1 << UF_PORT))
162 *port = parsedUrl.port;
167 if (strcmp(*scheme,
"http") == 0)
169 else if (strcmp(*scheme,
"https") == 0)
176 if (parsedUrl.field_set & (1 << UF_PATH))
184 if (parsedUrl.field_set & (1 << UF_QUERY))
192 if (parsedUrl.field_set & (1 << UF_FRAGMENT))
193 *fragment =
VuoText_makeWithMaxLength(url + parsedUrl.field_data[UF_FRAGMENT].off, parsedUrl.field_data[UF_FRAGMENT].len);
223 if (separatorIndex < length)
226 fileAndExtension = NULL;
273 const char *urlWithSchemePattern =
"^[a-zA-Z][a-zA-Z0-9+-\\.]+:";
274 regex_t urlWithSchemeRegExp;
276 regmatch_t pmatch[0];
278 regcomp(&urlWithSchemeRegExp, urlWithSchemePattern, REG_EXTENDED);
279 bool matchFound = !regexec(&urlWithSchemeRegExp, url, nmatch, pmatch, 0);
280 regfree(&urlWithSchemeRegExp);
290 return ((strlen(url) >= 1) && (url[0] ==
'/'));
298 return ((strlen(url) >= 1) && (url[0] ==
'~'));
317 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
318 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
319 '"',
'$',
'&',
'+',
',',
':',
';',
'=',
'?',
'@',
'#',
' ',
330 unsigned long inLength = strlen(path);
331 unsigned long escapedLength = 0;
332 for (
unsigned long i = 0; i < inLength; ++i)
345 char *escapedUrl = (
char *)malloc(escapedLength + 1);
346 unsigned long outIndex = 0;
347 const char *hexCharSet =
"0123456789ABCDEF";
348 for (
unsigned long inIndex = 0; inIndex < inLength; ++inIndex)
350 unsigned char c = path[inIndex];
351 bool foundEscape =
false;
355 escapedUrl[outIndex++] =
'%';
356 escapedUrl[outIndex++] = hexCharSet[c >> 4];
357 escapedUrl[outIndex++] = hexCharSet[c & 0x0f];
365 if (inIndex+2 < inLength)
366 if (c == 0xea && (
unsigned char)path[inIndex+1] == 0x9e && (
unsigned char)path[inIndex+2] == 0x89)
368 escapedUrl[outIndex++] =
'%';
369 escapedUrl[outIndex++] = hexCharSet[
':' >> 4];
370 escapedUrl[outIndex++] = hexCharSet[
':' & 0x0f];
376 escapedUrl[outIndex++] = c;
378 escapedUrl[outIndex] = 0;
392 unsigned long inLength = strlen(url);
393 unsigned long escapedLength = 0;
394 for (
unsigned long i = 0; i < inLength; ++i)
396 if ((
unsigned char)url[i] > 0x7f)
402 char *escapedUrl = (
char *)malloc(escapedLength + 1);
403 unsigned long outIndex = 0;
404 const char *hexCharSet =
"0123456789ABCDEF";
405 for (
unsigned long inIndex = 0; inIndex < inLength; ++inIndex)
407 unsigned char c = url[inIndex];
410 escapedUrl[outIndex++] =
'%';
411 escapedUrl[outIndex++] = hexCharSet[c >> 4];
412 escapedUrl[outIndex++] = hexCharSet[c & 0x0f];
415 escapedUrl[outIndex++] = c;
417 escapedUrl[outIndex] = 0;
457 VuoText u = url + fileSchemeLength;
458 if (strncmp(u,
"//", 2) == 0)
474 size_t urlLen = strlen(trimmedUrl);
475 size_t spaceCount = 0;
476 for (
size_t i = 0; i < urlLen; ++i)
477 if (trimmedUrl[i] ==
' ')
481 resolvedUrl = (
char *)malloc(strlen(trimmedUrl) + spaceCount*2);
483 for (
size_t i = 0; i < urlLen; ++i)
484 if (trimmedUrl[i] ==
' ')
486 resolvedUrl[p++] =
'%';
487 resolvedUrl[p++] =
'2';
488 resolvedUrl[p++] =
'0';
491 resolvedUrl[p++] = trimmedUrl[i];
495 resolvedUrl = strdup(trimmedUrl);
501 char *filePath = (
char *)trimmedUrl;
508 if (access(filePath, 0) != 0)
510 char userTempDir[PATH_MAX];
511 size_t userTempDirLen;
512 if ((userTempDirLen = confstr(_CS_DARWIN_USER_TEMP_DIR, userTempDir, PATH_MAX)) > 0)
514 size_t filePathLen = strlen(filePath);
515 size_t mallocSize = userTempDirLen + filePathLen + 1;
516 char *privateFilePath = (
char *)malloc(mallocSize);
517 strlcpy(privateFilePath, userTempDir, mallocSize);
518 strlcat(privateFilePath, filePath + 4, mallocSize);
519 filePath = privateFilePath;
524 char *realPath = realpath(filePath, NULL);
530 if (filePath != trimmedUrl)
534 resolvedUrl = (
char *)malloc(mallocSize);
536 strlcat(resolvedUrl, escapedPath, mallocSize);
547 char *homeDir = getenv(
"HOME");
548 VuoText paths[2] = { homeDir, trimmedUrl+1 };
554 char *realPath = realpath(absolutePath, NULL);
563 resolvedUrl = (
char *)malloc(mallocSize);
565 strlcat(resolvedUrl, escapedPath, mallocSize);
573 resolvedUrl = (
char *)malloc(mallocSize);
575 strlcat(resolvedUrl, trimmedUrl, mallocSize);
583 bool compositionIsExportedApp =
false;
589 if (!strcmp(currentWorkingDir,
"/"))
592 char rawExecutablePath[PATH_MAX+1];
593 uint32_t size =
sizeof(rawExecutablePath);
594 _NSGetExecutablePath(rawExecutablePath, &size);
596 char cleanedExecutablePath[PATH_MAX+1];
597 realpath(rawExecutablePath, cleanedExecutablePath);
600 size_t pathSize = PATH_MAX + 1;
601 char executableDir[pathSize];
602 strlcpy(executableDir, dirname(cleanedExecutablePath), pathSize);
604 const char *resourcesPathFromExecutable =
"/../Resources";
605 pathSize = strlen(executableDir) + strlen(resourcesPathFromExecutable) + 1;
606 char rawResourcesPath[pathSize];
607 strlcpy(rawResourcesPath, executableDir, pathSize);
608 strlcat(rawResourcesPath, resourcesPathFromExecutable, pathSize);
610 char cleanedResourcesPath[PATH_MAX+1];
611 realpath(rawResourcesPath, cleanedResourcesPath);
615 if (access(cleanedResourcesPath, 0) == 0)
617 compositionIsExportedApp =
true;
621 char *homeDir = getenv(
"HOME");
622 const char *desktop =
"/Desktop/";
623 size_t mallocSize = strlen(homeDir) + strlen(desktop) + strlen(trimmedUrl) + 1;
624 absolutePath = (
char *)malloc(mallocSize);
625 strlcpy(absolutePath, homeDir, mallocSize);
626 strlcat(absolutePath, desktop, mallocSize);
627 strlcat(absolutePath, trimmedUrl, mallocSize);
631 size_t mallocSize = strlen(cleanedResourcesPath) + strlen(
"/") + strlen(trimmedUrl) + 1;
632 absolutePath = (
char *)malloc(mallocSize);
633 strlcpy(absolutePath, cleanedResourcesPath, mallocSize);
634 strlcat(absolutePath,
"/", mallocSize);
635 strlcat(absolutePath, trimmedUrl, mallocSize);
641 if (!compositionIsExportedApp)
643 size_t mallocSize = strlen(currentWorkingDir) + strlen(
"/") + strlen(trimmedUrl) + 1;
644 absolutePath = (
char *)malloc(mallocSize);
645 strlcpy(absolutePath, currentWorkingDir, mallocSize);
646 strlcat(absolutePath,
"/", mallocSize);
647 strlcat(absolutePath, trimmedUrl, mallocSize);
650 char *realPath = realpath(absolutePath, NULL);
660 resolvedUrl = (
char *)malloc(mallocSize);
662 strlcat(resolvedUrl, escapedPath, mallocSize);
668 size_t lastIndex = strlen(resolvedUrl) - 1;
669 if (resolvedUrl[lastIndex] ==
'/')
670 resolvedUrl[lastIndex] = 0;
688 unsigned long inLength = strlen(url);
689 char *unescapedUrl = (
char *)malloc(inLength + 1);
690 unsigned long outIndex = 0;
691 for (
unsigned long inIndex = 0; inIndex < inLength; ++inIndex, ++outIndex)
693 char c = url[inIndex];
696 if (inIndex + 2 >= inLength)
698 char highNibbleASCII = url[++inIndex];
699 char lowNibbleASCII = url[++inIndex];
703 unescapedUrl[outIndex] = c;
705 unescapedUrl[outIndex] = 0;
709 return unescapedUrlVT;
727 if (strncmp(url + fileSchemeLength,
"//", 2) == 0)
728 fileSchemeLength += 2;
731 unsigned long inLength = strlen(url);
733 char *unescapedUrl = (
char *)malloc(inLength*3 + 1);
734 unsigned long outIndex = 0;
735 for (
unsigned long inIndex = fileSchemeLength; inIndex < inLength; ++inIndex, ++outIndex)
737 char c = url[inIndex];
740 char highNibbleASCII = url[++inIndex];
741 char lowNibbleASCII = url[++inIndex];
745 unescapedUrl[outIndex] = c;
751 if (unescapedUrl[outIndex] ==
':')
753 unescapedUrl[outIndex++] = 0xea;
754 unescapedUrl[outIndex++] = 0x9e;
755 unescapedUrl[outIndex] = 0x89;
758 unescapedUrl[outIndex] = 0;
763 return unescapedUrlVT;
788 CFStringRef urlCFS = CFStringCreateWithCString(NULL, url, kCFStringEncodingUTF8);
789 CFURLRef cfurl = CFURLCreateWithString(NULL, urlCFS, NULL);
793 VUserLog(
"Error: Couldn't check '%s': Invalid URL.", url);
797 LSItemInfoRecord outItemInfo;
798 OSStatus ret = LSCopyItemInfoForURL(cfurl, kLSRequestAllFlags, &outItemInfo);
803 VUserLog(
"Error: Couldn't check '%s': %s", url, errorString);
807 return outItemInfo.flags & kLSItemInfoIsPackage;
815 char* fileSuffix = strrchr(filename,
'.');
816 char* curExtension = fileSuffix != NULL ? strdup(fileSuffix+1) : NULL;
818 if(curExtension != NULL)
819 for(
char *p = &curExtension[0]; *p; p++) *p = tolower(*p);
822 for (
int i = 0; i < json_object_array_length(validExtensions); ++i)
824 if (curExtension != NULL && strcmp(curExtension, json_object_get_string(json_object_array_get_idx(validExtensions, i))) == 0)
833 const char *chosenExtension = json_object_get_string(json_object_array_get_idx(validExtensions, 0));
834 size_t buf_size = strlen(filename) + strlen(chosenExtension) + 2;
835 char* newfilepath = (
char*)malloc(buf_size *
sizeof(
char));
836 snprintf(newfilepath, buf_size,
"%s.%s", filename, chosenExtension);