PDA

View Full Version : [Clojure] RS Loader



Echo_
07-14-2012, 09:02 PM
I was bored, so I decided to write an RS client loader in Clojure :)

web.clj

(ns loader.web
(:import (java.io BufferedReader InputStreamReader)
(java.net URL)))

(def session-pattern #"src=\"(.*)\" f")
(def archive-pattern #"archive=(.*)\s+code=(.*)\.class m")
(def param-pattern #"<param name=\"([^\s]+)\"\s+value=\"([^>]*)\">")

(defn- read-page [address]
(with-open [reader (BufferedReader. (InputStreamReader. (.openStream (URL. address))))]
(let [lines (line-seq reader)]
(reduce #(str %1 "\n" %2) lines))))

(defn- read-session [html]
(.trim (second (re-find session-pattern html))))

(defn- read-archive [html]
(let [archive (re-find archive-pattern html)]
{:jar (second archive) :code (last archive)}))

(defn- read-params [html]
(loop [matches (re-seq param-pattern html)
result {}]
(if (empty? matches)
result
(recur (rest matches) (assoc result (-> matches first second) (-> matches first last))))))

(defn read-info []
(let [page (read-page "http://www.runescape.com/game.ws?j=0")
session (read-session page)
frame (read-page session)
url (.substring session 0 (.indexOf session "/,"))
archive (read-archive frame)
parameters (read-params frame)]
(println " - Loaded" url)
(println " - SecretKeySpec =" (parameters "0"))
(println " - IvParameterSpec =" (parameters "-1"))
{:session url :archive archive :parameters parameters}))

gui.clj

(ns loader.gui
(:require [loader.web :as web])
(:import (java.applet Applet AppletStub)
(java.awt BorderLayout Dimension)
(java.net MalformedURLException URL URLClassLoader)
(javax.swing JFrame JPanel)))

(defn- create-loader [session parameters]
(proxy [JFrame AppletStub] []
(appletResize [width height])
(getAppletContext [] nil)
(getCodeBase [] (URL. session))
(getDocumentBase [] (.getCodeBase this))
(getParameter [name] (parameters name))
(isActive [] false)))

(defn init-loader []
(let [info (web/read-info)
loader (create-loader (info :session) (info :parameters))
class-loader (URLClassLoader. (into-array [(URL. (str (info :session) "/" (-> info :archive :jar)))]))
applet-class (.loadClass class-loader (-> info :archive :code))
#^Applet applet-loader (.newInstance applet-class)
game (JPanel. (BorderLayout.))]
(.setStub applet-loader loader)
(.setTitle loader "RuneScape")
(.setPreferredSize game (Dimension. 768 560))
(.setDefaultCloseOperation loader JFrame/EXIT_ON_CLOSE)
(.setSize loader 768 560)
(.init applet-loader)
(.start applet-loader)
(.add game applet-loader)
(.. loader getContentPane (add game BorderLayout/CENTER))
(.setVisible loader true)))

main.clj

(ns loader.main
(:require [loader.gui :as gui])
(:gen-class))

(defn -main [& args]
(gui/init-loader))

Obviously not the safest way to load the client, but that can be fixed. I also attached the Clojure source code and compiled classes, because it's fun to see how Clojure compiles to Java bytecode :p

eska
07-14-2012, 10:44 PM
First time I hear about "Clojure". Looks cool though.

Echo_
07-18-2012, 07:14 PM
First time I hear about "Clojure". Looks cool though.

It's an awesome language, I'd recommend it to anybody interested in concurrency or functional programming.

Hazzah
07-19-2012, 02:08 AM
Would this be compiled in Java and run through a .jar then?

Not actually understanding seeing as I am a noob at all things programming.

Echo_
07-19-2012, 04:06 PM
Would this be compiled in Java and run through a .jar then?

Not actually understanding seeing as I am a noob at all things programming.

Yes all you would need is the Clojure jar on your classpath and it runs exactly like any other java app. You can actually run the Clojure source as a script too if you don't feel like compiling it :)