2011-04-14 14 views
9

Używam openssl_pkcs7_sign i openssl_pkcs7_encrypt do tworzenia zaszyfrowanych danych. Funkcje akceptują tylko nazwy plików. Chciałbym przechowywać pliki tymczasowe we wspólnej pamięci, aby poprawić wydajność. Rozumiem w Linuksie, że mogę file_put_contents('/dev/shm/xxx', data), ale nie jest to możliwe w systemie Windows. Czy jest jakiś przenośny sposób w PHP, aby to zrobić? Czy funkcja shmop_ pomoże tutaj? Dzięki.Plik pamięci współdzielonej w PHP

PS: Czy jest sposób, aby te funkcje zaakceptować ciągi danych?

PS2: Proszę nie sugerować wywoływania /usr/bin/openssl z PHP. To nie jest przenośne.

+0

co chcesz z tym zrobić po zapisaniu? Czy myślałeś o użyciu strumienia plików zamiast pamięci współdzielonej? zobacz [StreamWrapper] (http://us2.php.net/manual/en/class.streamwrapper.php) – ircmaxell

+0

Po prostu zapisuję dane w pliku (używając 'file_put_contents') i przesyłam nazwę pliku do funkcji OpenSSL. Większość obciążeń pochodzi z funkcji OpenSSL i operacji VFS (odczyt, zapis, odłączenie). W jaki sposób transmisja strumieniowa ma znaczenie? –

Odpowiedz

3

Od systemu Windows 2000 dostępne są metody shmop (wcześniej shm_).

shmop_open wykorzystuje unikalny klucz całkowity do współużytkowania obszaru pamięci. ftok można użyć do utworzenia unikalnego indeksu na podstawie ścieżki pliku (zazwyczaj pełnej ścieżki do pliku skryptu). Każda instancja udostępniająca ten sam klucz może współużytkować tę samą pamięć.

http://php.net/manual/en/ref.shmop.php

Testowane na wersji 5.3.3 PHP z Zend Server CE systemu Windows NT 6.1 build 7601 CRYPE (wersja Unknow Okna Business Edition z dodatkiem Service Pack 1) i586

<?php 
$key = ftok(__FILE__, 't'); 
$memory = shmop_open($key, "c", 0600, 16 * 1024); 
$data = array('data' => 'value'); 
$bytes = shmop_write($memory, serialize($data), 0); 
$return = shmop_read($memory, 0, $bytes); 
print_r(unserialize($return)); 
?> 

shmop_read/shmop_write sklepach surowe bajty z ciągu, więc nie musisz serializować go, ale musisz gdzieś napisać długość łańcucha. Mój przykład tworzy obszar pamięci współużytkowanej o wielkości 16 KB, można go oczywiście dopasować do pliku openssl i miejsca potrzebnego do zapisania rozmiaru pliku.

+0

Rozumiem funkcje 'shmop_'. Moje pytanie brzmi: jak przesłać nazwę pliku do OpenSSL? Bloki pamięci nie mają nazw plików. –

+0

Nie wygląda na to, że większość funkcji OpenSSL akceptuje wskaźniki plików, które pozwoliłyby na użycie plików pamięci '' php: // memory''. Będziesz musiał użyć plików tymczasowych do odczytu i wyjęcia danych, co negatywnie wpływa na korzyści płynące z pamięci współdzielonej. Jednak niektóre funkcje, takie jak openssl_private_decrypt, umożliwiają pracę z ciągami zamiast plikami, które można załadować i wyładować bezpośrednio z pamięci współużytkowanej. Są inne funkcje MIME, które mogą działać zamiast pkcs7, ale nie jestem aż tak znajomy. Zalecam sprawdzenie, czy którakolwiek z tych funkcji będzie działać zgodnie z Twoimi potrzebami. –

+0

Dodatkowo możesz użyć shmop_size, aby odzyskać rozmiar bloku. – RafaSashi

6

OK, więc sposób, w jaki proponuję to zrobić, to plik stream wrapper. Pozwól mi wzbudzać szybki przykład:

class staticStreamWrapper { 
    public $context; 
    protected static $data = array(); 

    protected $path = ''; 
    protected $pointer = 0; 
    protected $writable = false; 

    public function stream_close() {} 

    public function stream_eof() { 
     return $this->pointer >= strlen(static::$data[$this->path]); 
    } 

    public function stream_flush() {} 

    public function stream_open($path, $mode, $options, &$opened_path) { 
     switch ($mode[0]) { 
      case 'r': 
       if (!isset(static::$data[$path])) return false; 
       $this->path = $path; 
       $this->writable = isset($mode[1]) && $mode[1] == '+'; 
       break; 
      case 'w': 
       static::$data[$path] = ''; 
       $this->path = $path; 
       $this->writable = true; 
       break; 
      case 'a': 
       if (!isset(static::$data[$path])) static::$data[$path] = ''; 
       $this->path = $path; 
       $this->writable = true; 
       $this->pointer = strlen(static::$data[$path]); 
       break; 
      case 'x': 
       if (isset(static::$data[$path])) return false; 
       $this->path = $path; 
       $this->writable = true; 
       break; 
      case 'c': 
       if (!isset(static::$data[$path])) static::$data[$path] = ''; 
       $this->path = $path; 
       $this->writable = true; 
       break; 
      default: 
       return false; 
     } 
     $opened_path = $this->path; 
     return true; 
    } 

    public function stream_read($count) { 
     $bytes = min(strlen(static::$data[$this->path]) - $this->pointer, $count); 
     $data = substr(static::$data[$this->path], $this->pointer, $bytes); 
     $this->pointer += $bytes; 
     return $data; 
    } 

    public function stream_seek($offset, $whence = SEEK_SET) { 
     $len = strlen(static::$data[$this->path]); 
     switch ($whence) { 
      case SEEK_SET: 
       if ($offset <= $len) { 
        $this->pointer = $offset; 
        return true; 
       } 
       break; 
      case SEEK_CUR: 
       if ($this->pointer + $offset <= $len) { 
        $this->pointer += $offset; 
        return true; 
       } 
       break; 
      case SEEK_END: 
       if ($len + $offset <= $len) { 
        $this->pointer = $len + $offset; 
        return true; 
       } 
       break; 
     } 
     return false; 
    } 

    public function stream_stat() { 
     $size = strlen(static::$data[$this->path]); 
     $time = time(); 
     return array(
      0 => 0, 
      'dev' => 0, 
      1 => 0, 
      'ino' => 0, 
      2 => 0777, 
      'mode' => 0777, 
      3 => 1, 
      'nlink' => 1, 
      4 => 0, 
      'uid' => 0, 
      5 => 0, 
      'gid' => 0, 
      6 => '', 
      'rdev' => '', 
      7 => $size, 
      'size' => $size, 
      8 => $time, 
      'atime' => $time, 
      9 => $time, 
      'mtime' => $time, 
      10 => $time, 
      'ctime' => $time, 
      11 => -1, 
      'blksize' => -1, 
      12 => -1, 
      'blocks' => -1, 
     ); 
    } 

    public function stream_tell() { 
     return $this->pointer; 
    } 

    public function stream_write($data) { 
     if (!$this->writable) return 0; 
     $size = strlen($data); 
     $len = strlen(static::$data[$this->path]); 
     if ($this->stream_eof()) { 
      static::$data[$this->path] .= $data; 
     } else { 
      static::$data[$this->path] = substr_replace(
       static::$data[$this->path], 
       $data, 
       $this->pointer 
      ); 
     } 
     $this->pointer += $size; 
     return $size; 
    } 

    public function unlink($path) { 
     if (isset(static::$data[$path])) { 
      unset(static::$data[$path]); 
     } 
     return true; 
    } 

} 

Teraz, by następnie trzeba zarejestrować opakowanie:

stream_wrapper_register('static', 'staticStreamWrapper'); 

Więc teraz można traktować jak plik mimo że w rzeczywistości nigdy nie opuszcza PHP (jest przechowywany jako zmienna statyczna)!

file_put_contents('static://foo.txt', 'this is my data'); 
file_get_contents('static://foo.txt'); // "this is my data" 
$f = fopen('static://foo.txt', 'r'); // should return a resource 
// etc... 
+0

Dzięki za informację o strumieniu.Rozumiem, że PHP obsługuje implementację opakowania niestandardowego strumienia. Jednak rozszerzenie OpenSSL najprawdopodobniej zostanie napisane przy pomocy API systemu operacyjnego, a funkcje nie wykorzystują strumieni PHP. Wywołanie 'openssl_pkcs7_encrypt' z' static' stream powoduje pojawienie się następującego komunikatu o błędzie: 'error: 02001002: system library: fopen: No takiego pliku lub katalogu'. –

Powiązane problemy