files = array(); } function add_file ($path, $pakpath) { // Check path exists and is valid and pakpath is valid if (!is_readable ($path) || strlen ($pakpath) > 55 || strchr ($pakpath, '\\')) { return FALSE; } array_push ($this->files, array("filepath" => $path, "pakpath" => $pakpath)); return TRUE; } function add_directory ($basedir, $pakdir, $match = '/.*/') { // Check it's really a directory if (!is_dir ($basedir)) { return FALSE; } // Be sure pakdir is proper path since readdir returns only filenames if (!preg_match ("/\/$/", $pakdir)) { $pakdir .= '/'; } // Open directory $dh = opendir ($basedir); // Read in entries while (($entry = readdir($dh)) !== FALSE) { // Generate proper paths $fullpath = $basedir . '/' . $entry; $pakpath = $pakdir . $entry; // If it's a valid file, add it if (is_file($fullpath) && is_readable($fullpath)) { // Check it's wanted if (!preg_match ($match, $entry)) { continue; } $this->add_file ($fullpath, $pakpath); } else if (is_dir ($fullpath) && $entry != '.' && $entry != '..') { // Descend into this directory $this->add_directory ($fullpath, $pakpath); } } closedir ($dh); return TRUE; } function remove_file_by_path ($path) { $num_items = count($this->files); for ($i = 0; $i < $num_items; $i++) { $file = &$this->files[$i]; if ($file['filepath'] == $path) { array_splice ($files, $i, 1); } } } function remove_file_by_pakpath ($path) { $num_items = count($this->files); for ($i = 0; $i < $num_items; $i++) { $file = &$this->files[$i]; if ($file['pakpath'] == $path) { array_splice ($this->files, $i, 1); } } } function generate_pak ($optimize) { $files = &$this->files; $num_items = count($files); $pak = NULL; // Pak data starts after the header $offset = 12; for ($i = 0; $i < $num_items; $i++) { $file = &$files[$i]; // Read in the file data $filesize = filesize ($file['filepath']); $filedata = file_get_contents ($file['filepath']); if (!$filedata) { return FALSE; } // Record filesize for directory $file['size'] = $filesize; // Optimize .pak output? if ($optimize) { // Calculate hash for duplicate check $file['hash'] = sha1($filedata, TRUE); for ($j = 0; $j < $i; $j++) { if ($file['hash'] == $files[$j]['hash']) { // Duplicated data, only write as offset in directory $file['offset'] = $files[$j]['offset']; continue 2; } } } // Record offset for directory $file['offset'] = $offset; // Add data $pak .= $filedata; // Update current offset $offset += $filesize; } //Pak directory $direntries = NULL; $dirlen = 0; for ($i = 0; $i < $num_items; $i++) { $file = &$files[$i]; $direntries .= pack ('a56@56VV', $file['pakpath'], $file['offset'], $file['size']); $dirlen += 64; } // Add directory $pak .= $direntries; // Add pak header and we're done $pack = pack ("VVV", 1262698832, $offset, $dirlen); $pack .= $pak; return $pack; } function save_pak ($path, $optimize) { $pak = $this->generate_pak ($optimize); $fh = fopen($path, "wb"); if (!$fh) { return FALSE; } fwrite ($fh, $pak); fclose ($fh); return TRUE; } } ?>