Skip to content
This repository was archived by the owner on Jul 1, 2025. It is now read-only.

Commit fc59c1d

Browse files
authored
Upload SCS
1 parent ed6ad24 commit fc59c1d

File tree

1 file changed

+358
-0
lines changed

1 file changed

+358
-0
lines changed

scs

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
#!/usr/bin/php
2+
<?php
3+
#> curl xdotool diffutils colordiff wdiff
4+
5+
/* Source control utility. Backup/Restore files. Run actions on any change in a directory.
6+
* Create hard copies and display file diffs.
7+
* Verify content, ownserships and rights.
8+
* Can execute one -or more- commands, or reload a browser tab, at a file change.
9+
* Restore file on demand.
10+
* Automatize dev flow. Example, run a test script, or compile at a file change.
11+
* Recursive to the whole directory tree.
12+
* Backup all files versions, keeping the flow by timestamp.
13+
* Does not alter the dev target working dir.
14+
* Exclude git hidden files. Works well on top of git.
15+
* Can inject some javascript into a browser console tab, at a file change.
16+
*
17+
* PARAMS:
18+
* -e --exec <command> Execute command (Use quotes if necessary)
19+
* -r --reload <program> Reload target program (F5)
20+
* -x --inject <js file> javascript injection in browser console
21+
* --purge Delete cache
22+
* All params can be declared multiple times
23+
*
24+
* Browse GLOBAL historic and restore files
25+
* Those are all changes made in the whole machine, by date, while the current program was running
26+
* -g --global
27+
*
28+
*
29+
* * Browse DIR historic and restore files
30+
* Those are all changes made in the current DIR, by date, while the current program was running
31+
* -b --browse
32+
*
33+
* Examples:
34+
* # Reload focused tabs of many browsers
35+
* -r firefox -r chromium
36+
* # Run commands
37+
* ./scs -r firefox -e "ls -ltrapR"
38+
* # Inject alert("xss") in the currently focused Firefox tab
39+
* -x script.js
40+
*
41+
* Can be used on top of any text editor CTR+Z + Fat fingers = lost code
42+
*
43+
* */
44+
$path = getcwd();
45+
/* Avoid pipe errors */
46+
stream_set_blocking(STDIN, 0);
47+
/* Fully report errors*/
48+
error_reporting(E_ALL);
49+
/* Path target DIR */
50+
$crc = hash("crc32", $path);
51+
52+
/* Parse command line options */
53+
$com0 = $argv[0];
54+
$com1 = "rchange"; // @$argv[1];
55+
$com2 = @$argv[2]; // exec, reload, inject
56+
$com3 = @$argv[3]; // <browser>, command
57+
$com4 = @$argv[4];
58+
59+
/* Home path */
60+
$home = $_SERVER['HOME'];
61+
$params = $argv;
62+
63+
/* --purge : Delete backup DIR */
64+
if (@$params[1] === "--purge"){
65+
echo "Erasing cache.\n";
66+
//readline();
67+
exec("rm -rf ~/.scs/*");
68+
exit;
69+
}
70+
71+
/* Dispatch command line options */
72+
$FLAGPARAMS = ["commands" => [], "reloads" => [], "injects" => [], "historic" => []];
73+
foreach ($params as $k => $v){
74+
if ($v === "-e"){
75+
echo "Got commands\n";
76+
$FLAGPARAMS["commands"][] = $params[$k + 1];
77+
}
78+
if ($v === "-r"){
79+
echo "Got reloads\n";
80+
$FLAGPARAMS["reloads"][] = $params[$k + 1];
81+
}
82+
if ($v === "-x"){
83+
echo "Got injections\n";
84+
$FLAGPARAMS["injects"][] = $params[$k + 1];
85+
}
86+
if ($v === "-g" || $v === "--global"){
87+
echo "GLOBAL HISTORIC mode\n";
88+
$com1 = "history";
89+
}
90+
if ($v === "--setup"){
91+
echo "Installing\n";
92+
$com1 = "setup";
93+
}
94+
if ($v === "--purge"){
95+
$com1 = "purge";
96+
}
97+
if ($v === "-b" || $v === "--browse"){
98+
echo "Historic\n";
99+
if (!is_file("$home/.scs/index$crc")){echo "This directory has no backups\n";exit;}
100+
if (@$params[$k+1] != ""){
101+
echo "History of ".$params[$k+1]."\n";
102+
$FLAGPARAMS["historic"][] = $params[$k+1];
103+
} else {
104+
echo "History of $path\n";
105+
$FLAGPARAMS["historic"][] = $crc;
106+
}
107+
$com1 = "history";
108+
}
109+
}
110+
111+
/* The backup folder doesn't exist */
112+
if (!is_dir($_SERVER['HOME']."/.scs")){
113+
echo "Setting up ~/.scs\n";
114+
$com1 = "setup";
115+
}
116+
117+
/* Setup option */
118+
if ($com1 === "setup"){
119+
exec("mkdir -p ~/.scs && touch ~/.scs/ && cd ~/.scs ; touch ~/.scs/dif ~/.scs/sum ~/.scs/todif ~/.scs/ttodif ~/.scs/ttodif ~/.scs/hold");
120+
$com1 = "rchange";
121+
}
122+
123+
/* Max dir size copy [100mo] or ABORT */
124+
$maxdirsize = "100000"; // Bytes
125+
/* History array creation */
126+
$history = ["HELLO","WORLD!"];
127+
$iloop = 0;
128+
129+
function shutdown(){
130+
echo 'Success', PHP_EOL;
131+
}
132+
register_shutdown_function('shutdown');
133+
134+
/* Draw a separator line across the shell */
135+
function sep(){
136+
@ob_start();
137+
$shell = system("tput cols");
138+
@ob_end_clean();
139+
for( $i= 0 ; $i < $shell ; $i++ ){
140+
echo "";
141+
}
142+
};
143+
144+
/* The target DIR is over over $maxdirsize */
145+
@ob_start();
146+
$ts = (int)system("ls -ltr | head -n1 | cut -d' ' -f2");
147+
@ob_end_clean();
148+
if ($ts > $maxdirsize){
149+
echo "Hey this directory is full AF. Not suitable as a scs folder. Aborting.\n";
150+
exit;
151+
}
152+
153+
$iview = intval("1");
154+
/* History option */
155+
if ($com1 === "history"){
156+
$dirhash = "";
157+
$home = $_SERVER['HOME'];
158+
if ((count($FLAGPARAMS["historic"]) != 0) && is_file("$home/.scs/index$crc")){
159+
$dirhash = $FLAGPARAMS["historic"][0];
160+
}
161+
rdiff($iview,$dirhash);
162+
echo "\n";
163+
echo join(array_slice(file("$home/.scs/index$dirhash"), -12));
164+
HISTORY:
165+
echo "\n";
166+
sep();
167+
$store = file("$home/.scs/index$dirhash");
168+
$rep = readline("Before [b] | Next [n] | Restore [r]: ");
169+
$line = $store[count($store)-($iview)];
170+
$last = str_replace("~","home",$line);
171+
$last = explode("home",$last);
172+
$lastp1 = $home.trim($last[1]);
173+
$lastp2 = $home.trim($last[2]);
174+
$rpath = @explode("]", @explode("[",$line)[2])[0];
175+
$rpath = substr($rpath, 0, strlen($rpath));
176+
$subpath = join("/",array_slice(explode("/",$lastp2),6));
177+
$rpath = $path . "/" . $rpath.$subpath;
178+
//var_dump("cp '$lastp2' '$rpath'");
179+
echo "\033[1m".$subpath."\e[0m".PHP_EOL;
180+
$ls1 = system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif $lastp2 | egrep -v '\.$|\.\.|\.:|\.\/|total|^d'| sed '/^$/d' > $home/.scs/.lsbcopy1");
181+
$ls2 = system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif $rpath | egrep -v '\.$|\.\.|\.:|\.\/|total|^d'| sed '/^$/d' > $home/.scs/.lsbcopy2");
182+
@system("dwdiff -cbmagenta:black -C 0 -L '$home/.scs/.lsbcopy1' '$home/.scs/.lsbcopy2'");
183+
if ($iview < "1"){
184+
$iview = "1"; echo "\n---End of history---\n";
185+
}
186+
if ($rep === "b"){
187+
rdiff(($iview++)+1, $dirhash);
188+
}
189+
if ($rep === "n"){
190+
rdiff(($iview--)-1, $dirhash);
191+
}
192+
if ($rep === "r"){
193+
@ob_end_clean;
194+
echo "\033[1mcp -P '$lastp2' '$rpath'\e[0m\n";
195+
readline("Confirm copy? ");
196+
system("cp -P '$lastp2' '$rpath'");
197+
/* Hide stdout */
198+
@ob_start();
199+
/* Number of shell columns, for a nice progress bar */
200+
$shell = system("tput cols");
201+
/* Retake stdout as regular */
202+
@ob_end_clean();
203+
echo PHP_EOL;
204+
$i= 0;
205+
for( $i ; $i < 81; $i++ ){
206+
$hello = "\rFile replaced in $path . Your editor is going to display an alert!";
207+
if ($i === "79"){
208+
$i = "0";
209+
}
210+
$hello = str_split($hello);
211+
$hello[$i] = strtoupper($hello[$i]);
212+
echo implode($hello);
213+
usleep(30000); } /* <- Fast */
214+
}
215+
goto HISTORY;
216+
}
217+
218+
/* Diff files */
219+
function rdiff($me, $crc = ""){
220+
@ob_start;
221+
$home = $_SERVER['HOME'];
222+
if (count(file("$home/.scs/index$crc")) - $me <= 2){echo "No more diff found";return;}
223+
$store = file("$home/.scs/index$crc");
224+
$last = $store[count($store)-$me-1];
225+
$last = str_replace("~","home",$last);
226+
$last = explode("home",$last);
227+
$lastp1 = $home.trim($last[1]);
228+
$lastp2 = $home.trim($last[2]);
229+
@ob_end_clean;
230+
echo PHP_EOL;
231+
@system("dwdiff -c -C 0 -L '$lastp1' '$lastp2'");
232+
}
233+
234+
$dirWatch = $path;
235+
$dimd5 = system("ls -pl --time-style=full-iso -I '*.git' -I 'nohup.out' $path");
236+
$dirmd5 = md5($dimd5);
237+
/* Keep the hashes in an array, to create an historic */
238+
array_push($history, $dirmd5);
239+
/* RCHANGE, recursive into subfolders */
240+
if ($com1 === "rchange"){
241+
@ob_start();
242+
/* Necessary files and directory creation */
243+
exec("mkdir -p ~/.scs/$dirmd5 && cd ~/.scs/$dirmd5 ; touch dif sum todif ttodif ttodif hold history.json && touch ~/.scs/index && touch ~/.scs/index$crc");
244+
/* Save the directory md5 hash into a file */
245+
$dmd5 = system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif | egrep -v '\.$|\.\.|\.:|\.\/|total|^d' | sed '/^$/d'");
246+
file_put_contents("$home/.scs/$dirmd5/sum",md5($dmd5));
247+
/* Save the recursive ls output into a file */
248+
system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif | egrep -v '\.$|\.\.|\.:|\.\/|total|^d' | sed '/^$/d' > ~/.scs/$dirmd5/todif");
249+
@ob_end_clean();
250+
}
251+
@ob_start();
252+
$shell = intval(system("tput cols"));
253+
@ob_end_clean();
254+
echo "[+]\n";
255+
256+
/*Watcher loop */
257+
while(true){
258+
/* Slow down */
259+
usleep(700000);
260+
/* Hide stdout */
261+
@ob_start();
262+
if ($com1 === "rchange"){
263+
/* Save recursive ls output md5 */
264+
system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif | egrep -v '\.$|\.\.|\.:|\.\/|total|^d' | sed '/^$/d' | md5sum > ~/.scs/$dirmd5/hold");
265+
/* Create new md5 from php */
266+
$newmd5 = md5(system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif | egrep -v '\.$|\.\.|\.:|\.\/|total|^d' | sed '/^$/d'"));
267+
}
268+
@ob_end_clean();
269+
if ($com1 === "rchange"){
270+
$hello = " Watching changes";
271+
if (strlen($hello) === $iloop + 4){
272+
$iloop = "0";
273+
}
274+
$hello = str_split($hello);
275+
$iloop++;
276+
$hello[$iloop] = strtoupper($hello[$iloop]);
277+
echo "\r\r".implode($hello) . " in " . $path . "\r\r";
278+
$sum = file_get_contents("$home/.scs/$dirmd5/sum");
279+
$hold = file_get_contents("$home/.scs/$dirmd5/hold");
280+
// File changed
281+
if ($sum != $hold && $iloop > 3){
282+
@ob_start();
283+
$shell = system("tput cols");
284+
if ($com1 === "rchange"){
285+
system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif | egrep -v '\.$|\.\.|\.:|\.\/|total|^d' |sed '/^$/d' | md5sum > ~/.scs/$dirmd5/sum");
286+
system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif | egrep -v '\.$|\.\.|\.:|\.\/|total|^d' | sed '/^$/d' | md5sum > ~/.scs/$dirmd5/hold");
287+
system("ls --time-style=full-iso -ltrapR -I '*.git' -I 'nohup.out' -I sum -I todif -I hold -I dif -I ttodif -I tttodif | egrep -v '\.$|\.\.|\.:|\.\/|total|^d' | sed '/^$/d' > ~/.scs/$dirmd5/dif");
288+
}
289+
array_push($history, md5(system("cat ~/.scs/$dirmd5/hold")));
290+
$lastdif = end($history);
291+
$beforedif = $history[count($history)-2];
292+
$stack = json_encode($history);
293+
file_put_contents("$home/.scs/$dirmd5/history.json",$stack);
294+
$focus = system("find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d'/'");
295+
system("mkdir -p ~/.scs/$dirmd5/$lastdif && cp -R . ~/.scs/$dirmd5/$lastdif");
296+
@ob_end_clean();
297+
if (is_file("$home/.scs/$dirmd5/$beforedif/$focus") && is_file("$home/.scs/$dirmd5/$lastdif/$focus")){
298+
sep();
299+
echo PHP_EOL."@ ".date('D M j Y G:i:s');
300+
echo "\nFile change in $path\n";
301+
echo "\033[1m".$focus."\e[0m\n";
302+
@system("dwdiff -c -C 0 '$home/.scs/$dirmd5/todif' '$home/.scs/$dirmd5/dif'");
303+
echo str_repeat("-",$shell)."\n";
304+
@system("dwdiff -c -C 0 -L '$home/.scs/$dirmd5/$beforedif/$focus' '$home/.scs/$dirmd5/$lastdif/$focus'");
305+
echo str_repeat("-",$shell)."\n";
306+
}
307+
// Load history json file/
308+
$json = file_get_contents("$home/.scs/$dirmd5/history.json");
309+
$idx= file_get_contents("$home/.scs/index");
310+
$idxcrc = file_get_contents("$home/.scs/index$crc");
311+
// Decode json into array/
312+
@$stack_temp = json_decode($json);
313+
// Push md5 in history array/
314+
@array_push($stack_temp, md5(file_get_contents($com1)));
315+
// Encode back into json/
316+
@$stack = json_encode($stack_temp);
317+
// Save back history in historic/
318+
@file_put_contents("$home/.scs/$dirmd5/history.json",$stack);
319+
$indexline = "[".date("D M j G:i:s T Y")."] ~/.scs/$dirmd5/$beforedif/$focus"." ~/.scs/$dirmd5/$lastdif/$focus".PHP_EOL;
320+
@file_put_contents("$home/.scs/index",$indexline,FILE_APPEND);
321+
@file_put_contents("$home/.scs/index$crc",$indexline,FILE_APPEND);
322+
if ((count($FLAGPARAMS["reloads"]) != 0)){
323+
foreach ($FLAGPARAMS["reloads"] as $k=>$v){
324+
$firefox = system("xdotool search --name $v | tail -1");
325+
system("xdotool windowactivate $firefox");
326+
system("xdotool windowactivate --sync $firefox key F5");
327+
}
328+
}
329+
if ((count($FLAGPARAMS["commands"]) != 0)){
330+
foreach ($FLAGPARAMS["commands"] as $k=>$v){
331+
system("$v &");
332+
}
333+
}
334+
if ((count($FLAGPARAMS["injects"]) != 0)){
335+
foreach ($FLAGPARAMS["injects"] as $k=>$v){
336+
$pipe = file_get_contents($v);
337+
//$pipe = $v;
338+
var_dump($pipe );
339+
echo "Trying javascript injection\n$pipe \non: $com3\n";
340+
$firefox = system("xdotool search --name Firefox | tail -1");
341+
system("xdotool windowactivate $firefox");
342+
if ($pipe == " "){
343+
echo "\nWarning: STDIN empty\nSee help section(-h or --help)\n";
344+
}
345+
system("echo -n '$pipe' | xclip -selection clipboard > /scs/null");
346+
usleep(1000000);
347+
system("xdotool key ctrl+shift+E"); // open debugger
348+
usleep(1000000);
349+
system("xdotool key ctrl+shift+L"); // clear
350+
usleep(100000);
351+
system("xdotool key ctrl+v"); // paste
352+
usleep(100000);
353+
system("xdotool key Return"); // execute
354+
}
355+
}
356+
}
357+
}
358+
}

0 commit comments

Comments
 (0)