Exemple #1
0
        //public IEnumerator GetEnumerator() {
        //    foreach (object o in Nodes.Values.ToList()) {
        //        if (o == null) {
        //            break;
        //            }
        //        yield return o;
        //        }
        //    }
        #endregion "Accessors"

        /// <summary>
        /// Creates a virtual node to display, linking 'up' a level in the tree
        /// </summary>
        /// <param name="current">Current <PRTableNode>PRTableNode</PRTableNode> from which to generate the virtual 'up' node</param>
        /// <returns><PRTableNode>PRTableNode</PRTableNode></returns>
        public PRTableNode GetVirtualUpNode(PRTableNode current)
        {
            PRTableNode virtualUP = PRTableNode.CreateUp(new PRNode("Up", Guid.Empty));

            virtualUP.GUID       = GetPPGuid(current.GUID);
            virtualUP.Name       = Utils.StringToBase("Up");
            virtualUP.Node.Flags = NodeFlag.Directory;
            return(virtualUP);
        }
Exemple #2
0
 /// <summary>
 /// Adds an orphan <PRTableNode>&lt;PRTableNode&gt;</PRTableNode> to the FileTable
 /// </summary>
 /// <param name="node">PRTableNode to insert</param>
 /// <returns><ErrCode>ErrCode</ErrCode></returns>
 public ErrCode Add(PRTableNode node)
 {
     //Log($"Adding PRTNode {node.Name}", LogType.Info);
     if (Nodes.Values.Contains(node))
     {
         return(ErrCode.APP_DUPLICATE_NODE);
     }
     else
     {
         Nodes.Add(node.GUID, node);
         return(ErrCode.SUCCESS);
     }
 }
Exemple #3
0
        /// <summary>
        /// Extract specified PRNode to specified file/path
        /// </summary>
        /// <param name="node">Node to extract</param>
        /// <param name="path"></param>
        /// <returns><errcode>Result</errcode></returns>
        private ErrCode ExFile(PRNode node, DirectoryInfo path, ProgressTracker pt, string altName = "")
        {
            Log($"Creating streams for IO ..", LogType.Init);
            PRTableNode  prt    = node.TableNode;
            string       fName  = altName == "" ? prt.DisplayName : altName;
            FileStream   output = new FileStream(Path.Combine(path.FullName, fName), FileMode.Create);
            BinaryWriter bw     = new BinaryWriter(output);

            PRXSwapFile.Seek(prt.Offset, 0);
            // create a hash algorithm to be used in the while(read) loop
            HashAlgorithm hasher = new MD5CryptoServiceProvider();

            long bytesRead;
            long tbr         = 0;
            long bytesToRead = prt.SizeUncompressed;
            var  buffer      = new byte[Utils.IO_BUFFER_SIZE];

            Log($"Writing data..", LogType.IO);
            long bytesSoFar = 0;

            while (bytesToRead > 0)
            {
                long bytesLeft = prt.SizeUncompressed - bytesSoFar;
                long bufSize   = bytesToRead > Utils.IO_BUFFER_SIZE ? Utils.IO_BUFFER_SIZE : bytesLeft;
                bytesRead   = PRXSwapFile.Read(buffer, 0, (int)bufSize);
                bytesSoFar += bytesRead;
                hasher.TransformBlock(buffer, 0, (int)bufSize, null, 0);
                bytesToRead -= bytesRead;
                tbr         += bytesRead;
                bw.Write(buffer, 0, (int)bytesRead);
            }

            hasher.TransformFinalBlock(new byte[0], 0, 0);
            byte[] hash = hasher.Hash;
            if (HashToHex(hash) == prt.Hash)
            {
                Log($"Ex OK [{prt.HashString}]", LogType.Info);
                pt[node] = ErrCode.SUCCESS;
                return(ErrCode.SUCCESS);
            }
            else
            {
                Log($"Fail! [{prt.Hash}]", LogType.Critical);
                pt[node] = ErrCode.APP_FAIL_HASH;
                return(ErrCode.APP_FAIL_HASH);
            }
        }
Exemple #4
0
        /// <summary>
        /// Initializes the MasterFileTable and instantiates a virtual 'root' from which all nodes are descended
        /// </summary>
        public PRTable()
        {
            Log("MasterFileTable initialize and set virtual toplevel node", LogType.FTable);
            Nodes = new Dictionary <Guid, PRTableNode>();

            PRTableNode prt = PRTableNode.CreateUp(RootNode);
            Encoding    enc = System.Text.Encoding.UTF8;

            prt.GUID         = RootNode.GUID;
            prt.Parent       = RootNode.GUID;
            prt.DateCreated  = 0;
            prt.DateModified = 0;
            prt.Attribs      = Attrib.Root;
            prt.NameLength   = Convert.ToBase64String(enc.GetBytes("/")).Length;
            prt.Name         = Convert.ToBase64String(enc.GetBytes("/"));

            Nodes.Add(prt.GUID, prt);
        }
