Date: Thu, 10 Jul 2014 00:07:08 +0200
Subject: [PATCH 1/4] Add historic January 2014 submissions
---
solutions/Fox/README | 19 ++
solutions/Fox/bla.py | 7 +
solutions/Fox/foo.hs | 195 +++++++++++++++++++
solutions/Fox/foo.php | 3 +
solutions/Fox/foo.pl | 5 +
solutions/Fox/foo.py | 7 +
solutions/Fox/foo.rb | 6 +
solutions/Liothen/dcc.d | 27 +++
solutions/Liothen/dcc.rb | 32 +++
solutions/Mantis/dcc.php | 41 ++++
solutions/NeX/Bash/66.sh | 1 +
solutions/NeX/Bash/78.sh | 1 +
solutions/NeX/Bash/82.sh | 1 +
solutions/NeX/Python/dsdcc.py | 17 ++
solutions/Tempest/solution.html | 15 ++
solutions/d0gpants/DCCjan14.pl | 61 ++++++
solutions/infy/a.html | 1 +
solutions/infy/timed_product.html | 31 +++
solutions/infy/timed_product.php | 49 +++++
solutions/infy/timed_product.py | 29 +++
solutions/infy/timed_product.sh | 16 ++
solutions/infy/timed_product_busybox.sh | 26 +++
solutions/infy/timed_product_busybox_PoC.jpg | Bin 0 -> 224557 bytes
solutions/kurtisebear/products.py | 25 +++
solutions/majuscule/darkscience.sh | 39 ++++
solutions/majuscule/foo.sh | 1 +
solutions/whoami/dcc/__init__.py | 0
solutions/whoami/dcc/plugin.py | 25 +++
28 files changed, 680 insertions(+)
create mode 100644 solutions/Fox/README
create mode 100644 solutions/Fox/bla.py
create mode 100644 solutions/Fox/foo.hs
create mode 100644 solutions/Fox/foo.php
create mode 100755 solutions/Fox/foo.pl
create mode 100755 solutions/Fox/foo.py
create mode 100755 solutions/Fox/foo.rb
create mode 100644 solutions/Liothen/dcc.d
create mode 100644 solutions/Liothen/dcc.rb
create mode 100644 solutions/Mantis/dcc.php
create mode 100755 solutions/NeX/Bash/66.sh
create mode 100755 solutions/NeX/Bash/78.sh
create mode 100755 solutions/NeX/Bash/82.sh
create mode 100644 solutions/NeX/Python/dsdcc.py
create mode 100644 solutions/Tempest/solution.html
create mode 100755 solutions/d0gpants/DCCjan14.pl
create mode 100644 solutions/infy/a.html
create mode 100755 solutions/infy/timed_product.html
create mode 100755 solutions/infy/timed_product.php
create mode 100755 solutions/infy/timed_product.py
create mode 100755 solutions/infy/timed_product.sh
create mode 100755 solutions/infy/timed_product_busybox.sh
create mode 100755 solutions/infy/timed_product_busybox_PoC.jpg
create mode 100644 solutions/kurtisebear/products.py
create mode 100755 solutions/majuscule/darkscience.sh
create mode 100755 solutions/majuscule/foo.sh
create mode 100644 solutions/whoami/dcc/__init__.py
create mode 100644 solutions/whoami/dcc/plugin.py
diff --git a/solutions/Fox/README b/solutions/Fox/README
new file mode 100644
index 0000000..1c2a822
--- /dev/null
+++ b/solutions/Fox/README
@@ -0,0 +1,19 @@
+----------------------------------------------------------------------------------
+-- What does the Fox say? Fox'--
+-- ____ |\/| HTTP-Math-Fetch-Parse-Evaluate-Responder--
+-- \ /\ / ..__. --
+-- \/ \__\ _/ --
+-- \__ __ \ in Haskell--
+-- \____\___\ DarkScience Code Contest January--
+----------------------------------------------------------------------------------
+
+-- Implementations, in order of elegance:
+#1 Haskell implementation: ghc -o foo ./foo.hs
+#2 Perl implementation: ./foo.pl
+#3 Python implementation: ./foo.py
+#4 Ruby implementation: ./foo.rb
+#5 PHP implementation: ./foo.php
+#6 JS implementation: See ./foo.hs comments at the top of the file,
+ should run in JS console at DCC page.
+
+[*] Scuse, the Haskell implementation is not fully commented.
\ No newline at end of file
diff --git a/solutions/Fox/bla.py b/solutions/Fox/bla.py
new file mode 100644
index 0000000..dbb92f8
--- /dev/null
+++ b/solutions/Fox/bla.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python
+import requests
+import re
+import zlib
+import bz2
+u = 'http://directus.darkscience.net:6789/'
+print re.search('(Correct|Wrong)', requests.post(u, {'answer': eval(re.search('[0-9]+ x [0-9]+', requests.get(u).text).group(0).replace('x', '*'))}).text).group(0)
diff --git a/solutions/Fox/foo.hs b/solutions/Fox/foo.hs
new file mode 100644
index 0000000..44a9c65
--- /dev/null
+++ b/solutions/Fox/foo.hs
@@ -0,0 +1,195 @@
+----------------------------------------------------------------------------------
+-- What does the Fox say? Fox'--
+-- ____ |\/| HTTP-Math-Fetch-Parse-Evaluate-Responder--
+-- \ /\ / ..__. --
+-- \/ \__\ _/ --
+-- \__ __ \ in Haskell--
+-- \____\___\ DarkScience Code Contest January--
+----------------------------------------------------------------------------------
+
+-- Perl: eval "print LWP::UserAgent->new()->post('http://directus.darkscience.net:6789', {'answer' => $1*$2})->decoded_content() =~ /(Correct|Wrong)/g;\n" if get("http://directus.darkscience.net:6789") =~ /([0-9]+) x ([0-9]+)/g
+
+-- Python: print re.search('(Correct|Wrong)', requests.post(u, {'answer': eval(re.search('[0-9]+ x [0-9]+', requests.get(u).text).group(0).replace('x', '*'))}).text).group(0)
+
+-- PHP: ($u='http://directus.darkscience.net:6789/')&&!($a=array())&&preg_match('/[0-9]+ x [0-9]+/',file_get_contents($u),$a)&&(preg_match('(Correct|Wrong)',file_get_contents($u,false,stream_context_create(array('http'=>array('header'=>"Content-type: application/x-www-form-urlencoded\r\n",'method'=>'POST','content'=>http_build_query(array('answer'=>eval('return ('.str_replace('x','*',$a[0].');')))))))),$a)) && die(reset($a));
+
+-- JS: (x=new XMLHttpRequest)&&!x.open("GET","http://directus.darkscience.net:6789",false)&&!x.send(null)&&(r=/([0-9]+) x ([0-9]+)/g.exec(x.responseText))&&(a="answer="+eval(r[1]+"*"+r[2]))&&!x.open("POST","http://directus.darkscience.net:6789",false)&&!x.setRequestHeader("Content-type","application/x-www-form-urlencoded")&&!x.send(a)&&alert(/(Correct|Wrong)/.exec(x.responseText)[0])
+
+-- Ruby: (a, b = Net::HTTP.get(URI.parse("http://directus.darkscience.net:6789")).scan(/([0-9]+) x ([0-9]+)/)[0]) and print /(Correct|Wrong)/.match(Net::HTTP.post_form(URI.parse("http://directus.darkscience.net:6789"), {"answer" => (a.to_i.send '*', b.to_i)}).body)
+
+module Main
+where
+
+import Network.HTTP.Conduit
+import Network.HTTP.Types.Method
+import Control.Applicative
+import Text.Regex.Posix
+import Language.Haskell.Interpreter
+import Data.String.Utils
+import Data.Char
+
+import qualified Control.Exception as E
+
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.ByteString.Char8 as BS8
+
+-- Our input URL
+dccUrl = "http://directus.darkscience.net:6789/"
+
+-- Definition of our grammar
+data Expression
+data Operator = Plus -- We have support for Plus
+ | Minus -- Minus
+ | Multiplication -- Multiplication
+ | Division -- Division
+ deriving (Show, Eq)
+
+-- ^
+data Token = TokenOperator Operator -- We have an Operator token
+ | TokenAssign -- Assignment token
+ | TokenLeftParentheses -- Left parentheses
+ | TokenRightParentheses -- Right parentheses
+ | TokenIdentifier String -- Identifier
+ | TokenNumber Double -- Number
+ | TokenEnd -- End of expression
+ deriving (Show, Eq)
+
+-- ^
+data Tree = SumNode Operator Tree Tree -- A summation traverses into two trees
+ | ProductNode Operator Tree Tree -- A product traverses into two trees
+ | AssignNode String Tree -- An assignment traverses into one tree
+ | UnaryNode Operator Tree -- A unary traverses into one tree
+ | NumNode Double -- A number
+ | VarNode String -- A variable
+ deriving Show
+
+-- Convert an inputted Char to an Operator
+operator :: Char -> Operator
+operator c | c == '+' = Plus -- Plus => "+"
+ | c == '-' = Minus -- Minus => "-"
+ | c == 'x' = Multiplication -- Multiplication => "x"
+ | c == '/' = Division -- Division => "/"
+
+-- Tokenize an input string into a list of Tokens
+tokenize :: String -> [Token]
+tokenize [] = [] -- In case of an empty set, return an empty set
+tokenize (c : cs)
+ | elem c "+-x/" = TokenOperator (operator c) : tokenize cs -- If we've encountered one of "+-x/" fetch c as the operator, recursively work with the rest of the string
+ | isDigit c = number c cs -- In case of a digit, treat c as a number
+ | isSpace c = tokenize cs -- In case of a space, recursively work with the current string
+ | otherwise = error $ "Cannot tokenize " ++ [c] -- Else we have a problem
+
+-- This actually is a simply head operation, returning TokenEnd on empty list
+lookAhead :: [Token] -> Token
+lookAhead [] = TokenEnd -- Pattern match empty list, [], to reflect TokenEnd
+lookAhead (t:ts) = t -- Pattern match t as head, ts as tail, to reflect head
+
+-- This actually is a simple tail operation, returning an error on empty list
+accept :: [Token] -> [Token]
+accept [] = error "Nothing to accept" -- Pattern match empty list to trigger error
+accept (t:ts) = ts -- Pattern match t as head, ts as tail to reflect tail
+
+number :: Char -> [Char] -> [Token]
+number c cs =
+ let (digs, cs') = span isDigit cs in
+ TokenNumber (read (c : digs)) : tokenize cs'
+
+expression :: [Token] -> (Tree, [Token])
+expression toks =
+ let (termTree, toks') = term toks
+ in
+ case lookAhead toks' of
+ (TokenOperator op) | elem op [Plus, Minus] ->
+ let (exTree, toks'') = expression (accept toks')
+ in (SumNode op termTree exTree, toks'')
+ TokenAssign ->
+ case termTree of
+ VarNode str ->
+ let (exTree, toks'') = expression (accept toks')
+ in (AssignNode str exTree, toks'')
+ _ -> error "Assignment on non-variable!"
+ _ -> (termTree, toks')
+
+term :: [Token] -> (Tree, [Token])
+term toks =
+ let (facTree, toks') = factor toks
+ in
+ case lookAhead toks' of
+ (TokenOperator op) | elem op [Multiplication, Division] ->
+ let (termTree, toks'') = term (accept toks')
+ in (ProductNode op facTree termTree, toks'')
+ _ -> (facTree, toks')
+
+factor :: [Token] -> (Tree, [Token])
+factor toks =
+ case lookAhead toks of
+ (TokenNumber x) -> (NumNode x, accept toks) -- In case we've encountered a TokenNumber, x is NumNode, accept toks
+ (TokenIdentifier x) -> (VarNode x, accept toks) -- In case we've encountered a TokenIdentifier, x is VarNode, accept toks
+ (TokenOperator op) | elem op [Plus, Minus] -> -- In case we've encountered a TokenOperator,
+ let (facTree, toks') = factor (accept toks)
+ in (UnaryNode op facTree, toks')
+ TokenLeftParentheses ->
+ let (expTree, toks') = expression (accept toks)
+ in
+ if lookAhead toks' /= TokenRightParentheses
+ then error "Missing right parenthesis"
+ else (expTree, accept toks')
+ _ -> error $ "Syntax error on token: " ++ show toks -- Oops, syntax error!
+
+parse :: [Token] -> Tree
+parse toks = let (tree, toks') = expression toks
+ in
+ if null toks' -- Traverse the
+ then tree -- ^ tree
+ else error $ "Syntax error (left over token): " ++ show toks' -- Oops, syntax error!
+
+-- Evaluate a SumNode tree, reflect Double
+evaluate :: Tree -> Double
+evaluate (SumNode op left right) =
+ let lft = evaluate left
+ rgt = evaluate right
+ in
+ case op of
+ Plus -> lft + rgt
+ Minus -> lft - rgt
+
+-- Evaluate a ProductNode tree, reflect Double
+evaluate (ProductNode op left right) =
+ let lft = evaluate left
+ rgt = evaluate right
+ in
+ case op of
+ Multiplication -> lft * rgt
+ Division -> lft / rgt
+
+-- Evaluate a UnaryNode tree, reflect Double
+evaluate (UnaryNode op tree) =
+ let x = evaluate tree
+ in case op of
+ Plus -> x
+ Minus -> -x
+
+-- Evaluate a NumNode, reflect Number
+evaluate (NumNode x) = x
+
+-- Convert lazy ByteString to ByteString
+lazyToStrictBS :: LBS.ByteString -> BS.ByteString
+lazyToStrictBS x = BS.concat $ LBS.toChunks x
+
+-- Entry point
+main :: IO ()
+main = do
+ b <- simpleHttp dccUrl
+
+ let eq = (map (chr . fromIntegral) $ BS.unpack $ lazyToStrictBS b) =~ "[0-9]+ [+-x/] [0-9]+" :: String
+ let answer = show $ round $ evaluate $ parse $ tokenize eq
+
+ initReq <- parseUrl dccUrl
+ let request = (flip urlEncodedBody) initReq $ [(BS8.pack "answer", BS8.pack answer)]
+ res <- withManager $ httpLbs request
+ let result = (show $ lazyToStrictBS $ responseBody res) =~ "(Correct|Wrong)" :: String
+
+ print (eq ++ " = " ++ answer ++ " is " ++ result)
+
+ main
\ No newline at end of file
diff --git a/solutions/Fox/foo.php b/solutions/Fox/foo.php
new file mode 100644
index 0000000..0d123c1
--- /dev/null
+++ b/solutions/Fox/foo.php
@@ -0,0 +1,3 @@
+array('header'=>"Content-type: application/x-www-form-urlencoded\r\n",'method'=>'POST','content'=>http_build_query(array('answer'=>eval('return ('.str_replace('x','*',$a[0].');')))))))),$a)) && die(reset($a));
\ No newline at end of file
diff --git a/solutions/Fox/foo.pl b/solutions/Fox/foo.pl
new file mode 100755
index 0000000..e5e2e5b
--- /dev/null
+++ b/solutions/Fox/foo.pl
@@ -0,0 +1,5 @@
+#!/usr/bin/perl
+
+use LWP::Simple;
+
+eval "print LWP::UserAgent->new()->post('http://directus.darkscience.net:6789', {'answer' => $1*$2})->decoded_content() =~ /(Correct|Wrong)/g;\n" if get("http://directus.darkscience.net:6789") =~ /([0-9]+) x ([0-9]+)/g
\ No newline at end of file
diff --git a/solutions/Fox/foo.py b/solutions/Fox/foo.py
new file mode 100755
index 0000000..b6498c8
--- /dev/null
+++ b/solutions/Fox/foo.py
@@ -0,0 +1,7 @@
+import requests
+import re
+import zlib
+import bz2
+u = 'http://directus.darkscience.net:6789/'
+print re.search('(Correct|Wrong)', requests.post(u, {'answer': eval(re.search('[0-9]+ x [0-9]+', requests.get(u).text).group(0).replace('x', '*'))}).text).group(0)
+# Derecho: oeps shit weggehaald enzo
diff --git a/solutions/Fox/foo.rb b/solutions/Fox/foo.rb
new file mode 100755
index 0000000..790eaa4
--- /dev/null
+++ b/solutions/Fox/foo.rb
@@ -0,0 +1,6 @@
+#!/usr/bin/ruby
+
+require "net/http"
+require "uri"
+
+(a, b = Net::HTTP.get(URI.parse("http://directus.darkscience.net:6789")).scan(/([0-9]+) x ([0-9]+)/)[0]) and print /(Correct|Wrong)/.match(Net::HTTP.post_form(URI.parse("http://directus.darkscience.net:6789"), {"answer" => (a.to_i.send '*', b.to_i)}).body)
\ No newline at end of file
diff --git a/solutions/Liothen/dcc.d b/solutions/Liothen/dcc.d
new file mode 100644
index 0000000..286911a
--- /dev/null
+++ b/solutions/Liothen/dcc.d
@@ -0,0 +1,27 @@
+import std.net.curl, std.stdio, std.regex, std.string, std.algorithm, std.array, std.conv;
+
+void main() {
+ // Get HTML
+ auto html = get!HTTP("directus.darkscience.net:6789");
+ auto re = regex(r"\d+");
+ auto nums = matchAll(html, re).map!(a => a.front.to!size_t).array();
+ auto answer = nums[1] * nums[2];
+
+ // Post
+ auto client = HTTP();
+ client.addRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ string postme = text("answer=", answer);
+ auto post = post("directus.darkscience.net:6789", postme, client);
+
+ // Verify Correctness
+ auto post_result = "";
+ if (matchAll(post, r"\bCorrect\b")) {
+ post_result = "Correct!";
+ } else {
+ post_result = "Wrong!";
+ }
+
+ // Print Results
+ string response = format("Problem is %s + %s = %s (%s)",nums[1],nums[2],answer,post_result);
+ writeln(response);
+}
\ No newline at end of file
diff --git a/solutions/Liothen/dcc.rb b/solutions/Liothen/dcc.rb
new file mode 100644
index 0000000..271cef4
--- /dev/null
+++ b/solutions/Liothen/dcc.rb
@@ -0,0 +1,32 @@
+#!/usr/bin/env ruby
+########################
+### Requirements
+## Ruby
+## gem install mechanize
+########################
+# Setup
+require 'mechanize'
+agent = Mechanize.new
+
+# Open source site
+source = agent.get('http://directus.darkscience.net:6789/')
+
+# Find the problem, There are only two groups of numbers then convert the array returned into integers
+problem = source.at("p").to_html.scan(/\d+/).map!(&:to_i)
+
+# Grab the form from the source
+form = source.form()
+
+# Inject the answer
+form.answer = problem.inject(:*)
+
+# Submit and record result
+agent.submit(form, form.buttons.first)
+result = agent.submit(form, form.buttons.first)
+
+# Make pretty
+puts "Solution for #{problem.join(' x ')} is #{problem.inject(:*)} (#{result.at("body").content.to_s}!)"
+
+
+## Liothen
+### Still working on rust version but rust was compiling version 0.9 and i wanted to do something
\ No newline at end of file
diff --git a/solutions/Mantis/dcc.php b/solutions/Mantis/dcc.php
new file mode 100644
index 0000000..5c4241e
--- /dev/null
+++ b/solutions/Mantis/dcc.php
@@ -0,0 +1,41 @@
+ 'http://directus.darkscience.net:6789/',
+ CURLOPT_POST => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_POSTFIELDS => 'answer=' . $math_result,
+ ]);
+
+ $x = curl_exec($ch);
+
+ curl_close($ch);
+
+ echo (preg_match('/correct/i', $x) ? 'Correct' : 'Wrong');
+}
+?>
diff --git a/solutions/NeX/Bash/66.sh b/solutions/NeX/Bash/66.sh
new file mode 100755
index 0000000..278199f
--- /dev/null
+++ b/solutions/NeX/Bash/66.sh
@@ -0,0 +1 @@
+A=2509937211:6789;curl $A -danswer=`curl $A|awk '{print $12*$14}'`
diff --git a/solutions/NeX/Bash/78.sh b/solutions/NeX/Bash/78.sh
new file mode 100755
index 0000000..0637a47
--- /dev/null
+++ b/solutions/NeX/Bash/78.sh
@@ -0,0 +1 @@
+A=2509937211:6789;curl $A -danswer=`curl $A|awk '{print $12*$14}'`|cut -c81-87
diff --git a/solutions/NeX/Bash/82.sh b/solutions/NeX/Bash/82.sh
new file mode 100755
index 0000000..f06fdac
--- /dev/null
+++ b/solutions/NeX/Bash/82.sh
@@ -0,0 +1 @@
+A=2509937211:6789;curl $A -sdanswer=`curl -s $A|awk '{print $12*$14}'`|cut -c81-87
diff --git a/solutions/NeX/Python/dsdcc.py b/solutions/NeX/Python/dsdcc.py
new file mode 100644
index 0000000..b223c9f
--- /dev/null
+++ b/solutions/NeX/Python/dsdcc.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+import urllib2
+import urllib
+
+resp = urllib2.urlopen("http://directus.darkscience.net:6789/").read()
+i = resp.split().index("x")
+a = int(resp.split()[i-1])
+b = int(resp.split()[i+1])
+
+req = urllib2.Request("http://directus.darkscience.net:6789/",urllib.urlencode({'answer':a*b}))
+resp = urllib2.urlopen(req).read()
+
+if "Correct" in resp:
+ print "Correct! %d * %d = %d" % (a,b,a*b)
+else:
+ print "Incorrect :< Apparently %d * %d is not %d" % (a,b,a*b)
diff --git a/solutions/Tempest/solution.html b/solutions/Tempest/solution.html
new file mode 100644
index 0000000..e7384e6
--- /dev/null
+++ b/solutions/Tempest/solution.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/solutions/d0gpants/DCCjan14.pl b/solutions/d0gpants/DCCjan14.pl
new file mode 100755
index 0000000..de9001c
--- /dev/null
+++ b/solutions/d0gpants/DCCjan14.pl
@@ -0,0 +1,61 @@
+#!/usr/bin/perl
+
+$|=1; # because perl: buffer ALL the prints!
+
+use strict;
+use warnings;
+use Time::HiRes qw(usleep);
+use LWP::UserAgent;
+
+sub getFreshSum
+{
+ my ($host, $tmpsum, $ua) = @_;
+ my $resp = $ua->get($host);
+ if($resp->is_success)
+ {
+ my $page = $resp->decoded_content;
+ my @eqsplit = split(' ', $page);
+ my $sum = $eqsplit[11] * $eqsplit[13];
+ print("New: $sum : Old: $tmpsum\n");
+ print("Fresh!\n") if($sum != $tmpsum and $tmpsum);
+ usleep(200000); #results seem to vary per call but even though its single-threaded perl on a netbook
+ #it can be a tad floody without sleeping.
+ return getFreshSum($host, $sum, $ua) if(($tmpsum == $sum) or not $tmpsum);
+ # call getFreshSum again if value isn't fresh or first call, otherwise...
+ return $sum;
+ }
+ else
+ { die $resp->status_line }
+
+}
+
+sub postAnswer
+{
+ my ($host,$sum,$ua) = @_;
+ my $resp = $ua->post($host, {'answer' => $sum});
+ if($resp->is_success)
+ { return $resp->decoded_content }
+ else
+ { die $resp->status_line }
+
+}
+
+
+my $ua = LWP::UserAgent->new;
+$ua->timeout(10);
+$ua->env_proxy;
+
+my $host = "http://directus.darkscience.net:6789";
+my $sum = 0;
+my $resp = '';
+
+print("Getting fresh answer...\n");
+$sum = getFreshSum($host, $sum, $ua);
+
+print("\nPosting: $sum\n");
+$resp = postAnswer($host, $sum, $ua);
+
+if ($resp =~ m/Correct/)
+ { print("$sum was Correct. :>\n") }
+else
+ { print("$sum was Wrong.\n Either you are unlucky or you have a pants connection\n") }
diff --git a/solutions/infy/a.html b/solutions/infy/a.html
new file mode 100644
index 0000000..2a49661
--- /dev/null
+++ b/solutions/infy/a.html
@@ -0,0 +1 @@
+Dark Science Code Contest - January 2014What is the answer to 3586 x 541 ?