Skip to content
This repository has been archived by the owner on Sep 21, 2022. It is now read-only.

Commit

Permalink
Merge pull request #80 from modio/v2.3.2-dev
Browse files Browse the repository at this point in the history
V2.3.2
  • Loading branch information
modio-jackson committed Jun 10, 2021
2 parents a7ef09d + b030158 commit 34c56b9
Show file tree
Hide file tree
Showing 22 changed files with 585 additions and 195 deletions.
104 changes: 78 additions & 26 deletions Runtime/API Objects/WebRequestError.cs
Expand Up @@ -72,17 +72,25 @@ public class APIError
public static WebRequestError GenerateFromWebRequest(UnityWebRequest webRequest)
{
UnityEngine.Debug.Assert(webRequest != null);
UnityEngine.Debug.Assert(webRequest.isNetworkError || webRequest.isHttpError);

WebRequestError error = new WebRequestError();
error.webRequest = webRequest;
if(webRequest == null)
{
Debug.LogWarning("[mod.io] WebRequestError.GenerateFromWebRequest(webRequest) parameter was null.");
return WebRequestError.GenerateLocal("An unknown error occurred.");
}
else
{
WebRequestError error = new WebRequestError();

error.timeStamp = ParseDateHeaderAsTimeStamp(webRequest);
error.webRequest = webRequest;

error.ApplyAPIErrorValues();
error.ApplyInterpretedValues();
error.timeStamp = ParseDateHeaderAsTimeStamp(webRequest);

return error;
error.ApplyAPIErrorValues();
error.ApplyInterpretedValues();

return error;
}
}

public static WebRequestError GenerateLocal(string errorMessage)
Expand Down Expand Up @@ -138,34 +146,81 @@ private void ApplyAPIErrorValues()
this.errorMessage = null;
this.fieldValidationMessages = null;

// early out
if(this.webRequest == null)
{
this.errorMessage = "An unknown error occurred. Please try again later.";
return;
}

// null-ref and type-check
if(this.webRequest.downloadHandler != null
&& !(this.webRequest.downloadHandler is DownloadHandlerFile))
{
string requestContent = null;

try
{
// get the request content
string requestContent = this.webRequest.downloadHandler.text;
if(string.IsNullOrEmpty(requestContent)) { return; }

// deserialize into an APIError
WebRequestError.APIWrapper errorWrapper = JsonConvert.DeserializeObject<APIWrapper>(requestContent);
if(errorWrapper == null
|| errorWrapper.error == null)
{
return;
}

// extract values
this.errorReference = errorWrapper.error.errorReference;
this.errorMessage = errorWrapper.error.message;
this.fieldValidationMessages = errorWrapper.error.errors;
requestContent = this.webRequest.downloadHandler.text;
}
catch(System.Exception e)
{
Debug.LogWarning("[mod.io] Error deserializing API Error:\n"
Debug.LogWarning("[mod.io] Error reading webRequest.downloadHandler text body:\n"
+ e.Message);
}

if(!string.IsNullOrEmpty(requestContent))
{
WebRequestError.APIWrapper errorWrapper = null;

// Parse Cloudflare error
if(requestContent.StartsWith(@"<!DOCTYPE html>"))
{
int readIndex = requestContent.IndexOf("what-happened-section");
int messageEnd = -1;

if(readIndex > 0)
{
readIndex = requestContent.IndexOf(@"<p>", readIndex);

if(readIndex > 0)
{
readIndex += 3;
messageEnd = requestContent.IndexOf(@"</p>", readIndex);
}
}

if(messageEnd > 0)
{
this.errorMessage = ("A Cloudflare error has occurred: "
+ requestContent.Substring(readIndex, messageEnd - readIndex));
}
}
else
{
try
{
// deserialize into an APIError
errorWrapper = JsonConvert.DeserializeObject<APIWrapper>(requestContent);
}
catch(System.Exception e)
{
Debug.LogWarning("[mod.io] Eror parsing error object from repsonse:\n"
+ e.Message);

}

if(errorWrapper != null
&& errorWrapper.error != null)
{
// extract values
this.errorReference = errorWrapper.error.errorReference;
this.errorMessage = errorWrapper.error.message;
this.fieldValidationMessages = errorWrapper.error.errors;
}
}
}
}

if(this.errorMessage == null)
Expand Down Expand Up @@ -370,9 +425,6 @@ private void ApplyInterpretedValues()
+ this.webRequest.responseCode + "]");

this.isRequestUnresolvable = true;

