Skip to content

Commit

Permalink
Update readme and add extact() method
Browse files Browse the repository at this point in the history
  • Loading branch information
wapmorgan committed Sep 12, 2018
1 parent 1b4fcd1 commit 9cb9090
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 26 deletions.
61 changes: 38 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,32 @@ var_dump($cab->getFileData('README.md'));
## CabArchive API
All list of properties and methods of `CabArchive` is listed below.

- **$filesCount** - number of files in Cab-archive
- **__construct($filename)** - creates new instance from file, stream or socket
- **getCabHeader()** - returns header of Cab-archive as array
- **hasPreviousCab()** - checks that this cab has previous Cab in set
- **getPreviousCab()** - returns name of previous Cab
- **hasNextCab()** - checks that this cab has next Cab in set
- **getNextCab()** - returns name of next Cab
- **getSetId()** - returns set id (identical for all cab-archives from one set)
- **getInSetNumber()** - returns number of cab in set
- **getFileNames(): array** - retrives list of files from archive
- **getFileData($filename): object** - returns additional info of file as object.
- **getFileAttributes($filename): array** - returns list of file attributes. All available attributes:
- **CabArchive::ATTRIB_READONLY**
- **CabArchive::ATTRIB_HIDDEN**
- **CabArchive::ATTRIB_SYSTEM**
- **CabArchive::ATTRIB_EXEC**
- **getFileContent($filename): string** - returns raw content of file.
- **extract($output, array $nodes = [])** - _in development now_

### getFileNames()
- `$filesCount` - number of files in Cab-archive
- `__construct($filename)` - creates new instance from file, stream or socket
- `getCabHeader()` - returns header of Cab-archive as array
- `hasPreviousCab()` - checks that this cab has previous Cab in set
- `getPreviousCab()` - returns name of previous Cab
- `hasNextCab()` - checks that this cab has next Cab in set
- `getNextCab()` - returns name of next Cab
- `getSetId()` - returns set id (identical for all cab-archives from one set)
- `getInSetNumber()` - returns number of cab in set
- `getFileNames(): array` - retrives list of files from archive
- `getFileData($filename): object` - returns additional info of file as object.
- `getFileAttributes($filename): array` - returns list of file attributes. All available attributes:
- `CabArchive::ATTRIB_READONLY`
- `CabArchive::ATTRIB_HIDDEN`
- `CabArchive::ATTRIB_SYSTEM`
- `CabArchive::ATTRIB_EXEC`
- `getFileContent($filename): string` - returns raw content of file.
- `extract($output, array $files = []): bool|int` - _in development now_

### getFileNames
```php
array getFileNames()
```
This method returns an array of file names compressed in cab.

### getFileData($filename)
### getFileData
```php
object getFileData($filename)
```
Expand All @@ -68,11 +68,26 @@ This method returns an object with following fields:
- **unixtime** - date&time of modification in unixtime format
- **isCompressed** - is file compressed as _boolean_

### getFileContent($filename)
### getFileContent
```php
string getFileContent($filename)
```
This method returns raw file content of `$filename`. Supports extracting from cab's without compression and with MSZip compression. LZX compression is not supported.
This method returns raw file content of `$filename`.
Supports extracting from cab's without compression and with MSZip compression. LZX compression is not supported.

Works correctly only on PHP:

- 7.0.22+
- 7.1.8+
- 7.2.0

### extract($outputDirectory, array $files = [])
```php
int|bool extract($outputDirectory, array $files = [])
```
This method extracts passed files or the whole cab to `$outputDirectory`.

Supports extracting from cab's without compression and with MSZip compression. LZX compression is not supported.

Works correctly only on PHP:

Expand Down
5 changes: 4 additions & 1 deletion bin/cabfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ if (!isset($argv[1])) die('Usage: '.basename(__FILE__).' <cab> [<operation>] [--
.' - blocks - show all blocks within cab'.PHP_EOL
.' - files - show files list within cab'.PHP_EOL
.' - [filename] - show information about files within cab'.PHP_EOL
.' If you set --content option, it will print content of the file'.PHP_EOL);
.' If you set --content option, it will print content of the file'.PHP_EOL
.' If you set --extract option, it will extract file in current folder'.PHP_EOL);

$width = TerminalInfo::isInteractive() ? (TerminalInfo::getWidth() - 30) : 50;