Exemple #5
0
        /// <summary>
        /// Add a file to the prx archive beneath specified node
        /// </summary>
        /// <param name="file">File to be added</param>
        /// <param name="parent">Parent node of added file</param>
        /// <returns><errcode>Result</errcode></returns>
        private ErrCode AddFile(string file, ProgressTracker progress, PRNode parent)
        {
            ErrCode err = ErrCode.NULL;

            if (!File.Exists(file))
            {
                err = ErrCode.APP_FAIL_TO_READ;
                return(err);
            }

            // forcefully demand read access to the target file, returning ErrCode.EX_ACCESS_DENIED if this fails
            try {
                new FileIOPermission(FileIOPermissionAccess.Read, file).Demand();
            }
            catch (SecurityException se) {
                err = ErrCode.EX_ACCESS_DENIED;
                return(MapExceptionName(se));
            }
            catch (NullReferenceException ex) {
                Log($"Ex: {MapExceptionName(ex)}", LogType.Error);
            }

            long        startOfWrite = 0;
            FileInfo    fi           = new FileInfo(file);
            PRNode      node         = new PRNode(fi.Name, parent.GUID);
            PRTableNode prtn         = new PRTableNode(fi, node, fi.Name, parent.GUID);
            FileStream  fs           = null;

            node.AssignTableNode(prtn);


            //TODO Refactor this to a BinaryWriter extension: BinaryWriter.Write(PRNode)

            try {
                BinaryWriter bw = new BinaryWriter(PRXSwapFile);

                fs = new FileStream(fi.FullName, FileMode.Open);

                // jump to the end of the swap file
                bw.Seek(0, SeekOrigin.End);
                startOfWrite = bw.BaseStream.Position;

                node.TableNode.SizeUncompressed = fi.Length;

                // write the data header
                bw.Write(node.GUID.ToByteArray());
                bw.Write(new string('X', 16)); // we write a spacer for the hash that'll be inserted after we actually parse the data
                bw.Write((ulong)fi.Length);
                long dataOffset = bw.BaseStream.Position;
                node.TableNode.Offset = (long)dataOffset;

                // create a hash algorithm to be used in the while(read) loop
                HashAlgorithm hasher = new MD5CryptoServiceProvider();

                int bytesRead;
                var buffer = new byte[Utils.IO_BUFFER_SIZE];
                progress.BytesProcessedInFile = 0;
                progress.TotalBytesInFile     = fi.Length;
                while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
                {
                    progress.BytesProcessed       += bytesRead;
                    progress.BytesProcessedInFile += bytesRead;

                    //TODO encrypt/compress data [optional]

                    bw.Write(buffer, 0, bytesRead);
                    hasher.TransformBlock(buffer, 0, bytesRead, null, 0);
                    ProgressReport(progress);
                }

                hasher.TransformFinalBlock(new byte[0], 0, 0);
                byte[] hash = hasher.Hash;
                prtn.Hash = HashToHex(hash);
                PRXSwapFile.Seek(dataOffset - 24, SeekOrigin.Begin);
                //bw.Seek(dataOffset - 24, SeekOrigin.Begin);
                PRXSwapFile.Write(hash, 0, hash.Length);
                //bw.Write(hash);

                //Log($"Wrote {progress.BytesProcessedInFile}b [{prtn.HashString}] at offset: {dataOffset}, EOD: {bw.BaseStream.Position}", LogType.IO);

                // move back to the end of the stream just for safety
                bw.Seek(0, SeekOrigin.End);
                PRXSwapFile.Seek(0, SeekOrigin.End);
                //BUG Not properly inserting all files anymore.. WTF
                //INFO Have to close the BinaryWriter without colosing the underlying stream.. F**K.
                //bw.Dispose();

                // supposedly the binarywriter is closed *WITHOUT* nuking PRXSwapFile..
            }
            catch (Exception ex) {
                //TODO remove whatever may have been written in the event of a failure
                // this'll be added at a later date when I'm able to produce an error
                //Log($"EX: {MapExceptionName(ex)} on {fi.Name} in {fi.DirectoryName}", LogType.Exception);
                return(MapExceptionName(ex));
            }
            finally {
                fs.Dispose();
                //GC.Collect(1); //Cardinal sin, I know.. But I can't dispose of the binarywriter, has to be collected so it won't close PRXSwapFile
            }

            // increment the number of files processed in our tracker
            progress.FilesProcessed++;

            // finally, if and only if this is ErrCode.SUCCESS- add the node as a TableNode to our FileTable
            if (err == ErrCode.NULL)
            {
                FileTable.Add(prtn);
            }

            return(ErrCode.SUCCESS);
        }