Debug.LogWarning("[mod.io] An unhandled error was returned during a web request."
+ "\nPlease report this to jackson@mod.io with the following information");
}
}
break;
Expand Down
18 changes: 5 additions & 13 deletions Runtime/ComplexCallbacks/ModManager_SubmitModOperation.cs
Expand Up @@ -386,23 +386,15 @@ private void SubmitModChanges_Internal_ZipImages()
{
if(success)
{
try
{
using(var zip = new Ionic.Zip.ZipFile())
{
foreach(string imageFilePath in this.addedImageFilePaths)
{
zip.AddFile(imageFilePath);
}
zip.Save(imageArchivePath);
}
bool didZip = CompressionModule.CompressFileCollection(null, this.addedImageFilePaths, imageArchivePath);
if(didZip)
{
DataStorage.ReadFile(imageArchivePath, this.SubmitModChanges_Internal_OnReadImageArchive);
}
catch(Exception e)
else
{
this.SubmissionError_Local("Unable to zip image gallery prior to uploading.\n"
+ Utility.GenerateExceptionDebugString(e));
this.SubmissionError_Local("Unable to zip image gallery prior to uploading.");
}
}
else
Expand Down
10 changes: 10 additions & 0 deletions Runtime/Compression.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions Runtime/Compression/CompressionModule.cs
@@ -0,0 +1,40 @@
using System.Collections.Generic;

namespace ModIO
{
/// <summary>Defines the static interface for the compression operations.</summary>
public static class CompressionModule
{
// ---------[ Constants ]---------
/// <summary>Compression implementation to use.</summary>
public static readonly ICompressionImpl IMPLEMENTATION;

// ---------[ Initialization ]---------
/// <summary>Loads the compression implementation.</summary>
static CompressionModule()
{
CompressionModule.IMPLEMENTATION = new DotNetZipCompressionImpl();
}

// ---------[ Interface ]---------
/// <summary>Extracts the contents of an archive.</summary>
public static bool ExtractAll(string archivePath, string targetDirectory)
{
return CompressionModule.IMPLEMENTATION.ExtractAll(archivePath, targetDirectory);
}

/// <summary>Compresses the contents of a file collection into an output archive.</summary>
public static bool CompressFileCollection(string rootDirectory,
IEnumerable<string> filePathCollection,
string targetFilePath)
{
return CompressionModule.IMPLEMENTATION.CompressFileCollection(rootDirectory, filePathCollection, targetFilePath);
}

/// <summary>Compresses a single file into an output archive.</summary>
public static bool CompressFile(string filePath, string targetFilePath)
{
return CompressionModule.IMPLEMENTATION.CompressFile(filePath, targetFilePath);
}
}
}
13 changes: 13 additions & 0 deletions Runtime/Compression/CompressionModule.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

154 changes: 154 additions & 0 deletions Runtime/Compression/DotNetZipCompressionImpl.cs
@@ -0,0 +1,154 @@
using System.Collections.Generic;

using Exception = System.Exception;
using Debug = UnityEngine.Debug;
using Path = System.IO.Path;

namespace ModIO
{
/// <summary>A wrapper for the DotNetZip library that matches the ICompressionImpl interface.</summary>
public class DotNetZipCompressionImpl : ICompressionImpl
{
// ---------[ Interface ]---------
/// <summary>Extracts the contents of an archive.</summary>
public bool ExtractAll(string archivePath, string targetDirectory)
{
// early outs
if(string.IsNullOrEmpty(archivePath))
{
Debug.LogWarning("[mod.io] Unable to extract archive to target directory."
+ "\narchivePath is NULL or EMPTY.");
return false;
}
if(string.IsNullOrEmpty(targetDirectory))
{
Debug.LogWarning("[mod.io] Unable to extract archive to target directory."
+ "\ntargetDirectory is NULL or EMPTY.");
return false;
}

// Extract
bool success = false;

try
{
using (var zip = Ionic.Zip.ZipFile.Read(archivePath))
{
zip.ExtractAll(targetDirectory);

success = true;
}
}
catch(Exception e)
{
Debug.LogWarning("[mod.io] Unable to extract archive to target directory."
+ "\nArchive: " + archivePath
+ "\nTarget: " + targetDirectory
+ "\n\n"
+ Utility.GenerateExceptionDebugString(e));
}

return success;
}

/// <summary>Compresses the contents of a file collection into a new output archive.</summary>
public bool CompressFileCollection(string rootDirectory,
IEnumerable<string> filePathCollection,
string targetFilePath)
{
// early outs
if(filePathCollection == null)
{
Debug.LogWarning("[mod.io] Unable to compress file collection to archive."
+ "\nfilePathCollection is NULL.");
return false;
}
if(string.IsNullOrEmpty(targetFilePath))
{
Debug.LogWarning("[mod.io] Unable to compress file collection to archive."
+ "\ntargetFilePath is NULL or EMPTY.");
return false;
}

// compress
if(string.IsNullOrEmpty(rootDirectory))
{
rootDirectory = string.Empty;
}

bool success = false;
string lastFilePath = string.Empty;

try
{
using(var zip = new Ionic.Zip.ZipFile())
{
foreach(string filePath in filePathCollection)
{
lastFilePath = filePath;

string relativeFilePath = filePath.Substring(rootDirectory.Length);
string relativeDirectory = Path.GetDirectoryName(relativeFilePath);

zip.AddFile(filePath, relativeDirectory);
}

zip.Save(targetFilePath);

success = true;
}
}
catch(Exception e)
{
Debug.LogWarning("[mod.io] Unable to compress file collection to archive."
+ "\nLast Attempted File: " + lastFilePath
+ "\nOutput: " + targetFilePath
+ "\n\n"
+ Utility.GenerateExceptionDebugString(e));
}

return success;
}

/// <summary>Compresses a single file into a new output archive.</summary>
public bool CompressFile(string filePath, string targetFilePath)
{
// early outs
if(string.IsNullOrEmpty(filePath))
{
Debug.LogWarning("[mod.io] Unable to compress file collection to archive."
+ "\nfilePath is NULL or EMPTY.");
return false;
}
if(string.IsNullOrEmpty(targetFilePath))
{
Debug.LogWarning("[mod.io] Unable to compress file collection to archive."
+ "\ntargetFilePath is NULL or EMPTY.");
return false;
}

// compress
bool success = false;

try
{
using(var zip = new Ionic.Zip.ZipFile())
{
zip.AddFile(filePath, "");
zip.Save(targetFilePath);
success = true;
}
}
catch(Exception e)
{
Debug.LogWarning("[mod.io] Unable to compress file to archive."
+ "\nFile: " + filePath
+ "\nOutput: " + targetFilePath
+ "\n\n"
+ Utility.GenerateExceptionDebugString(e));
}

return success;
}
}
}

0 comments on commit 34c56b9

Please sign in to comment.