ObjFW  Check-in [645ae7ac0a]

Overview
Comment:Correctly handle Unicode when URL encoding
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 645ae7ac0a98dd2633ce9775a3abf8adbc5aceabcfcdeba2cf79310af60f70a5
User & Date: js on 2017-11-05 21:39:29
Other Links: manifest | tags
Context
2017-11-06
00:10
of_string_utf8_encode(): Remove a variable check-in: 455caa7063 user: js tags: trunk
2017-11-05
21:39
Correctly handle Unicode when URL encoding check-in: 645ae7ac0a user: js tags: trunk
19:53
Make -[stringByURLEncoding] take an OFCharacterSet check-in: 2f555742c0 user: js tags: trunk
Changes

Modified src/OFString+URLEncoding.m from [7628140be6] to [ab8d94f5c6].

19
20
21
22
23
24
25

26
27
28
29
30
31
32
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33







+







#include <stdlib.h>
#include <string.h>

#import "OFString+URLEncoding.h"
#import "OFCharacterSet.h"

#import "OFInvalidFormatException.h"
#import "OFInvalidEncodingException.h"
#import "OFOutOfMemoryException.h"

/* Reference for static linking */
int _OFString_URLEncoding_reference;

@implementation OFString (URLEncoding)
- (OFString *)stringByURLEncodingWithAllowedCharacters:
44
45
46
47
48
49
50








51
52
53



54
55
56
57





58
59
60



61
62
63
64
65
66
67
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59



60
61
62
63



64
65
66
67
68
69


70
71
72
73
74
75
76
77
78
79







+
+
+
+
+
+
+
+
-
-
-
+
+
+

-
-
-
+
+
+
+
+

-
-
+
+
+







		of_unichar_t c = characters[i];

		if (characterIsMember(allowedCharacters,
		    @selector(characterIsMember:), c))
			[ret appendCharacters: &c
				       length: 1];
		else {
			char buffer[4];
			size_t bufferLen;

			if ((bufferLen = of_string_utf8_encode(c, buffer)) == 0)
				@throw [OFInvalidEncodingException exception];

			for (size_t j = 0; j < bufferLen; j++) {
				unsigned char byte = buffer[j];
			unsigned char high = c >> 4;
			unsigned char low = c & 0x0F;
			of_unichar_t escaped[3];
				unsigned char high = byte >> 4;
				unsigned char low = byte & 0x0F;
				char escaped[3];

			escaped[0] = '%';
			escaped[1] = (high > 9 ? high - 10 + 'A' : high + '0');
			escaped[2] = (low  > 9 ? low  - 10 + 'A' : low  + '0');
				escaped[0] = '%';
				escaped[1] =
				    (high > 9 ? high - 10 + 'A' : high + '0');
				escaped[2] =
				    (low  > 9 ? low  - 10 + 'A' : low  + '0');

			[ret appendCharacters: escaped
				       length: 3];
				[ret appendUTF8String: escaped
					       length: 3];
			}
		}
	}

	objc_autoreleasePoolPop(pool);

	return ret;
}

Modified tests/OFStringTests.m from [a80b9ca389] to [fb9438be53].

779
780
781
782
783
784
785


786
787

788
789

790
791
792
793


794
795
796
797
798
799
800
779
780
781
782
783
784
785
786
787
788

789


790
791
792


793
794
795
796
797
798
799
800
801







+
+

-
+
-
-
+


-
-
+
+







	    @"73286da882ffddca2f45e005cfa6b44f3fc65bfb26db1d08"
	    @"7ded2f9c279e5addf8be854044bca0cece073fce28eec7d9"])

	TEST(@"-[SHA512Hash]", [[C(@"asdfoobar") SHA512Hash] isEqual:
	    @"0464c427da158b02161bb44a3090bbfc594611ef6a53603640454b56412a9247c"
	    @"3579a329e53a5dc74676b106755e3394f9454a2d42273242615d32f80437d61"])

	OFCharacterSet *cs = [OFCharacterSet
	    characterSetWithCharactersInString: @"abfo'_~$🍏"];
	TEST(@"-[stringByURLEncodingWithAllowedCharacters:]",
	    [[C(@"foo\"ba'_~$]") stringByURLEncodingWithAllowedCharacters:
	    [[C(@"foo\"ba'_~$]🍏🍌") stringByURLEncodingWithAllowedCharacters:
	    [OFCharacterSet URLPathAllowedCharacterSet]]
	    isEqual: @"foo%22ba'_~$%5D"])
	    cs] isEqual: @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"])

	TEST(@"-[stringByURLDecoding]",
	    [[C(@"foo%20bar%22+%24") stringByURLDecoding]
	    isEqual: @"foo bar\"+$"])
	    [[C(@"foo%20bar%22+%24%F0%9F%8D%8C") stringByURLDecoding]
	    isEqual: @"foo bar\"+$🍌"])

	TEST(@"-[insertString:atIndex:]",
	    (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) &&
	    R([s[0] insertString: @"äöü"
			 atIndex: 3]) &&
	    [s[0] isEqual: @"𝄞ööäöüöbä€"])