Skip to content

Commit 9341fb3

Browse files
Merge pull request livecode#2017 from livecodesebastien/bugfix-14413
[[ Bug 14413 ]] revZip: add UTF-8 understanding of archive filename / archive item names on Windows
2 parents bd88068 + 04e11bc commit 9341fb3

9 files changed

Lines changed: 137 additions & 13 deletions

File tree

docs/notes/bugfix-14413.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# revZipOpenArchive fails in 7.0.1 with Unicode characters

engine/src/externalv0.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ extern MCExecContext *MCECptr;
6363
// IM-2014-03-06: [[ revBrowserCEF ]] Add revision number to v0 external interface
6464
// SN-2014-07-08: [[ UnicodeExternalsV0 ]] Bump revision number after unicode update
6565
// AL-2015-02-06: [[ SB Inclusions ]] Increment revision number of v0 external interface
66-
#define EXTERNAL_INTERFACE_VERSION 3
66+
// SN-2015-03-12: [[ Bug 14413 ]] Increment revision number, for the addition of
67+
// UTF-8 <-> native string functions.
68+
#define EXTERNAL_INTERFACE_VERSION 4
6769

6870
typedef struct _Xternal
6971
{
@@ -1718,6 +1720,50 @@ static char *resolve_symbol_in_module(const char *arg1, const char *arg2,
17181720
return nil;
17191721
}
17201722

1723+
////////////////////////////////////////////////////////////////////////////////
1724+
// V4: UTF-8 <-> Native string conversion
1725+
// arg1 contains the string to convert, for both of the functions.
1726+
static char *convert_from_native_to_utf8(const char *arg1, const char *arg2,
1727+
const char *arg3, int *retval)
1728+
{
1729+
MCAutoStringRef t_input;
1730+
char* t_utf8_string;
1731+
if (arg1 == NULL
1732+
|| !MCStringCreateWithNativeChars((char_t*)arg1, strlen(arg1), &t_input)
1733+
|| !MCStringConvertToUTF8String(*t_input, t_utf8_string))
1734+
{
1735+
*retval = xresFail;
1736+
return nil;
1737+
}
1738+
1739+
*retval = xresSucc;
1740+
// Return a string owned by the engine, to avoid the release issue
1741+
MCExternalAddAllocatedString(MCexternalallocpool, t_utf8_string);
1742+
return t_utf8_string;
1743+
}
1744+
1745+
static char *convert_to_native_from_utf8(const char *arg1, const char *arg2,
1746+
const char *arg3, int *retval)
1747+
{
1748+
MCAutoStringRef t_input;
1749+
char *t_native_string;
1750+
1751+
if (arg1 == NULL
1752+
|| !MCStringCreateWithBytes((byte_t*)arg1, strlen(arg1), kMCStringEncodingUTF8, false, &t_input)
1753+
|| !MCStringConvertToCString(*t_input, t_native_string))
1754+
{
1755+
*retval = xresFail;
1756+
return nil;
1757+
}
1758+
1759+
*retval = xresSucc;
1760+
// Return a string owned by the engine, to avoid the release issue
1761+
MCExternalAddAllocatedString(MCexternalallocpool, t_native_string);
1762+
return t_native_string;
1763+
}
1764+
1765+
////////////////////////////////////////////////////////////////////////////////
1766+
17211767
// IM-2014-03-06: [[ revBrowserCEF ]] Add externals extension to the callback list
17221768
// SN-2014-07-08: [[ UnicodeExternalsV0 ]] Add externals extension to handle UTF8-encoded parameters
17231769
// AL-2015-02-06: [[ SB Inclusions ]] Add new callbacks for resource loading.
@@ -1788,6 +1834,9 @@ XCB MCcbs[] =
17881834
/* V3 */ unload_module,
17891835
/* V3 */ resolve_symbol_in_module,
17901836

1837+
/* V4 */ convert_from_native_to_utf8,
1838+
/* V4 */ convert_to_native_from_utf8,
1839+
17911840
NULL
17921841
};
17931842

libexternal/include/revolution/external.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,12 @@ extern Bool SecurityCanAccessLibrary(const char *p_library);
511511
extern Bool SecurityCanAccessFileUTF8(const char *p_file);
512512
extern Bool SecurityCanAccessHostUTF8(const char *p_host);
513513
extern Bool SecurityCanAccessLibraryUTF8(const char *p_library);
514+
515+
516+
// SN-2015-03-12: [[ Bug 14413 ]] Added UTF-8 <-> native string conversion
517+
// The string returned are owned by the engine, and must not be free'd
518+
extern const char *ConvertCStringFromNativeToUTF8(const char *p_native, int *r_success);
519+
extern const char *ConvertCStringToNativeFromUTF8(const char *p_utf8, int *r_success);
514520

515521
#ifdef __cplusplus
516522
};

libexternal/src/external.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ enum
7474
/* V3 */ OPERATION_LOAD_MODULE,
7575
/* V3 */ OPERATION_UNLOAD_MODULE,
7676
/* V3 */ OPERATION_RESOLVE_SYMBOL_IN_MODULE,
77+
78+
// SN-2015-03-12: [[ Bug 14413 ]] Add new UTF-8 <-> native conversion functions
79+
/* V4 */ OPERATION_CONVERT_FROM_NATIVE_TO_UTF8,
80+
/* V4 */ OPERATION_CONVERT_TO_NATIVE_FROM_UTF8,
7781
};
7882

