Skip to content

Commit fb9efd0

Browse files
authored
Merge PR #255, Correctly handle Unicode strings
* Split out string conversion from ZipConstants to ZipStrings * Switch ZipOutputStream to using ZipStrings * Add ZipConstants wrappers for backwards compability * Set IsUnicodeText based upon ZipStrings default code page * Update string transcoding to handle DefaultCodePage not Unicode * Update tests for string coding * Fixes #251
1 parent 796b5be commit fb9efd0

File tree

10 files changed

+409
-197
lines changed

10 files changed

+409
-197
lines changed

src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs

Lines changed: 24 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ public enum GeneralBitFlags
202202
/// <summary>
203203
/// This class contains constants used for Zip format files
204204
/// </summary>
205-
public sealed class ZipConstants
205+
public static class ZipConstants
206206
{
207207
#region Versions
208208
/// <summary>
@@ -421,166 +421,49 @@ public sealed class ZipConstants
421421
public const int ENDSIG = 'P' | ('K' << 8) | (5 << 16) | (6 << 24);
422422
#endregion
423423

424-
/// <remarks>
425-
/// The original Zip specification (https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT) states
426-
/// that file names should only be encoded with IBM Code Page 437 or UTF-8.
427-
/// In practice, most zip apps use OEM or system encoding (typically cp437 on Windows).
428-
/// Let's be good citizens and default to UTF-8 http://utf8everywhere.org/
429-
/// </remarks>
430-
static int defaultCodePage = Encoding.UTF8.CodePage;
431-
432424
/// <summary>
433425
/// Default encoding used for string conversion. 0 gives the default system OEM code page.
434426
/// Using the default code page isnt the full solution neccessarily
435427
/// there are many variable factors, codepage 850 is often a good choice for
436428
/// European users, however be careful about compatability.
437429
/// </summary>
438-
public static int DefaultCodePage {
439-
get {
440-
return defaultCodePage;
441-
}
442-
set {
443-
if ((value < 0) || (value > 65535) ||
444-
(value == 1) || (value == 2) || (value == 3) || (value == 42)) {
445-
throw new ArgumentOutOfRangeException(nameof(value));
446-
}
447-
448-
defaultCodePage = value;
449-
}
430+
[Obsolete("Use ZipStrings instead")]
431+
public static int DefaultCodePage
432+
{
433+
get => ZipStrings.CodePage;
434+
set => ZipStrings.CodePage = value;
450435
}
451436

452-
/// <summary>
453-
/// Convert a portion of a byte array to a string.
454-
/// </summary>
455-
/// <param name="data">
456-
/// Data to convert to string
457-
/// </param>
458-
/// <param name="count">
459-
/// Number of bytes to convert starting from index 0
460-
/// </param>
461-
/// <returns>
462-
/// data[0]..data[count - 1] converted to a string
463-
/// </returns>
437+
/// <summary> Depracated wrapper for <see cref="ZipStrings.ConvertToString(byte[], int)"/></summary>
438+
[Obsolete("Use ZipStrings.ConvertToString instead")]
464439
public static string ConvertToString(byte[] data, int count)
465-
{
466-
if (data == null) {
467-
return string.Empty;
468-
}
469-
470-
return Encoding.GetEncoding(DefaultCodePage).GetString(data, 0, count);
471-
}
440+
=> ZipStrings.ConvertToString(data, count);
472441

473-
/// <summary>
474-
/// Convert a byte array to string
475-
/// </summary>
476-
/// <param name="data">
477-
/// Byte array to convert
478-
/// </param>
479-
/// <returns>
480-
/// <paramref name="data">data</paramref>converted to a string
481-
/// </returns>
442+
/// <summary> Depracated wrapper for <see cref="ZipStrings.ConvertToString(byte[])"/></summary>
443+
[Obsolete("Use ZipStrings.ConvertToString instead")]
482444
public static string ConvertToString(byte[] data)
483-
{
484-
if (data == null) {
485-
return string.Empty;
486-
}
487-
return ConvertToString(data, data.Length);
488-
}
445+
=> ZipStrings.ConvertToString(data);
489446

490-
/// <summary>
491-
/// Convert a byte array to string
492-
/// </summary>
493-
/// <param name="flags">The applicable general purpose bits flags</param>
494-
/// <param name="data">
495-
/// Byte array to convert
496-
/// </param>
497-
/// <param name="count">The number of bytes to convert.</param>
498-
/// <returns>
499-
/// <paramref name="data">data</paramref>converted to a string
500-
/// </returns>
447+
/// <summary> Depracated wrapper for <see cref="ZipStrings.ConvertToStringExt(int, byte[], int)"/></summary>
448+
[Obsolete("Use ZipStrings.ConvertToStringExt instead")]
501449
public static string ConvertToStringExt(int flags, byte[] data, int count)
502-
{
503-
if (data == null) {
504-
return string.Empty;
505-
}
506-
507-
if ((flags & (int)GeneralBitFlags.UnicodeText) != 0) {
508-
return Encoding.UTF8.GetString(data, 0, count);
509-
} else {
510-
return ConvertToString(data, count);
511-
}
512-
}
450+
=> ZipStrings.ConvertToStringExt(flags, data, count);
513451

514-
/// <summary>
515-
/// Convert a byte array to string
516-
/// </summary>
517-
/// <param name="data">
518-
/// Byte array to convert
519-
/// </param>
520-
/// <param name="flags">The applicable general purpose bits flags</param>
521-
/// <returns>
522-
/// <paramref name="data">data</paramref>converted to a string
523-
/// </returns>
452+
/// <summary> Depracated wrapper for <see cref="ZipStrings.ConvertToStringExt(int, byte[])"/></summary>
453+
[Obsolete("Use ZipStrings.ConvertToStringExt instead")]
524454
public static string ConvertToStringExt(int flags, byte[] data)
525-
{
526-
if (data == null) {
527-
return string.Empty;
528-
}
529-
530-
if ((flags & (int)GeneralBitFlags.UnicodeText) != 0) {
531-
return Encoding.UTF8.GetString(data, 0, data.Length);
532-
} else {
533-
return ConvertToString(data, data.Length);
534-
}
535-
}
455+
=> ZipStrings.ConvertToStringExt(flags, data);
536456

537-
/// <summary>
538-
/// Convert a string to a byte array
539-
/// </summary>
540-
/// <param name="str">
541-
/// String to convert to an array
542-
/// </param>
543-
/// <returns>Converted array</returns>
457+
/// <summary> Depracated wrapper for <see cref="ZipStrings.ConvertToArray(string)"/></summary>
458+
[Obsolete("Use ZipStrings.ConvertToArray instead")]
544459
public static byte[] ConvertToArray(string str)
545-
{
546-
if (str == null) {
547-
return new byte[0];
548-
}
460+
=> ZipStrings.ConvertToArray(str);
549461

550-
return Encoding.GetEncoding(DefaultCodePage).GetBytes(str);
551-
}
552-
553-
/// <summary>
554-
/// Convert a string to a byte array
555-
/// </summary>
556-
/// <param name="flags">The applicable <see cref="GeneralBitFlags">general purpose bits flags</see></param>
557-
/// <param name="str">
558-
/// String to convert to an array
559-
/// </param>
560-
/// <returns>Converted array</returns>
462+
/// <summary> Depracated wrapper for <see cref="ZipStrings.ConvertToArray(int, string)"/></summary>
463+
[Obsolete("Use ZipStrings.ConvertToArray instead")]
561464
public static byte[] ConvertToArray(int flags, string str)
562-
{
563-
if (str == null) {
564-
return new byte[0];
565-
}
566-
567-
if ((flags & (int)GeneralBitFlags.UnicodeText) != 0) {
568-
return Encoding.UTF8.GetBytes(str);
569-
} else {
570-
return ConvertToArray(str);
571-
}
572-
}
465+
=> ZipStrings.ConvertToArray(flags, str);
573466

574467

575-
/// <summary>
576-
/// Initialise default instance of <see cref="ZipConstants">ZipConstants</see>
577-
/// </summary>
578-
/// <remarks>
579-
/// Private to prevent instances being created.
580-
/// </remarks>
581-
ZipConstants()
582-
{
583-
// Do nothing
584-
}
585468
}
586469
}

