blob: 77b96f50292f0e8168f5cefbc6f108e20b70a691 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
/**
* File.cpp
*
* Implementation file for the File class
*
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
* @copyright 2014 Copernica BV
*/
/**
* Dependencies
*/
#include "includes.h"
/**
* Namespace
*/
namespace Php {
/**
* Constructor
*
* The constructor receives a filename as parameter. It uses the normal
* PHP include path resolve algorithms to find the location of the file.
*
* @param name the filename
* @param size length of the filename
*/
File::File(const char *name, size_t size)
{
// we need the tsrm_ls variable
TSRMLS_FETCH();
// resolve the path
_path = zend_resolve_path(name, size TSRMLS_CC);
}
/**
* Destructor
*/
File::~File()
{
// clean up path name
if (_path) zend_string_release(_path);
}
/**
* Compile the file
* @return bool
*/
bool File::compile()
{
// never works if the path is invalid
if (!_path) return false;
// is the file already compiled?
if (_opcodes) return _opcodes->valid();
// we are going to open the file
zend_file_handle fileHandle;
// we need the tsrm_ls variable (@todo would it be better if this was a member?)
TSRMLS_FETCH();
// open the file
if (zend_stream_open(ZSTR_VAL(_path), &fileHandle TSRMLS_CC) == FAILURE) return false;
// make sure the path name is stored in the handle (@todo: is this necessary? do we need the copy?)
if (!fileHandle.opened_path) fileHandle.opened_path = zend_string_copy(_path);
// we need temporary compiler options
CompilerOptions options(ZEND_COMPILE_DEFAULT TSRMLS_CC);
// create the opcodes
_opcodes.reset(new Opcodes(zend_compile_file(&fileHandle, ZEND_INCLUDE TSRMLS_CC) TSRMLS_CC));
// close the file handle
zend_destroy_file_handle(&fileHandle TSRMLS_CC);
// done
return _opcodes->valid();
}
/**
* Does the file exist?
* @return boolean
*/
bool File::exists()
{
// it is of course not valid if the path could not be resolved
if (!_path) return false;
// if we have valid opcodes, we're sure that it exists
if (_opcodes && _opcodes->valid()) return true;
// retrieve stats
struct stat buf;
return stat(ZSTR_VAL(_path), &buf) == 0;
}
/**
* Is this a valid file?
* @return boolean
*/
bool File::valid()
{
// check if file is compilable
return compile();
}
/**
* Execute the file
* @return Value
*/
Value File::execute()
{
// do we already have the opcodes?
if (_opcodes) return _opcodes->execute();
// try compiling the file
if (!compile()) return nullptr;
// add the entry to the list of included files
zend_hash_add_empty_element(&EG(included_files), _path);
// execute the opcodes
return _opcodes->execute();
}
/**
* Execute a file only once
* @return Value
*/
Value File::once()
{
// skip if the path is invalid
if (!_path) return nullptr;
// we need the tsrm_ls variable (@todo would it be better if this was a member?)
TSRMLS_FETCH();
// check if this file was already included
if (zend_hash_exists(&EG(included_files), _path)) return nullptr;
// execute the file
return execute();
}
/**
* End of namespace
*/
}
|