7983
enum
@@ -905,6 +909,37 @@ void ResolveSymbolInModule(void *p_handle, const char *p_symbol, void **r_resolv
905909
}
906910

907911
////////////////////////////////////////////////////////////////////////////////
912+
// V4: UTF-8 <-> native string conversion
913+
914+
const char *ConvertCStringFromNativeToUTF8(const char *p_native, int *r_success)
915+
{
916+
char *t_result;
917+
918+
if (s_external_interface_version < 4)
919+
{
920+
*r_success = EXTERNAL_FAILURE;
921+
return;
922+
}
923+
924+
t_result = (s_operations[OPERATION_CONVERT_FROM_NATIVE_TO_UTF8])(p_native, NULL, NULL, r_success);
925+
926+
return t_result;
927+
}
928+
929+
const char *ConvertCStringToNativeFromUTF8(const char *p_utf8, int *r_success)
930+
{
931+
char *t_result;
932+
933+
if (s_external_interface_version < 4)
934+
{
935+
*r_success = EXTERNAL_FAILURE;
936+
return;
937+
}
938+
939+
t_result = (s_operations[OPERATION_CONVERT_TO_NATIVE_FROM_UTF8])(p_utf8, NULL, NULL, r_success);
940+
941+
return t_result;
942+
}
908943

909944
#ifdef TARGET_SUBPLATFORM_IPHONE
910945
struct LibExport

libexternal/src/osxsupport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,4 @@ char *os_path_resolve(const char *p_native_path)
236236
free(fullpath);
237237
}
238238
return newname;
239-
}
239+
}

libexternal/src/unxsupport.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ char *string_to_utf8(const char *p_string)
3535
unsigned int v;
3636
v = ((unsigned char *)p_string)[i];
3737

38-
if (v < 128)
38+
if (v < 128)
3939
t_utf8_string[j++] = v;
4040
else
4141
{
42-
t_utf8_string[j++] = 0xC0 | (v >> 5);
43-
t_utf8_string[j++] = 0x80 | (v & 63);
42+
// SN-2015-03-11: [[ Bug 14413 ]] Do the expected shift
43+
t_utf8_string[j++] = (0xC0 | (v >> 6));
44+
t_utf8_string[j++] = (0x80 | (v & 63));
4445
}
45-
}
46+
}
4647

4748
t_utf8_string[j] = '\0';
4849

libexternal/src/w32support.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,4 @@ char *os_path_resolve(const char *p_native_path)
118118
char *cstr = strclone(p_native_path);
119119
cstr = os_path_to_native(cstr);
120120
return cstr;
121-
}
121+
}

revzip/src/revzip.cpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,15 +1267,47 @@ void revZipEnumerateItems(char *p_arguments[], int p_argument_count, char **r_re
12671267
for( int i = 0; i < t_num_files; ++i )
12681268
{
12691269
const char* t_line = NULL;
1270-
t_line = zip_get_name(t_archive, i, 0);
1271-
if( t_line )
1270+
struct zip_stat t_stat;
1271+
1272+
// SN-2015-03-11: [[ Bug 14413 ]] We want to get the bitflags
1273+
// alongside the name: zip_stat_index provides this.
1274+
if (zip_stat_index(t_archive, i, 0, &t_stat) != 0)
12721275
{
1273-
t_str_names += std::string(t_line);
1274-
t_str_names += "\n";
1276+
std::string t_outerr = "ziperr," + std::string((zip_strerror(t_archive)));
1277+
t_result = strdup(t_outerr.c_str());
1278+
t_error = False;
1279+
}
1280+
else
1281+
{
1282+
// SN-2015-03-10: [[ Bug 14413 ]] We convert the string to UTF-8
1283+
// in case it was natively encoded, as revZipEnumerateItems is
1284+
// meant to return a UTF-8 encoded string.
1285+
const char *t_converted_name;
1286+
int t_success;
1287+
1288+
if (t_stat.bitflags & ZIP_UTF8_FLAG)
1289+
{
1290+
t_success = EXTERNAL_SUCCESS;
1291+
t_converted_name = t_stat.name;
1292+
}
1293+
else
1294+
t_converted_name = ConvertCStringFromNativeToUTF8(t_stat.name, &t_success);
1295+
1296+
if (t_success == EXTERNAL_SUCCESS)
1297+
{
1298+
t_str_names += std::string(t_converted_name);
1299+
t_str_names += "\n";
1300+
}
1301+
else
1302+
{
1303+
t_result = strdup("");
1304+
t_error = True;
1305+
break;
1306+
}
12751307
}
12761308
}
12771309

1278-
if( !t_str_names.empty() )
1310+
if( !t_str_names.empty() && t_error == False)
12791311
{
12801312
t_result = strdup(t_str_names.c_str());
12811313
t_error = False;

thirdparty

0 commit comments

Comments
 (0)