Expand Down Expand Up @@ -46,5 +47,7 @@ switch ($mode) {
var_dump($cab->getFileData($mode));
if (in_array('--content', $argv))
var_dump($cab->getFileContent($mode));
else if (in_array('--extract', $argv))
var_dump($cab->extract(getcwd(), [$mode]));
break;
}
86 changes: 85 additions & 1 deletion src/CabArchive.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ class CabArchive {
public $foldersCount = -1;
public $blocksCount = -1;

/**
* CabArchive constructor.
* @param $filename
* @throws Exception
*/
public function __construct($filename) {
$this->filename = $filename;
$this->stream = new BinaryStream($filename);
Expand All @@ -32,6 +37,9 @@ public function __construct($filename) {
$this->open();
}

/**
*
*/
protected function setupReader() {
$this->stream->saveGroup('header', [
's:signature' => 4,
Expand Down Expand Up @@ -65,6 +73,9 @@ protected function setupReader() {
]);
}

/**
* @throws Exception
*/
protected function open() {
if (!$this->stream->compare(4, 'MSCF'))
throw new Exception('This is not a cab-file');
Expand Down Expand Up @@ -142,42 +153,72 @@ protected function open() {
}
}

/**
* @return mixed
*/
public function getCabHeader() {
return $this->header;
}

/**
* @return int
*/
public function hasPreviousCab() {
return $this->header['flags'] & 0x1;
}

/**
* @return mixed
*/
public function getPreviousCab() {
return $this->header['cab_previous'];
}

/**
* @return int
*/
public function hasNextCab() {
return $this->header['flags'] & 0x2;
}

/**
* @return mixed
*/
public function getNextCab() {
return $this->header['cab_next'];
}

/**
* @return mixed
*/
public function getSetId() {
return $this->header['setId'];
}

/**
* @return mixed
*/
public function getInSetNumber() {
return $this->header['inSetNumber'];
}

/**
* @return array
*/
public function getCabFolders() {
return $this->folders;
}

/**
* @return array
*/
public function getCabBlocks() {
return $this->blocks;
}

/**
* @return array
*/
public function getFileNames() {
$files = array();
foreach ($this->files as $file) {
Expand All @@ -186,6 +227,10 @@ public function getFileNames() {
return $files;
}

/**
* @param $filename
* @return bool|object
*/
public function getFileData($filename) {
foreach ($this->files as $file) {
if ($file['name'] == $filename) {
Expand Down Expand Up @@ -214,7 +259,7 @@ public function getFileData($filename) {
/**
* List of attributes of file.
* @param string $filename Name of stored file
* @return array An array that may containing following values: CabArchive::ATTRIB_READONLY, CabArchive::ATTRIB_HIDDEN, CabArchive::ATTRIB_SYSTEM, CabArchive::ATTRIB_EXEC
* @return array|bool An array that may containing following values: CabArchive::ATTRIB_READONLY, CabArchive::ATTRIB_HIDDEN, CabArchive::ATTRIB_SYSTEM, CabArchive::ATTRIB_EXEC
*/
public function getFileAttributes($filename) {
foreach ($this->files as $file) {
Expand All @@ -233,6 +278,7 @@ public function getFileAttributes($filename) {
* Gets content of the file
* @param string $filename Name of stored file
* @return string|boolean Content of the file. False, if decompression is not supported.
* @throws Exception
*/
public function getFileContent($filename) {
foreach ($this->files as $file) {
Expand Down Expand Up @@ -272,8 +318,35 @@ public function getFileContent($filename) {
return $content;
}

/**
* Extracts file or files to specific folder
* @param $outputFolder
* @param array $files
* @return bool|int
* @throws Exception
*/
public function extract($outputFolder, $files = array())
{
$extracted = 0;
$outputFolder = realpath($outputFolder);

if (empty($files)) $files = $this->files;

foreach ($files as $file) {
if (file_put_contents($outputFolder.'/'.$file, $this->getFileContent($file)) === false)
return false;
$extracted++;
}

return $extracted;
}

/**
* Returns list of block ids in which file stored
* @param $folderId
* @param $fileOffset
* @param $fileSize
* @return array
*/
protected function detectBlocksOfFile($folderId, $fileOffset, $fileSize) {
$fileEnd = $fileOffset + $fileSize;
Expand All @@ -293,6 +366,9 @@ protected function detectBlocksOfFile($folderId, $fileOffset, $fileSize) {

/**
* Decompresses folder with MS-ZIP compression
* @param $folderId
* @return bool
* @throws Exception
*/
protected function decompressMsZipFolder($folderId) {
if (isset($this->foldersRaw[$folderId]))
Expand Down Expand Up @@ -324,6 +400,9 @@ protected function decompressMsZipFolder($folderId) {

/**
* Decompresses folder with LZX compression. Not supported now
* @param $folderId
* @return bool
* @throws Exception
*/
protected function decompressLzxFolder($folderId) {
if (isset($this->foldersRaw[$folderId]))
Expand All @@ -333,6 +412,8 @@ protected function decompressLzxFolder($folderId) {

/**
* Reads folder without compression
* @param $folderId
* @return bool
*/
protected function readFolder($folderId) {
if (isset($this->foldersRaw[$folderId]))
Expand All @@ -359,6 +440,9 @@ protected function readNullTerminatedString() {

/**
* Calculates how B intersect with A
* @param array $rangeA
* @param array $rangeB
* @return float|int
*/
protected function calculateRangesIntersection(array $rangeA, array $rangeB) {
$intersection = 100;
Expand Down
20 changes: 19 additions & 1 deletion src/TerminalInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
class TerminalInfo {
const WIDTH = 1;
const HEIGHT = 2;

/**
* @return bool
*/
static public function isInteractive() {
if (strncasecmp(PHP_OS, 'win', 3) === 0) {
// windows has no test for that
Expand All @@ -18,6 +22,9 @@ static public function isInteractive() {
}
}

/**
* @return string
*/
static public function getWidth() {
if (strncasecmp(PHP_OS, 'win', 3) === 0) {
return self::getWindowsTerminalSize(self::WIDTH);
Expand All @@ -26,6 +33,9 @@ static public function getWidth() {
}
}

/**
* @return string
*/
static public function getHeight() {
if (strncasecmp(PHP_OS, 'win', 3) === 0) {
return self::getWindowsTerminalSize(self::HEIGHT);
Expand All @@ -34,12 +44,20 @@ static public function getHeight() {
}
}

/**
* @param $param
* @return string
*/
static protected function getWindowsTerminalSize($param) {
$output = explode("\n", shell_exec('mode'));
$output = explode("\n", shell_exec('mode con'));
$line = explode(':', trim($param == self::WIDTH ? $output[4] : $output[3]));
return trim($line[1]);
}

/**
* @param $param
* @return string
*/
static protected function getUnixTerminalSize($param) {
return trim(shell_exec('tput '.($param == self::WIDTH ? 'cols' : 'linus')));
}
Expand Down

0 comments on commit 9cb9090

Please sign in to comment.