diff options
-rw-r--r-- | src/include/gnunet_strings_lib.h | 58 | ||||
-rw-r--r-- | src/util/strings.c | 183 |
2 files changed, 241 insertions, 0 deletions
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h index 4fb007707..385b6c042 100644 --- a/src/include/gnunet_strings_lib.h +++ b/src/include/gnunet_strings_lib.h | |||
@@ -256,6 +256,64 @@ GNUNET_STRINGS_string_to_data (const char *enc, size_t enclen, | |||
256 | } | 256 | } |
257 | #endif | 257 | #endif |
258 | 258 | ||
259 | enum GNUNET_STRINGS_FilenameCheck | ||
260 | { | ||
261 | GNUNET_STRINGS_CHECK_EXISTS = 0x00000001, | ||
262 | GNUNET_STRINGS_CHECK_IS_DIRECTORY = 0x00000002, | ||
263 | GNUNET_STRINGS_CHECK_IS_LINK = 0x00000004, | ||
264 | GNUNET_STRINGS_CHECK_IS_ABSOLUTE = 0x00000008 | ||
265 | }; | ||
266 | |||
267 | /** | ||
268 | * Parse a path that might be an URI. | ||
269 | * | ||
270 | * @param path path to parse. Must be NULL-terminated. | ||
271 | * @param scheme_part a pointer to 'char *' where a pointer to a string that | ||
272 | * represents the URI scheme will be stored. Can be NULL. The string is | ||
273 | * allocated by the function, and should be freed by GNUNET_free() when | ||
274 | * it is no longer needed. | ||
275 | * @param path_part a pointer to 'const char *' where a pointer to the path | ||
276 | * part of the URI will be stored. Can be NULL. Points to the same block | ||
277 | * of memory as 'path', and thus must not be freed. Might point to '\0', | ||
278 | * if path part is zero-length. | ||
279 | * @return GNUNET_YES if it's an URI, GNUNET_NO otherwise. If 'path' is not | ||
280 | * an URI, '* scheme_part' and '*path_part' will remain unchanged | ||
281 | * (if they weren't NULL). | ||
282 | */ | ||
283 | int | ||
284 | GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part, | ||
285 | const char **path_part); | ||
286 | |||
287 | /** | ||
288 | * Check whether @filename is absolute or not, and if it's an URI | ||
289 | * | ||
290 | * @param filename filename to check | ||
291 | * @param can_be_uri GNUNET_YES to check for being URI, GNUNET_NO - to | ||
292 | * assume it's not URI | ||
293 | * @param r_is_uri a pointer to an int that is set to GNUNET_YES if @filename | ||
294 | * is URI and to GNUNET_NO otherwise. Can be NULL. If @can_be_uri is | ||
295 | * not GNUNET_YES, *r_is_uri is set to GNUNET_NO. | ||
296 | * @param r_uri a pointer to a char * that is set to a pointer to URI scheme. | ||
297 | * The string is allocated by the function, and should be freed with | ||
298 | * GNUNET_free (). Can be NULL. | ||
299 | * @return GNUNET_YES if @filaneme is absolute, GNUNET_NO otherwise. | ||
300 | */ | ||
301 | int | ||
302 | GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri, | ||
303 | int *r_is_uri, char **r_uri_scheme); | ||
304 | |||
305 | /** | ||
306 | * Perform @checks on @filename | ||
307 | * | ||
308 | * @param filename file to check | ||
309 | * @param checks checks to perform | ||
310 | * @return GNUNET_YES if all @checks pass, GNUNET_NO if at least one of them | ||
311 | * fails, GNUNET_SYSERR when a check can't be performed | ||
312 | */ | ||
313 | int | ||
314 | GNUNET_STRINGS_check_filename (const char *filename, | ||
315 | enum GNUNET_STRINGS_FilenameCheck checks); | ||
316 | |||
259 | 317 | ||
260 | /* ifndef GNUNET_UTIL_STRING_H */ | 318 | /* ifndef GNUNET_UTIL_STRING_H */ |
261 | #endif | 319 | #endif |
diff --git a/src/util/strings.c b/src/util/strings.c index 2b8b955c8..abc763b88 100644 --- a/src/util/strings.c +++ b/src/util/strings.c | |||
@@ -766,5 +766,188 @@ GNUNET_STRINGS_string_to_data (const char *enc, size_t enclen, | |||
766 | } | 766 | } |
767 | 767 | ||
768 | 768 | ||
769 | /** | ||
770 | * Parse a path that might be an URI. | ||
771 | * | ||
772 | * @param path path to parse. Must be NULL-terminated. | ||
773 | * @param scheme_part a pointer to 'char *' where a pointer to a string that | ||
774 | * represents the URI scheme will be stored. Can be NULL. The string is | ||
775 | * allocated by the function, and should be freed by GNUNET_free() when | ||
776 | * it is no longer needed. | ||
777 | * @param path_part a pointer to 'const char *' where a pointer to the path | ||
778 | * part of the URI will be stored. Can be NULL. Points to the same block | ||
779 | * of memory as 'path', and thus must not be freed. Might point to '\0', | ||
780 | * if path part is zero-length. | ||
781 | * @return GNUNET_YES if it's an URI, GNUNET_NO otherwise. If 'path' is not | ||
782 | * an URI, '* scheme_part' and '*path_part' will remain unchanged | ||
783 | * (if they weren't NULL). | ||
784 | */ | ||
785 | int | ||
786 | GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part, | ||
787 | const char **path_part) | ||
788 | { | ||
789 | size_t len; | ||
790 | int i, end; | ||
791 | int pp_state = 0; | ||
792 | const char *post_scheme_part = NULL; | ||
793 | len = strlen (path); | ||
794 | for (end = 0, i = 0; !end && i < len; i++) | ||
795 | { | ||
796 | switch (pp_state) | ||
797 | { | ||
798 | case 0: | ||
799 | if (path[i] == ':' && i > 0) | ||
800 | { | ||
801 | pp_state += 1; | ||
802 | continue; | ||
803 | } | ||
804 | if (!((path[i] >= 'A' && path[i] <= 'Z') || (path[i] >= 'a' && path[i] <= 'z') | ||
805 | || (path[i] >= '0' && path[i] <= '9') || path[i] == '+' || path[i] == '-' | ||
806 | || (path[i] == '.'))) | ||
807 | end = 1; | ||
808 | break; | ||
809 | case 1: | ||
810 | case 2: | ||
811 | if (path[i] == '/') | ||
812 | { | ||
813 | pp_state += 1; | ||
814 | continue; | ||
815 | } | ||
816 | end = 1; | ||
817 | break; | ||
818 | case 3: | ||
819 | post_scheme_part = &path[i]; | ||
820 | end = 1; | ||
821 | break; | ||
822 | default: | ||
823 | end = 1; | ||
824 | } | ||
825 | } | ||
826 | if (post_scheme_part == NULL) | ||
827 | return GNUNET_NO; | ||
828 | if (scheme_part) | ||
829 | { | ||
830 | *scheme_part = GNUNET_malloc (post_scheme_part - path + 1); | ||
831 | memcpy (*scheme_part, path, post_scheme_part - path); | ||
832 | (*scheme_part)[post_scheme_part - path] = '\0'; | ||
833 | } | ||
834 | if (path_part) | ||
835 | *path_part = post_scheme_part; | ||
836 | return GNUNET_YES; | ||
837 | } | ||
838 | |||
839 | |||
840 | /** | ||
841 | * Check whether @filename is absolute or not, and if it's an URI | ||
842 | * | ||
843 | * @param filename filename to check | ||
844 | * @param can_be_uri GNUNET_YES to check for being URI, GNUNET_NO - to | ||
845 | * assume it's not URI | ||
846 | * @param r_is_uri a pointer to an int that is set to GNUNET_YES if @filename | ||
847 | * is URI and to GNUNET_NO otherwise. Can be NULL. If @can_be_uri is | ||
848 | * not GNUNET_YES, *r_is_uri is set to GNUNET_NO. | ||
849 | * @param r_uri a pointer to a char * that is set to a pointer to URI scheme. | ||
850 | * The string is allocated by the function, and should be freed with | ||
851 | * GNUNET_free (). Can be NULL. | ||
852 | * @return GNUNET_YES if @filaneme is absolute, GNUNET_NO otherwise. | ||
853 | */ | ||
854 | int | ||
855 | GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri, | ||
856 | int *r_is_uri, char **r_uri_scheme) | ||
857 | { | ||
858 | #if WINDOWS | ||
859 | size_t len; | ||
860 | #endif | ||
861 | const char *post_scheme_path; | ||
862 | int is_uri; | ||
863 | char * uri; | ||
864 | /* consider POSIX paths to be absolute too, even on W32, | ||
865 | * as plibc expansion will fix them for us. | ||
866 | */ | ||
867 | if (filename[0] == '/') | ||
868 | return GNUNET_YES; | ||
869 | if (can_be_uri) | ||
870 | { | ||
871 | is_uri = GNUNET_STRINGS_parse_uri (filename, &uri, &post_scheme_path); | ||
872 | if (r_is_uri) | ||
873 | *r_is_uri = is_uri; | ||
874 | if (is_uri) | ||
875 | { | ||
876 | if (r_uri_scheme) | ||
877 | *r_uri_scheme = uri; | ||
878 | else | ||
879 | GNUNET_free_non_null (uri); | ||
880 | #if WINDOWS | ||
881 | len = strlen(post_scheme_path); | ||
882 | /* Special check for file:///c:/blah | ||
883 | * We want to parse 'c:/', not '/c:/' | ||
884 | */ | ||
885 | if (post_scheme_path[0] == '/' && len >= 3 && post_scheme_path[2] == ':') | ||
886 | post_scheme_path = &post_scheme_path[1]; | ||
887 | #endif | ||
888 | return GNUNET_STRINGS_path_is_absolute (post_scheme_path, GNUNET_NO, NULL, NULL); | ||
889 | } | ||
890 | } | ||
891 | else | ||
892 | { | ||
893 | is_uri = GNUNET_NO; | ||
894 | if (r_is_uri) | ||
895 | *r_is_uri = GNUNET_NO; | ||
896 | } | ||
897 | #if WINDOWS | ||
898 | len = strlen (filename); | ||
899 | if (len >= 3 && | ||
900 | ((filename[0] >= 'A' && filename[0] <= 'Z') | ||
901 | || (filename[0] >= 'a' && filename[0] <= 'z')) | ||
902 | && filename[1] == ':' && (filename[2] == '/' || filename[2] == '\\')) | ||
903 | return GNUNET_YES; | ||
904 | #endif | ||
905 | return GNUNET_NO; | ||
906 | } | ||
907 | |||
908 | #if MINGW | ||
909 | #define _IFMT 0170000 /* type of file */ | ||
910 | #define _IFLNK 0120000 /* symbolic link */ | ||
911 | #define S_ISLNK(m) (((m)&_IFMT) == _IFLNK) | ||
912 | #endif | ||
913 | |||
914 | /** | ||
915 | * Perform @checks on @filename | ||
916 | * | ||
917 | * @param filename file to check | ||
918 | * @param checks checks to perform | ||
919 | * @return GNUNET_YES if all @checks pass, GNUNET_NO if at least one of them | ||
920 | * fails, GNUNET_SYSERR when a check can't be performed | ||
921 | */ | ||
922 | int | ||
923 | GNUNET_STRINGS_check_filename (const char *filename, | ||
924 | enum GNUNET_STRINGS_FilenameCheck checks) | ||
925 | { | ||
926 | struct stat st; | ||
927 | if (filename == NULL || filename[0] == '\0') | ||
928 | return GNUNET_SYSERR; | ||
929 | if (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE) | ||
930 | if (!GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL)) | ||
931 | return GNUNET_NO; | ||
932 | if (checks & (GNUNET_STRINGS_CHECK_EXISTS | ||
933 | | GNUNET_STRINGS_CHECK_IS_DIRECTORY | ||
934 | | GNUNET_STRINGS_CHECK_IS_LINK)) | ||
935 | { | ||
936 | if (STAT (filename, &st)) | ||
937 | { | ||
938 | if (checks & GNUNET_STRINGS_CHECK_EXISTS) | ||
939 | return GNUNET_NO; | ||
940 | else | ||
941 | return GNUNET_SYSERR; | ||
942 | } | ||
943 | } | ||
944 | if (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY) | ||
945 | if (!S_ISDIR (st.st_mode)) | ||
946 | return GNUNET_NO; | ||
947 | if (checks & GNUNET_STRINGS_CHECK_IS_LINK) | ||
948 | if (!S_ISLNK (st.st_mode)) | ||
949 | return GNUNET_NO; | ||
950 | return GNUNET_YES; | ||
951 | } | ||
769 | 952 | ||
770 | /* end of strings.c */ | 953 | /* end of strings.c */ |