Exemple #6
0
        /// <summary>
        /// Adds a directory entry to the archive
        /// </summary>
        /// <param name="dir">Directory to be added</param>
        /// <param name="progress">ProgressTracker</param>
        /// <param name="parent">Parent node of which this node belongs</param>
        /// <returns>ErrCode</returns>
        private PRNode AddDirectory(DirectoryInfo di, ProgressTracker progress, PRNode parent)
        {
            PRNode      retVal = new PRNode(di, parent.GUID);
            PRTableNode prtn   = new PRTableNode(di, retVal, di.Name, parent.GUID);

            FileTable.Add(prtn);
            //BUG Directories aren't actually written to the archive, dumbass.

            #region failure
            //long startOfWrite = 0;
            //retVal.AssignTableNode(prtn);

            //try {
            //    BinaryWriter bw = new BinaryWriter(PRXSwapFile);

            //    bw.Seek(0, SeekOrigin.End);
            //    startOfWrite = bw.BaseStream.Position;

            //    bw.Write(retVal.GUID.ToByteArray());
            //    bw.Write(new string('X', 16)); // we write a spacer for the hash that'll be inserted after we actually parse the data
            //    bw.Write((short)retVal.TableNode.DisplayName.Length);
            //    long dataOffset = bw.BaseStream.Position;
            //    retVal.TableNode.Offset = (long)dataOffset;

            //    // create a hash algorithm to be used in the while(read) loop
            //    HashAlgorithm hasher = new MD5CryptoServiceProvider();

            //    int bytesRead;
            //    var buffer = new byte[Utils.IO_BUFFER_SIZE];
            //    progress.BytesProcessedInFile = 0;
            //    progress.TotalBytesInFile = fi.Length;
            //    while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0) {
            //        progress.BytesProcessed += bytesRead;
            //        progress.BytesProcessedInFile += bytesRead;

            //        //TODO encrypt/compress data [optional]

            //        bw.Write(buffer, 0, bytesRead);
            //        hasher.TransformBlock(buffer, 0, bytesRead, null, 0);
            //        ProgressReport(progress);
            //        }

            //    hasher.TransformFinalBlock(new byte[0], 0, 0);
            //    byte[] hash = hasher.Hash;
            //    prtn.Hash = HashToHex(hash);
            //    PRXSwapFile.Seek(dataOffset - 24, SeekOrigin.Begin);
            //    //bw.Seek(dataOffset - 24, SeekOrigin.Begin);
            //    PRXSwapFile.Write(hash, 0, hash.Length);
            //    //bw.Write(hash);

            //    //Log($"Wrote {progress.BytesProcessedInFile}b [{prtn.HashString}] at offset: {dataOffset}, EOD: {bw.BaseStream.Position}", LogType.IO);

            //    // move back to the end of the stream just for safety
            //    bw.Seek(0, SeekOrigin.End);
            //    PRXSwapFile.Seek(0, SeekOrigin.End);
            //    //BUG Not properly inserting all files anymore.. WTF
            //    //INFO Have to close the BinaryWriter without colosing the underlying stream.. F**K.
            //    //bw.Dispose();

            //    // supposedly the binarywriter is closed *WITHOUT* nuking PRXSwapFile..

            //    }
            //catch (Exception ex) {
            //    //TODO remove whatever may have been written in the event of a failure
            //    // this'll be added at a later date when I'm able to produce an error
            //    //Log($"EX: {MapExceptionName(ex)} on {fi.Name} in {fi.DirectoryName}", LogType.Exception);
            //    return MapExceptionName(ex);
            //    }
            //finally {

            //    fs.Dispose();
            //    //GC.Collect(1); //Cardinal sin, I know.. But I can't dispose of the binarywriter, has to be collected so it won't close PRXSwapFile

            //    }
            #endregion failure

            return(retVal);
        }
Exemple #7
0
 public ErrCode AssignTableNode(PRTableNode prtn)
 {
     this._TableNode = prtn;
     return(ErrCode.SUCCESS);
 }
Exemple #8
0
        /// <summary>
        /// Creates a virtual UP table node for navigation purposes
        /// </summary>
        /// <param name="n">Virual PRNode from which to base this</param>
        /// <returns>Virtual PRTableNode (that doesn't exist in the file table)</returns>
        public static PRTableNode CreateUp(PRNode n)
        {
            PRTableNode prtn = new PRTableNode(n);

            return(prtn);
        }