Shared memory file in PHP

后端 未结 2 2066
走了就别回头了
走了就别回头了 2021-02-04 13:42

I use openssl_pkcs7_sign and openssl_pkcs7_encrypt to create encrypted data. The functions only accept file names. I would like to store the temporary

相关标签:
2条回答
  • 2021-02-04 14:18

    Ok, so the way I would suggest doing this is with a file stream wrapper. Let me whip up a quick example:

    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;
        }
    
    }
    

    Now, you would then need to register the wrapper:

    stream_wrapper_register('static', 'staticStreamWrapper');
    

    So you now can treat it like a file even though it never actually leaves PHP (it's stored as a static variable)!

    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 讨论(0)
  • 2021-02-04 14:39

    Since Windows 2000, the shmop (previously shm_) methods are available.

    shmop_open uses a unique integer key to share the memory area. ftok can be used to produce a unique index based on a file path (typically your script file's full path). Any instance that shares the same key can share the same memory.

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

    Tested on PHP Version 5.3.3 from Zend Server CE System Windows NT CRYPE 6.1 build 7601 (Unknow Windows version Business Edition 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 stores raw bytes from a string, so you don't need to serialize it, but you will need to write the length of the string somewhere. My example creates a 16KB shared memory area, you can of course size it to fit the openssl file plus the space you need to store the file size.

    0 讨论(0)
提交回复
热议问题