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);
586 bool compositionIsExportedAppOrPlugin =
false;
588 if (strcmp(currentWorkingDir,
"/") == 0
589 || strstr(currentWorkingDir,
"/Library/Containers/"))
596 char rawExecutablePath[PATH_MAX+1];
597 uint32_t size =
sizeof(rawExecutablePath);
598 _NSGetExecutablePath(rawExecutablePath, &size);
600 char cleanedExecutablePath[PATH_MAX+1];
601 realpath(rawExecutablePath, cleanedExecutablePath);
604 size_t pathSize = PATH_MAX + 1;
605 char executableDir[pathSize];
606 strlcpy(executableDir, dirname(cleanedExecutablePath), pathSize);
608 const char *resourcesPathFromExecutable =
"/../Resources";
609 pathSize = strlen(executableDir) + strlen(resourcesPathFromExecutable) + 1;
610 char rawResourcesPath[pathSize];
611 strlcpy(rawResourcesPath, executableDir, pathSize);
612 strlcat(rawResourcesPath, resourcesPathFromExecutable, pathSize);
614 char cleanedResourcesPath[PATH_MAX+1];
615 realpath(rawResourcesPath, cleanedResourcesPath);
619 if (access(cleanedResourcesPath, 0) == 0)
621 compositionIsExportedAppOrPlugin =
true;
625 char *homeDir = getenv(
"HOME");
626 const char *desktop =
"/Desktop/";
627 size_t mallocSize = strlen(homeDir) + strlen(desktop) + strlen(trimmedUrl) + 1;
628 absolutePath = (
char *)malloc(mallocSize);
629 strlcpy(absolutePath, homeDir, mallocSize);
630 strlcat(absolutePath, desktop, mallocSize);
631 strlcat(absolutePath, trimmedUrl, mallocSize);
635 size_t mallocSize = strlen(cleanedResourcesPath) + strlen(
"/") + strlen(trimmedUrl) + 1;
636 absolutePath = (
char *)malloc(mallocSize);
637 strlcpy(absolutePath, cleanedResourcesPath, mallocSize);
638 strlcat(absolutePath,
"/", mallocSize);
639 strlcat(absolutePath, trimmedUrl, mallocSize);
645 if (!compositionIsExportedAppOrPlugin)
647 size_t mallocSize = strlen(currentWorkingDir) + strlen(
"/") + strlen(trimmedUrl) + 1;
648 absolutePath = (
char *)malloc(mallocSize);
649 strlcpy(absolutePath, currentWorkingDir, mallocSize);
650 strlcat(absolutePath,
"/", mallocSize);
651 strlcat(absolutePath, trimmedUrl, mallocSize);
654 char *realPath = realpath(absolutePath, NULL);
664 resolvedUrl = (
char *)malloc(mallocSize);
666 strlcat(resolvedUrl, escapedPath, mallocSize);
672 size_t lastIndex = strlen(resolvedUrl) - 1;
673 if (resolvedUrl[lastIndex] ==
'/')
674 resolvedUrl[lastIndex] = 0;
692 unsigned long inLength = strlen(url);
693 char *unescapedUrl = (
char *)malloc(inLength + 1);
694 unsigned long outIndex = 0;
695 for (
unsigned long inIndex = 0; inIndex < inLength; ++inIndex, ++outIndex)
697 char c = url[inIndex];
700 if (inIndex + 2 >= inLength)
702 char highNibbleASCII = url[++inIndex];
703 char lowNibbleASCII = url[++inIndex];
707 unescapedUrl[outIndex] = c;
709 unescapedUrl[outIndex] = 0;
713 return unescapedUrlVT;
731 if (strncmp(url + fileSchemeLength,
"//", 2) == 0)
732 fileSchemeLength += 2;
735 unsigned long inLength = strlen(url);
737 char *unescapedUrl = (
char *)malloc(inLength*3 + 1);
738 unsigned long outIndex = 0;
739 for (
unsigned long inIndex = fileSchemeLength; inIndex < inLength; ++inIndex, ++outIndex)
741 char c = url[inIndex];
744 char highNibbleASCII = url[++inIndex];
745 char lowNibbleASCII = url[++inIndex];
749 unescapedUrl[outIndex] = c;
755 if (unescapedUrl[outIndex] ==
':')
757 unescapedUrl[outIndex++] = 0xea;
758 unescapedUrl[outIndex++] = 0x9e;
759 unescapedUrl[outIndex] = 0x89;
762 unescapedUrl[outIndex] = 0;
767 return unescapedUrlVT;
792 CFStringRef urlCFS = CFStringCreateWithCString(NULL, url, kCFStringEncodingUTF8);
793 CFURLRef cfurl = CFURLCreateWithString(NULL, urlCFS, NULL);
797 VUserLog(
"Error: Couldn't check '%s': Invalid URL.", url);
801 LSItemInfoRecord outItemInfo;
802 OSStatus ret = LSCopyItemInfoForURL(cfurl, kLSRequestAllFlags, &outItemInfo);
807 VUserLog(
"Error: Couldn't check '%s': %s", url, errorString);
811 return outItemInfo.flags & kLSItemInfoIsPackage;
819 char* fileSuffix = strrchr(filename,
'.');
820 char* curExtension = fileSuffix != NULL ? strdup(fileSuffix+1) : NULL;
822 if(curExtension != NULL)
823 for(
char *p = &curExtension[0]; *p; p++) *p = tolower(*p);
826 for (
int i = 0; i < json_object_array_length(validExtensions); ++i)
828 if (curExtension != NULL && strcmp(curExtension, json_object_get_string(json_object_array_get_idx(validExtensions, i))) == 0)
837 const char *chosenExtension = json_object_get_string(json_object_array_get_idx(validExtensions, 0));
838 size_t buf_size = strlen(filename) + strlen(chosenExtension) + 2;
839 char* newfilepath = (
char*)malloc(buf_size *
sizeof(
char));
840 snprintf(newfilepath, buf_size,
"%s.%s", filename, chosenExtension);