0x38 $msf = array( 'signature' => 'a32', // Microsoft C/C++ MSF 7.00 ... 'page_size' => 'V', // количество байт в странице/блоке 'free_page' => 'V', // не используется (значение 1 или 2) 'pages' => 'V', // всего страниц в файле 'directory_size' => 'V', // размер основной страницы 'reserved' => 'V', // reserved 'directory' => 'V', // на какой странице основная страница ); $from = fopen($_SERVER['argv'][1], 'r+'); $header = unpack(implode('/', array_map(function ($key, $value) { return $value . $key; }, array_keys($msf),array_values($msf))), fread($from, 0x38)); if ($header['signature'] != "Microsoft C/C++ MSF 7.00\r\n\x1ADS\0\0\0") { echo 'Bad format'; exit; } echo 'Read ' . $_SERVER['argv'][1] . PHP_EOL; $original = array(); // количество основных страниц описания потоков $directory_pages = ceil($header['directory_size'] / $header['page_size']); // читаем все номера основных страниц fseek($from, $header['directory'] * $header['page_size']); $original['directory'] = array(); for ($i = 0; $i < $directory_pages; $i++) { $original['directory'][] = implode(unpack('V', fread($from, 4))); } // переход на описание всех потоков $directory_current = 0; fseek($from, $original['directory'][ $directory_current] * $header['page_size']); $data = fread($from, $header['page_size']); // количество всех потоков $original['streams'] = implode(unpack('V', substr($data, 0, 4))); $data = substr($data, 4); // размер в байтах каждого потока $original['stream_sizes'] = array(); for ($i = 0; $i < $original['streams']; $i++) { $original['stream_sizes'][] = implode(unpack('V', substr($data, 0, 4))); $data = substr($data,4); if (empty($data)) { $directory_current++; fseek($from, $original['directory'][ $directory_current] * $header['page_size']); $data = fread($from, $header['page_size']); } } // номера страниц каждого потока $original['streams_pages'] = array(); for ($i = 0; $i < $original['streams']; $i++) { // сколько страниц в текущем потоке $pages = ceil($original['stream_sizes'][ $i ] / $header['page_size']); if ($pages > 0) { $list = array(); for ($j = 0; $j < $pages; $j++) { $list[] = implode(unpack('V', substr($data, 0, 4))); $data = substr($data, 4); if (empty($data)) { $directory_current++; fseek($from, $original['directory'][ $directory_current] * $header['page_size']); $data = fread($from, $header['page_size']); } } $original['streams_pages'][] = $list; } else { $original['streams_pages'][] = array(); } } // что будем пропускать $skipping = array(); // пропускаем TPI (2), тогда нужны все потоки $skipping[2] = array( 'name' => '.skip-tpi', 'streams' => array_keys($original['streams_pages']) ); // пропускаем DBI (3), тогда хватит первых десяти $skipping[3] = array( 'name' => '.skip-dbi', 'streams' => array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) ); function align($to, $size ) { if (ftell($to) % $size) { for ($i = 0, $ic = $size - (ftell($to) % $size); $i < $ic; $i++) { fwrite($to, chr(0x00)); } } return ; } foreach ($skipping as $index => $skip) { $filename = substr_replace($_SERVER['argv'][1], $skip['name'], (int)strrpos($_SERVER['argv'][1], '.'), 0); echo 'Pack ' . $filename . PHP_EOL; $to = fopen($filename, 'w+'); // первые блоки в нули, потом перезапишем for ($i = 0; $i < $header['page_size'] * ($header['free_page'] + 1); $i++) { fwrite($to, chr(0x00)); } // $streams = array( count($skip['streams']), '', ); $bytes = 8; // 0 - описание всех потоков $stream_number = array(0 => array()); for ($i = 1, $ic = count($skip['streams']); $i < $ic; $i++) { $bytes += 4; $pages = $original['streams_pages'][ $i ]; $stream_number[ $i ] = array(); if ($i === $index) { $streams[] = 0; continue; } $streams[] = $original['stream_sizes'][ $i ]; for ($j = 0, $jc = count($pages); $j < $jc; $j++) { $bytes += 4; $stream_number[ $i ][] = ftell($to) / $header['page_size']; fseek($from, $pages[ $j ] * $header['page_size']); $data = fread($from, $header['page_size']); fwrite($to, $data); } } // количество страниц в описании потоков $pages = ceil($bytes / $header['page_size']); $directory = ftell($to) / $header['page_size']; for ($i = 0; $i < $pages; $i++) { $stream_number[0][] = $directory + $i; } // количество потоков $streams[1] = $bytes; // размеры потоков foreach ($streams as $data) { fwrite($to, pack('V', $data)); } // номера страниц foreach ($stream_number as $size) { foreach ($size as $data) { fwrite($to, pack('V', $data)); } } // выравниваем страницу align($to, $header['page_size']); // записываем основную страницу $directory_pages = ftell($to) / $header['page_size']; for ($i = 0; $i < $pages; $i++) { fwrite($to, pack('V', $directory + $i)); } // выравниваем страницу align($to, $header['page_size']); // переписываем заголовок $header['pages'] = $directory_pages + 1; $header['directory'] = $directory_pages; $header['directory_size'] = $pages * $header['page_size']; fseek($to, 0); fwrite($to, pack(implode($msf), ...array_values($header))); fclose($to); }