src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ internal ZipEntry(string name, int versionRequiredToExtract, int madeByInfo,
191191
this.versionMadeBy = (ushort)madeByInfo;
192192
this.versionToExtract = (ushort)versionRequiredToExtract;
193193
this.method = method;
194+
195+
IsUnicodeText = ZipStrings.UseUnicode;
194196
}
195197

196198
/// <summary>

src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,27 +59,26 @@ public enum TimeSetting
5959
public ZipEntryFactory()
6060
{
6161
nameTransform_ = new ZipNameTransform();
62+
isUnicodeText_ = ZipStrings.UseUnicode;
6263
}
6364

6465
/// <summary>
6566
/// Initialise a new instance of <see cref="ZipEntryFactory"/> using the specified <see cref="TimeSetting"/>
6667
/// </summary>
6768
/// <param name="timeSetting">The <see cref="TimeSetting">time setting</see> to use when creating <see cref="ZipEntry">Zip entries</see>.</param>
68-
public ZipEntryFactory(TimeSetting timeSetting)
69+
public ZipEntryFactory(TimeSetting timeSetting): this()
6970
{
7071
timeSetting_ = timeSetting;
71-
nameTransform_ = new ZipNameTransform();
7272
}
7373

7474
/// <summary>
7575
/// Initialise a new instance of <see cref="ZipEntryFactory"/> using the specified <see cref="DateTime"/>
7676
/// </summary>
7777
/// <param name="time">The time to set all <see cref="ZipEntry.DateTime"/> values to.</param>
78-
public ZipEntryFactory(DateTime time)
78+
public ZipEntryFactory(DateTime time): this()
7979
{
8080
timeSetting_ = TimeSetting.Fixed;
8181
FixedDateTime = time;
82-
nameTransform_ = new ZipNameTransform();
8382
}
8483

