diff --git a/README.md b/README.md index fb9e4c8..9cbc1ef 100644 --- a/README.md +++ b/README.md @@ -8,23 +8,39 @@ Created by: [@mrjoelkemp](http://www.twitter.com/mrjoelkemp) ### Purpose I simply wanted an online repl that allowed me to -play with multiline scripts that explored various PHP apis. -There's already a console-based repl `php -a`, but it and many other +play with *multiline* scripts that explored various PHP apis. +There's already a console-based repl `php -a`, but it and many other console-based repls are not great for multiline snippets. I've used this quick hack a ton since building it. I hope you get some use out of it as well. -### Sandboxing +### Running it locally -The exposed `eval` is sandboxed at the server configuration layer +The online version of PHPepl is sandboxed. The exposed `eval` is sandboxed at the server configuration layer plus some blacklisting of methods at the application level via [PHP-Sandbox](https://github.com/fieryprophet/php-sandbox). -Close to 100 people use this REPL every day; don't ruin it for them. Please play nice. +This has, of course, crippled the tool and makes it not as useful – as whitelisting methods is a pain. +I recommend serving this app locally. + +To serve this application locally, you'll need a web server and PHP: + +* Mac: [MAMP](http://www.mamp.info/en/index.html) +* Windows: [WAMP](http://www.wampserver.com/en/) + +You can then point your apache server to serve files from the `/phpepl` root folder + +* Namely, you should be able to visit the app (`/phpepl/index.html`) from `http://localhost` (include a custom port if necessary) + +The app will automatically disable the sandbox and give you free reign over the REPL to +execute any commands. ### Contact Me If you hit any errors or if someone hacked the repl and it goes down, give me a shout on Twitter: [@mrjoelkemp](https://twitter.com/mrjoelkemp) +Close to 100 people use this REPL every day; don't ruin it for them. Please play nice. + +### License -License: MIT \ No newline at end of file +MIT \ No newline at end of file diff --git a/css/styles.css b/css/styles.css index 7a24c40..1f40f05 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1 +1 @@ -@-webkit-keyframes fade{0%{opacity:1}100%{opacity:0.25}}body{font-family:sans-serif}.container{width:75%;height:auto;margin:0 auto}.container .code{font-family:Courier}.container .header{width:100%;float:left;text-align:center;margin:0 0 5px 0}.container .header .title{width:100%;float:left}.container .header .title span{color:black;font-size:46px}.container .header .description{width:100%;float:left}.container .header .description span{color:black;font-size:17px;font-style:italic}.container .codebox{float:left;width:100%}.container .codebox .codebox-cont{width:80%;margin:0 auto}.container .codebox .codebox-cont #editor{font-size:17px;border:1px solid black;margin-bottom:10px}.container .codebox .codebox-cont #editor .CodeMirror{min-height:450px}.container .codebox .codebox-cont .output{float:left;width:100%;height:120px;position:relative;border:1px solid black;margin-bottom:10px;background-color:#eee;overflow:auto}.container .codebox .codebox-cont .output .spinner{position:absolute;display:none;top:8%;left:40%;width:100px;height:100px;margin:0 auto}.container .codebox .codebox-cont .output .spinner div{width:12%;height:26%;background:#000;position:absolute;left:44.5%;top:37%;opacity:0;-webkit-animation:fade 1s linear infinite;-webkit-border-radius:50px;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.2)}.container .codebox .codebox-cont .output .spinner div.bar1{-webkit-transform:rotate(0deg) translate(0, -142%);-webkit-animation-delay:0s}.container .codebox .codebox-cont .output .spinner div.bar2{-webkit-transform:rotate(30deg) translate(0, -142%);-webkit-animation-delay:-0.9167s}.container .codebox .codebox-cont .output .spinner div.bar3{-webkit-transform:rotate(60deg) translate(0, -142%);-webkit-animation-delay:-0.833s}.container .codebox .codebox-cont .output .spinner div.bar4{-webkit-transform:rotate(90deg) translate(0, -142%);-webkit-animation-delay:-0.75s}.container .codebox .codebox-cont .output .spinner div.bar5{-webkit-transform:rotate(120deg) translate(0, -142%);-webkit-animation-delay:-0.667s}.container .codebox .codebox-cont .output .spinner div.bar6{-webkit-transform:rotate(150deg) translate(0, -142%);-webkit-animation-delay:-0.5833s}.container .codebox .codebox-cont .output .spinner div.bar7{-webkit-transform:rotate(180deg) translate(0, -142%);-webkit-animation-delay:-0.5s}.container .codebox .codebox-cont .output .spinner div.bar8{-webkit-transform:rotate(210deg) translate(0, -142%);-webkit-animation-delay:-0.41667s}.container .codebox .codebox-cont .output .spinner div.bar9{-webkit-transform:rotate(240deg) translate(0, -142%);-webkit-animation-delay:-0.333s}.container .codebox .codebox-cont .output .spinner div.bar10{-webkit-transform:rotate(270deg) translate(0, -142%);-webkit-animation-delay:-0.25s}.container .codebox .codebox-cont .output .spinner div.bar11{-webkit-transform:rotate(300deg) translate(0, -142%);-webkit-animation-delay:-0.1667s}.container .codebox .codebox-cont .output .spinner div.bar12{-webkit-transform:rotate(330deg) translate(0, -142%);-webkit-animation-delay:-0.0833s}.container .codebox .codebox-cont .output .output-container{margin:5px 10px}.container .codebox .codebox-cont .output .output-container span{font-family:"Lucida Console", Monaco, monospace;color:black;font-size:16px}.container .codebox .codebox-cont .output .output-container span.error{color:red}.container .timestamp{height:21px;position:relative;text-align:right;right:-3px;top:-28px}.container .timestamp span{color:#888;font-size:15px;font-style:italic;margin-top:5px;margin-right:5px}.container .submit{width:100%;position:relative;float:left;text-align:center}.container .submit span{display:block;font-family:Courier;margin-bottom:5px}.container .submit button{width:150px;height:40px;cursor:pointer;border-radius:7px;border-top-radius:10px;-moz-border-radius-top:10px;-webkit-border-top-radius:10px;font-size:20px}.credits{width:100%;float:left;margin-top:5px;position:relative;text-align:center}.credits span,.credits a{font-style:italic;font-size:13px}.error-gutter{background-color:red} +@-webkit-keyframes fade{0%{opacity:1}100%{opacity:0.25}}body{font-family:sans-serif}.container{width:75%;height:auto;margin:0 auto}.container .code{font-family:Courier}.container .header{width:100%;float:left;text-align:center;margin:0 0 5px 0}.container .header .title{width:100%;float:left}.container .header .title span{color:black;font-size:46px}.container .header .description{width:100%;float:left}.container .header .description span{color:black;font-size:17px;font-style:italic}.container .codebox{float:left;width:100%}.container .codebox .codebox-cont{width:80%;margin:0 auto}.container .codebox .codebox-cont #editor{font-size:17px;border:1px solid black;margin-bottom:10px}.container .codebox .codebox-cont #editor .CodeMirror{min-height:450px}.container .codebox .codebox-cont .output{float:left;width:100%;height:120px;position:relative;border:1px solid black;margin-bottom:10px;background-color:#eee;overflow:auto}.container .codebox .codebox-cont .output .spinner{position:absolute;display:none;top:8%;left:40%;width:100px;height:100px;margin:0 auto}.container .codebox .codebox-cont .output .spinner div{width:12%;height:26%;background:#000;position:absolute;left:44.5%;top:37%;opacity:0;-webkit-animation:fade 1s linear infinite;-webkit-border-radius:50px;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.2)}.container .codebox .codebox-cont .output .spinner div.bar1{-webkit-transform:rotate(0deg) translate(0, -142%);-webkit-animation-delay:0s}.container .codebox .codebox-cont .output .spinner div.bar2{-webkit-transform:rotate(30deg) translate(0, -142%);-webkit-animation-delay:-0.9167s}.container .codebox .codebox-cont .output .spinner div.bar3{-webkit-transform:rotate(60deg) translate(0, -142%);-webkit-animation-delay:-0.833s}.container .codebox .codebox-cont .output .spinner div.bar4{-webkit-transform:rotate(90deg) translate(0, -142%);-webkit-animation-delay:-0.75s}.container .codebox .codebox-cont .output .spinner div.bar5{-webkit-transform:rotate(120deg) translate(0, -142%);-webkit-animation-delay:-0.667s}.container .codebox .codebox-cont .output .spinner div.bar6{-webkit-transform:rotate(150deg) translate(0, -142%);-webkit-animation-delay:-0.5833s}.container .codebox .codebox-cont .output .spinner div.bar7{-webkit-transform:rotate(180deg) translate(0, -142%);-webkit-animation-delay:-0.5s}.container .codebox .codebox-cont .output .spinner div.bar8{-webkit-transform:rotate(210deg) translate(0, -142%);-webkit-animation-delay:-0.41667s}.container .codebox .codebox-cont .output .spinner div.bar9{-webkit-transform:rotate(240deg) translate(0, -142%);-webkit-animation-delay:-0.333s}.container .codebox .codebox-cont .output .spinner div.bar10{-webkit-transform:rotate(270deg) translate(0, -142%);-webkit-animation-delay:-0.25s}.container .codebox .codebox-cont .output .spinner div.bar11{-webkit-transform:rotate(300deg) translate(0, -142%);-webkit-animation-delay:-0.1667s}.container .codebox .codebox-cont .output .spinner div.bar12{-webkit-transform:rotate(330deg) translate(0, -142%);-webkit-animation-delay:-0.0833s}.container .codebox .codebox-cont .output .output-container{margin:5px 10px}.container .codebox .codebox-cont .output .output-container span{font-family:"Lucida Console", Monaco, monospace;color:black;font-size:16px}.container .codebox .codebox-cont .output .output-container span.error{color:red}.container .timestamp{height:21px;position:relative;text-align:right;right:-3px;top:-28px}.container .timestamp span{color:#888;font-size:15px;font-style:italic;margin-top:5px;margin-right:5px}.container .submit{width:100%;position:relative;float:left;text-align:center;margin-bottom:3px}.container .submit span{display:block;font-family:Courier;margin-bottom:5px}.container .submit button{width:150px;height:40px;cursor:pointer;border-radius:7px;border-top-radius:10px;-moz-border-radius-top:10px;-webkit-border-top-radius:10px;font-size:20px}.fork-info{width:100%;text-align:center}.fork-info span{font-style:italic;font-size:12px}.credits{width:100%;float:left;margin-top:5px;position:relative;text-align:center}.credits span,.credits a{font-style:italic;font-size:13px}.error-gutter{background-color:red} diff --git a/css/styles.scss b/css/styles.scss index 41cb09b..fed92a0 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -55,7 +55,7 @@ body { .codebox-cont { width: 80%; margin: 0 auto; - #editor { + #editor { font-size: 17px; border: 1px solid black; margin-bottom: 10px; @@ -92,7 +92,7 @@ body { -webkit-animation: fade 1s linear infinite; -webkit-border-radius: 50px; -webkit-box-shadow: 0 0 3px rgba(0,0,0,0.2); - &.bar1 {-webkit-transform:rotate(0deg) translate(0, -142%); -webkit-animation-delay: 0s;} + &.bar1 {-webkit-transform:rotate(0deg) translate(0, -142%); -webkit-animation-delay: 0s;} &.bar2 {-webkit-transform:rotate(30deg) translate(0, -142%); -webkit-animation-delay: -0.9167s;} &.bar3 {-webkit-transform:rotate(60deg) translate(0, -142%); -webkit-animation-delay: -0.833s;} &.bar4 {-webkit-transform:rotate(90deg) translate(0, -142%); -webkit-animation-delay: -0.75s;} @@ -108,7 +108,7 @@ body { } .output-container{ margin: 5px 10px; - span { + span { font-family: "Lucida Console", Monaco, monospace; color: black; font-size: 16px; @@ -141,6 +141,7 @@ body { position: relative; float: left; text-align: center; + margin-bottom: 3px; span { display: block; font-family: Courier; @@ -157,7 +158,14 @@ body { } } - +.fork-info { + width: 100%; + text-align: center; + span { + font-style: italic; + font-size: 12px; + } +} .credits { width: 100%; diff --git a/eval/unsafe.php b/eval/unsafe.php new file mode 100644 index 0000000..d7f73df --- /dev/null +++ b/eval/unsafe.php @@ -0,0 +1,38 @@ +", " $result, + 'error' => $error + )); + + @ini_set('display_errors', $token); + @ini_set('log_errors', $inString); + + function getJsonOutput($options) { + $result = $options['result']; + $error = $options['error']; + return json_encode(array("result" => $result, "error" => $error)); + } +?> \ No newline at end of file diff --git a/index.haml b/index.haml index af0a554..d9a9117 100644 --- a/index.haml +++ b/index.haml @@ -8,7 +8,7 @@ %title PHPepl: The PHP REPL %link{:rel => "stylesheet", :href => "lib/codemirror/lib/codemirror.css?ver=3.18"} %link{:rel => "stylesheet", :href => "css/styles.css?ver=1.2"} - :javascript + :javascript var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-36055599-1']); _gaq.push(['_trackPageview']); @@ -18,13 +18,13 @@ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); - + (function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.increment people.append people.track_charge".split(" ");for(g=0;g"https://twitter.com/mrjoelkemp", :class=>"twitter-follow-button" } Follow @mrjoelkemp :javascript @@ -66,7 +68,7 @@ %script{:src => "lib/jquery-1.8.2.min.js"} %script{:src => "lib/codemirror/lib/codemirror.js?ver=3.18"} %script{:src => "lib/codemirror/addon/edit/closebrackets.js"} - + %script{:src => "lib/codemirror/addon/edit/matchbrackets.js"} %script{:src => "lib/codemirror/mode/htmlmixed/htmlmixed.js"} %script{:src => "lib/codemirror/mode/xml/xml.js"} @@ -74,9 +76,8 @@ %script{:src => "lib/codemirror/mode/css/css.js"} %script{:src => "lib/codemirror/mode/clike/clike.js"} %script{:src => "lib/codemirror/mode/php/php.js"} - + %script{:src => "lib/moment/moment.min.js"} / %script{:src => "scripts/phpepl.js"} %script{:src => "scripts/phpepl.min.js?ver=1.3"} - \ No newline at end of file diff --git a/index.html b/index.html index 7f2e465..0980f37 100644 --- a/index.html +++ b/index.html @@ -67,6 +67,9 @@ ⌘ + Enter or Ctrl + Enter +
+ Fork the project and serve locally for an unsandboxed experience +