/// <summary> /// Reads a session archive zip file into an array of Session objects /// </summary> /// <param name="sFilename">Filename to load</param> /// <param name="bVerboseDialogs"></param> /// <returns>Loaded array of sessions or null, in case of failure</returns> private static Session[] ReadSessionArchive(string sFilename, bool bVerboseDialogs) { /* Okay, given the zip, we gotta: * Unzip * Find all matching pairs of request, response * Create new Session object for each pair */ if (!File.Exists(sFilename)) { FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive Failed. File " + sFilename + " does not exist."); return null; } ZipArchive oZip = null; List<Session> outSessions = new List<Session>(); try { // Sniff for ZIP file. FileStream oSniff = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.Read); if (oSniff.Length < 64 || oSniff.ReadByte() != 0x50 || oSniff.ReadByte() != 0x4B) { // Sniff for 'PK' FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive Failed. " + sFilename + " is not a Fiddler-generated .SAZ archive of HTTP Sessions."); oSniff.Close(); return null; } oSniff.Close(); oZip = new ZipArchive(new DiskFile(sFilename)); oZip.BeginUpdate(); AbstractFolder oRaw = oZip.GetFolder("raw"); if (!oRaw.Exists) { FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive Failed. The selected ZIP is not a Fiddler-generated .SAZ archive of HTTP Sessions."); oZip.EndUpdate(); return null; } foreach (AbstractFile oRequestFile in oRaw.GetFiles(true, @"*_c.txt")) { try { byte[] arrRequest = new byte[oRequestFile.Size]; Stream oFS; RetryWithPassword: try { oFS = oRequestFile.OpenRead(FileShare.Read); } catch (Xceed.Zip.InvalidDecryptionPasswordException) { Console.Write("Password-Protected Session Archive.\nEnter the password to decrypt, or enter nothing to abort opening.\n>"); string sPassword = Console.ReadLine(); if (sPassword != String.Empty) { oZip.DefaultDecryptionPassword = sPassword; goto RetryWithPassword; } return null; } int iRead = Utilities.ReadEntireStream(oFS, arrRequest); oFS.Close(); Debug.Assert(iRead == arrRequest.Length, "Failed to read entire request."); AbstractFile oResponseFile = oRaw.GetFile(oRequestFile.Name.Replace("_c.txt", "_s.txt")); if (!oResponseFile.Exists) { FiddlerApplication.Log.LogString("Could not find a server response for: " + oResponseFile.FullName); continue; } byte[] arrResponse = new byte[oResponseFile.Size]; oFS = oResponseFile.OpenRead(); iRead = Utilities.ReadEntireStream(oFS, arrResponse); oFS.Close(); Debug.Assert(iRead == arrResponse.Length, "Failed to read entire response."); oResponseFile = oRaw.GetFile(oRequestFile.Name.Replace("_c.txt", "_m.xml")); Session oSession = new Session(arrRequest, arrResponse); if (oResponseFile.Exists) { oSession.LoadMetadata(oResponseFile.OpenRead()); } oSession.oFlags["x-LoadedFrom"] = oRequestFile.Name.Replace("_c.txt", "_s.txt"); outSessions.Add(oSession); } catch (Exception eX) { FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive incomplete. Invalid data was present in session: " + oRequestFile.FullName + ".\n\n\n" + eX.Message + "\n" + eX.StackTrace); } } } catch (Exception eX) { FiddlerApplication.ReportException(eX, "ReadSessionArchive Error"); return null; } if (null != oZip) { oZip.EndUpdate(); oZip = null; } return outSessions.ToArray(); }
/// <summary> /// Reads a session archive zip file into an array of Session objects /// </summary> /// <param name="sFilename">Filename to load</param> /// <param name="bVerboseDialogs"></param> /// <returns>Loaded array of sessions or null, in case of failure</returns> private static Session[] ReadSessionArchive(string sFilename, bool bVerboseDialogs) { /* Okay, given the zip, we gotta: * Unzip * Find all matching pairs of request, response * Create new Session object for each pair */ if (!File.Exists(sFilename)) { FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive Failed. File " + sFilename + " does not exist."); return null; } ZipFile oZip = null; string sPassword = String.Empty; List<Session> outSessions = new List<Session>(); try { // Sniff for ZIP file. FileStream oSniff = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.Read); if (oSniff.Length < 64 || oSniff.ReadByte() != 0x50 || oSniff.ReadByte() != 0x4B) { // Sniff for 'PK' FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive Failed. " + sFilename + " is not a Fiddler-generated .SAZ archive of HTTP Sessions."); oSniff.Close(); return null; } oSniff.Close(); oZip = new ZipFile(sFilename); if (!oZip.EntryFileNames.Contains("raw/")) { FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive Failed. The selected ZIP is not a Fiddler-generated .SAZ archive of HTTP Sessions."); return null; } foreach (ZipEntry oZE in oZip) { // Not a request. Skip it. if (!oZE.FileName.EndsWith("_c.txt") || !oZE.FileName.StartsWith("raw/")) continue; GetPassword: if (oZE.Encryption != EncryptionAlgorithm.None && (String.Empty == sPassword)) { Console.Write("Password-Protected Session Archive.\nEnter the password to decrypt, or enter nothing to abort opening.\n>"); sPassword = Console.ReadLine(); if (sPassword != String.Empty) { oZip.Password = sPassword; } else { return null; } } try { byte[] arrRequest = new byte[oZE.UncompressedSize]; Stream oFS; try { oFS = oZE.OpenReader(); } catch (Ionic.Zip.BadPasswordException) { Console.WriteLine("Incorrect password."); sPassword = String.Empty; goto GetPassword; } int iRead = Utilities.ReadEntireStream(oFS, arrRequest); oFS.Close(); Debug.Assert(iRead == arrRequest.Length, "Failed to read entire request."); ZipEntry oZEResponse = oZip[oZE.FileName.Replace("_c.txt", "_s.txt")]; if (null == oZEResponse) { FiddlerApplication.Log.LogString("Could not find a server response for: " + oZE.FileName); continue; } byte[] arrResponse = new byte[oZEResponse.UncompressedSize]; oFS = oZEResponse.OpenReader(); iRead = Utilities.ReadEntireStream(oFS, arrResponse); oFS.Close(); Debug.Assert(iRead == arrResponse.Length, "Failed to read entire response."); Session oSession = new Session(arrRequest, arrResponse); ZipEntry oZEMetadata = oZip[oZE.FileName.Replace("_c.txt", "_m.xml")]; if (null != oZEMetadata) { oSession.LoadMetadata(oZEMetadata.OpenReader()); } oSession.oFlags["x-LoadedFrom"] = oZE.FileName.Replace("_c.txt", "_s.txt"); outSessions.Add(oSession); } catch (Exception eX) { FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive incomplete. Invalid data was present in session: " + oZE.FileName + ".\n\n\n" + eX.Message + "\n" + eX.StackTrace); } } /* RetryWithPassword: try { oFS = oRequestFile.OpenRead(FileShare.Read); } catch (Xceed.Zip.InvalidDecryptionPasswordException) { Console.WriteLine("Password-Protected Session Archive.\nEnter the password to decrypt, or enter nothing to abort opening.\n>"); string sPassword = Console.ReadLine(); if (sPassword != String.Empty) { oZip.DefaultDecryptionPassword = sPassword; goto RetryWithPassword; } return null; } */ } catch (Exception eX) { FiddlerApplication.ReportException(eX, "ReadSessionArchive Error"); return null; } if (null != oZip) { oZip.Dispose(); oZip = null; } return outSessions.ToArray(); }
/// <summary> /// Reads a session archive zip file into an array of Session objects /// </summary> /// <param name="sFilename">Filename to load</param> /// <param name="bVerboseDialogs"></param> /// <returns>Loaded array of sessions or null, in case of failure</returns> private static Session[] ReadSessionArchive(string sFilename, bool bVerboseDialogs) { /* Okay, given the zip, we gotta: * Unzip * Find all matching pairs of request, response * Create new Session object for each pair */ if (!File.Exists(sFilename)) { FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive Failed. File " + sFilename + " does not exist."); return null; } List<Session> outSessions = new List<Session>(); try { // Sniff for ZIP file. using (FileStream oSniff = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (oSniff.Length < 64 || oSniff.ReadByte() != 0x50 || oSniff.ReadByte() != 0x4B) { // Sniff for 'PK' FiddlerApplication.Log.LogString("SAZFormat> ReadSessionArchive Failed. " + sFilename + " is not a Fiddler-generated .SAZ archive of HTTP Sessions."); return null; } } using (Package oZip = Package.Open(sFilename, FileMode.Open)) { PackagePartCollection oAllParts = oZip.GetParts(); foreach (PackagePart oPPC in oAllParts) { string sURI = oPPC.Uri.ToString(); if (!sURI.EndsWith("_c.txt")) continue; byte[] arrRequest = null; byte[] arrResponse = null; // Okay, we now have a Request. Let's read it. using (Stream oData = oPPC.GetStream(FileMode.Open, FileAccess.Read)) { arrRequest = ReadEntireStream(oData); } try { sURI = sURI.Replace("_c.txt", "_s.txt"); // Get the response PackagePart oResponse = oZip.GetPart(new Uri(sURI, UriKind.Relative)); using (Stream oData = oResponse.GetStream(FileMode.Open, FileAccess.Read)) { arrResponse = ReadEntireStream(oData); } } catch (Exception eX) { FiddlerApplication.Log.LogString("Could not load Server Response: " + sURI + "\n" + eX.Message); // Fatal error. Skip this session continue; } Session oSession = new Session(arrRequest, arrResponse); oSession.oFlags["x-LoadedFrom"] = sURI; sURI = sURI.Replace("_s.txt", "_m.xml"); try { // Get the Metadata PackagePart oMetadata = oZip.GetPart(new Uri(sURI, UriKind.Relative)); Stream oData = oMetadata.GetStream(FileMode.Open, FileAccess.Read); oSession.LoadMetadata(oData); // Note: Closes the stream automatically } catch { FiddlerApplication.Log.LogString("Could not load Metadata: " + sURI); // Missing metadata is not-fatal. } outSessions.Add(oSession); } } } catch (Exception eX) { FiddlerApplication.ReportException(eX, "ReadSessionArchive Error"); return null; } return outSessions.ToArray(); }