8584
#endregion

src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public bool IsFinished {
9898
public void SetComment(string comment)
9999
{
100100
// TODO: Its not yet clear how to handle unicode comments here.
101-
byte[] commentBytes = ZipConstants.ConvertToArray(comment);
101+
byte[] commentBytes = ZipStrings.ConvertToArray(comment);
102102
if (commentBytes.Length > 0xffff) {
103103
throw new ArgumentOutOfRangeException(nameof(comment));
104104
}
@@ -320,7 +320,7 @@ public void PutNextEntry(ZipEntry entry)
320320
}
321321
}
322322

323-
byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
323+
byte[] name = ZipStrings.ConvertToArray(entry.Flags, entry.Name);
324324

325325
if (name.Length > 0xFFFF) {
326326
throw new ZipException("Entry name too long.");
@@ -669,7 +669,7 @@ public override void Finish()
669669
WriteLeInt((int)entry.Size);
670670
}
671671

672-
byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
672+
byte[] name = ZipStrings.ConvertToArray(entry.Flags, entry.Name);
673673

674674
if (name.Length > 0xffff) {
675675
throw new ZipException("Name too long.");
@@ -705,7 +705,7 @@ public override void Finish()
705705

706706
byte[] entryComment =
707707
(entry.Comment != null) ?
708-
ZipConstants.ConvertToArray(entry.Flags, entry.Comment) :
708+
ZipStrings.ConvertToArray(entry.Flags, entry.Comment) :
709709
new byte[0];
710710

711711
if (entryComment.Length > 0xffff) {

0 commit comments

Comments
 (0)