-
Notifications
You must be signed in to change notification settings - Fork 29
/
Browser.php
185 lines (141 loc) · 7.46 KB
/
Browser.php
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<?php
//© 2016 Martin Madsen
namespace MTS\Common\Devices\Actions\Local\Host;
use MTS\Common\Devices\Actions\Local\Base;
class Browser extends Base
{
public function getBrowser($browserName, $enableDebug=false)
{
$this->_classStore['requestType'] = __FUNCTION__;
$this->_classStore['browserName'] = $browserName;
$this->_classStore['enableDebug'] = $enableDebug;
return $this->execute();
}
private function execute()
{
$requestType = $this->_classStore['requestType'];
$osObj = \MTS\Factories::getActions()->getLocalOperatingSystem()->getOsObj();
if ($requestType == 'getBrowser') {
$browserName = strtolower($this->_classStore['browserName']);
$enableDebug = $this->_classStore['enableDebug'];
if ($osObj->getType() == "Linux") {
if ($browserName == 'phantomjs') {
$fileFact = \MTS\Factories::getFiles();
$pipeUuid = uniqid();
$workPath = $fileFact->getDirectory(MTS_WORK_PATH . DIRECTORY_SEPARATOR . "LHB_" . $pipeUuid);
if ($osObj->getArchitecture() == 64) {
$pjsBin = $fileFact->getVendorFile("pjslinux64");
} elseif ($osObj->getArchitecture() == 32) {
$pjsBin = $fileFact->getVendorFile("pjslinux32");
} else {
throw new \Exception(__METHOD__ . ">> Phantomjs not available for OS Architecture: " . $osObj->getArchitecture());
}
$pjsCtrl = $fileFact->getVendorFile("pjsctrl");
$stdIn = $fileFact->getFile("stdIn", $workPath->getPathAsString());
$stdOut = $fileFact->getFile("stdOut", $workPath->getPathAsString());
$stdErr = $fileFact->getFile("stdErr", $workPath->getPathAsString());
$exeCmd = "\"" . $pjsBin->getPathAsString() . "\" --local-storage-path=\"".$workPath->getPathAsString()."\" --web-security=false --local-to-remote-url-access=true --ignore-ssl-errors=true --load-images=true \"" . $pjsCtrl->getPathAsString() . "\" \"".$workPath->getPathAsString() . DIRECTORY_SEPARATOR . "\"";
//on RHEL 7 the xterm TERM will show a duplicate PS1 command that cannot be removed, also added a sleep 2s before deleting the std files, that way the files exist on the termination read / write
$term = 'vt100';
$strCmd = "mkfifo ".$stdIn->getPathAsString()."; ( sleep 1000d > ".$stdIn->getPathAsString()." & ( export TERM=".$term."; SLEEP_PID=$! ; " . $exeCmd." < ".$stdIn->getPathAsString()." > ".$stdOut->getPathAsString()." 2> ".$stdErr->getPathAsString()."; sleep 2s; rm -rf ".$stdIn->getPathAsString()."; rm -rf ".$stdOut->getPathAsString()."; rm -rf ".$stdErr->getPathAsString()."; rm -rf ".$workPath->getPathAsString()."; kill -s TERM \$SLEEP_PID & ) & ) > /dev/null 2>&1";
//make the directory and out + err files
$fileFact->getFilesTool()->create($stdOut);
$fileFact->getFilesTool()->create($stdErr);
//execute the command
exec($strCmd);
$errObj = null;
try {
//sleep here so any error has time to be written to the stdErr file, the auto delete of error
//will not happen until a few sec after the process is terminated
usleep(10000);
clearstatcache(true, $stdErr->getPathAsString());
$fileFact->getFilesTool()->getContent($stdErr);
if ($stdErr->getContent() != "") {
throw new \Exception(__METHOD__ . ">> Failed to setup phantomJs on localHost Error: " . trim($stdErr->getContent()));
}
//if the server is busy it could take a bit to setup the shell
$maxWait = 30;
$eTime = time() + $maxWait;
$stdInOk = false;
while ($eTime > time()) {
$stdInOk = $fileFact->getFilesTool()->isFile($stdIn);
if ($stdInOk === true) {
break;
} else {
usleep(50);
}
}
if ($stdInOk !== true) {
throw new \Exception(__METHOD__ . ">> Failed to setup phantomJs on localHost stdIn was never created");
}
} catch (\Exception $e) {
switch($e->getCode()){
default;
$errObj = $e;
}
}
if ($errObj === null) {
//all good browser was created
$stdPipe = $fileFact->getProcessPipe($stdIn, $stdOut, $stdErr);
$pjsBrowser = new \MTS\Common\Devices\Browsers\PhantomJS();
$pjsBrowser->setPipes($stdPipe);
//this will init the browser if true
$pjsBrowser->setDebug($enableDebug);
return $pjsBrowser;
} else {
//clean up
$fileFact->getDirectoriesTool()->delete($workPath);
throw $errObj;
}
} else {
throw new \Exception(__METHOD__ . ">> Not able to setup browser of type: " . $browserName);
}
} elseif ($osObj->getType() == "Windows") {
if ($browserName == 'phantomjs') {
$fileFact = \MTS\Factories::getFiles();
$pipeUuid = uniqid();
$workPath = $fileFact->getDirectory(MTS_WORK_PATH . DIRECTORY_SEPARATOR . "LHB_" . $pipeUuid);
$stdIn = $fileFact->getFile("stdIn", $workPath->getPathAsString());
$stdOut = $fileFact->getFile("stdOut", $workPath->getPathAsString());
$stdErr = $fileFact->getFile("stdErr", $workPath->getPathAsString());
if ($osObj->getArchitecture() == 64) {
$pjsBin = $fileFact->getVendorFile("pjswindows64");
} elseif ($osObj->getArchitecture() == 32) {
$pjsBin = $fileFact->getVendorFile("pjswindows32");
} else {
throw new \Exception(__METHOD__ . ">> Phantomjs not available for OS Architecture: " . $osObj->getArchitecture());
}
$fileFact->getFilesTool()->create($stdIn);
$fileFact->getFilesTool()->create($stdOut);
$fileFact->getFilesTool()->create($stdErr);
$pjsCtrl = $fileFact->getVendorFile("pjsctrl");
$exeCmd = "\"" . $pjsBin->getPathAsString() . "\" --local-storage-path=\"".$workPath->getPathAsString()."\" --web-security=false --local-to-remote-url-access=true --ignore-ssl-errors=true --load-images=true \"" . $pjsCtrl->getPathAsString() . "\" \"".$workPath->getPathAsString() . DIRECTORY_SEPARATOR . "\" < \"".$stdIn->getPathAsString()."\" > \"".$stdOut->getPathAsString()."\" 2> \"".$stdErr->getPathAsString()."\"";
//the cmd width dictates the powershell width so we set it here
//wait 2 sec before deleting the files
$strCmd = "START \"seq\" cmd /c \"" . $exeCmd . " & ping -n 2 127.0.0.1 && rmdir /s /q \"" .$workPath->getPathAsString(). "\"\"";
//cannot get exec() to return without waiting for process to exit
//should get fixed since we dont want to depend on another function for MTS to run
pclose(popen($strCmd, "r"));
//do we need some validation the shell was created?
$errObj = null;
if ($errObj === null) {
//all good browser was created
$stdPipe = $fileFact->getProcessPipe($stdIn, $stdOut, $stdErr);
$pjsBrowser = new \MTS\Common\Devices\Browsers\PhantomJS();
$pjsBrowser->setPipes($stdPipe);
//this will init the browser if true
$pjsBrowser->setDebug($enableDebug);
return $pjsBrowser;
} else {
//clean up
$fileFact->getDirectoriesTool()->delete($workPath);
throw $errObj;
}
} else {
throw new \Exception(__METHOD__ . ">> Not able to setup browser of type: " . $browserName);
}
}
}
throw new \Exception(__METHOD__ . ">> Not Handled for Request Type: " . $requestType);
}
}