/// <summary> /// Remove a PXZ record object by instance /// </summary> /// <param name="record">Exact instance of the record to delete</param> public void RemoveRecord(PxzRecord record) { if (Records.Contains(record)) { Records.Remove(record); } }
public static XmlDocument PxzRecordToXml(PxzRecord record) { try { var xsSubmit = new XmlSerializer(typeof(PxzRecord)); var xmlSettings = new XmlWriterSettings(); var sww = new StringWriter(); var doc = new XmlDocument(); xmlSettings.Indent = true; xmlSettings.IndentChars = "\t"; xmlSettings.OmitXmlDeclaration = false; xsSubmit.Serialize(sww, record); doc.LoadXml(sww.ToString()); return(doc); } catch (Exception) { return(null); } }
/// <summary> /// Load an existing PXZ file from disk /// </summary> /// <param name="path">The file to load</param> public void Load(string path) { try { //can't load a non-existent file if (!System.IO.File.Exists(path)) { return; } //clear all lists and assign the new location Location = path; Records.Clear(); FileIndex.RecordReference.Clear(); //item names to load const string idxName = @"index"; const string dirName = @"records"; //read the PXZ file into memory using var zip = ZipFile.Read(path); //load the raw file index into memory var idxFile = zip[idxName]; //the index can't be null! if (idxFile == null) { if (!ParseSilent) { UIMessages.Error(@"PXZ index couldn't be found or it isn't valid"); } return; } //raw gzip index string (base64) string idxString; //extract and save the index to a new stream using (var idxStream = new MemoryStream()) { idxFile.Extract(idxStream); //ERROR LINE idxStream.Position = 0; idxString = new StreamReader(idxStream).ReadToEnd(); } //Gzip decompress var idxByte = GZipCompressor.DecompressString(idxString); var index = Serializers.StringToPxzIndex(idxByte); //if this gets flipped to true, it's potentially bad news var tamperedWith = false; //load all records into memory foreach (var recFile in index.RecordReference.Select( r => $"{dirName}/{r.StoredName}") .Select(recName => zip[recName])) { //byte stream for the raw record using var recStream = new MemoryStream(); //grab data from the file and store in memory recFile.Extract(recStream); recStream.Position = 0; //open a new reader for the memory block using var reader = new StreamReader(recStream); //jump through the memory stream and turn it into Base64 var recRaw = reader.ReadToEnd(); //serialise rawXml into a usable PxzRecord var rec = PxzRecord.FromRawForm(recRaw); //sync Encrypted with ProtectedRecord (native object can't do this) rec.ProtectedRecord = rec.Content.Encrypted; //verify checksums on the record to ensure authenticity tamperedWith = !rec.ChecksumValid; //finally, index and store the record Records.Add(rec); FileIndex.RecordReference.Add(rec.Header.Naming); } //apply new values FileIndex = index; //check authenticity flag, and warn if it's been altered if (tamperedWith) { if (!ParseSilent) { UIMessages.Warning("Content has been modified\n\nThe MD5 checksums stored do not match the checksums calculated, which is an indication that the contents may have been altered outside of the PXZ handler. The file will continue loading after you close this message."); } } } catch (Exception ex) { if (!ParseSilent) { UIMessages.Error(ex.ToString()); } } }
/// <summary> /// Add a new PXZ record to this file /// </summary> /// <param name="record"></param> public void AddRecord(PxzRecord record) { Records.Add(record); FileIndex.RecordReference.Add(record.Header.Naming); }
public static void MetadataToFile(string fileName, PlexObject contentToExport, Bitmap poster = null, bool silent = false) { try { //try and obtain a poster if one wasn't provided var p = poster ?? ImageHandler.GetPoster(contentToExport); //create each new PXZ record in memory var rawMetadata = new PxzRecord(contentToExport.RawMetadata, @"raw"); var objMetadata = new PxzRecord(contentToExport.ToXml(), @"obj"); var ptrMetadata = new PxzRecord(p, @"poster"); //the records to save to the PXZ file are contained in a list var data = new List <PxzRecord> { rawMetadata, objMetadata, ptrMetadata }; //export the actor images (if any) if (contentToExport.Actors != null) { if (contentToExport.Actors.Count > 0) { //loop through each actor and attempt an image download foreach (var a in contentToExport.Actors) { //download var image = ImageHandler.GetImageFromUrl(a.ThumbnailUri); //verify if (image != Resources.unavailable) { //create a new record for the image var record = new PxzRecord(image, $"actor_{MD5Helper.CalculateMd5Hash(a.ThumbnailUri)}"); //add it to the collection data.Add(record); } } } } //embedded in PXZ indexing information var plexdlVersion = Assembly.GetEntryAssembly()?.GetName().Version; //initialise the PXZ file and flush it to disk var pxz = new PxzFile(data, plexdlVersion, BuildState.State); pxz.Save(fileName); //show a message indicating success if allowed if (!silent) { UIMessages.Info(@"Successfully exported metadata!"); } } catch (Exception ex) { if (!silent) { UIMessages.Error("An error occurred\n\n" + ex, @"Metadata Export Error"); } LoggingHelpers.RecordException(ex.Message, "XmlMetadataSaveError"); } }