package controllers; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.bson.types.ObjectId; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import net.vz.mongodb.jackson.DBQuery; import com.mongodb.BasicDBObject; import models.RecordedLocation; import models.TrackSession; import models.TrackedAction; import static play.libs.Json.toJson; import play.Play; import play.mvc.Controller; import play.mvc.Result; import play.mvc.Security; import setups.AppConfig; import utils.Base64; import utils.Tools; import views.html.preview.*; @Security.Authenticated(AdminSecurity.class) public class Preview extends Controller { public static Result view(String locId) { RecordedLocation.Model location; TrackedAction.Model firstAction; TrackSession.Model sess; try { location = RecordedLocation.coll.findOneById(locId); sess = TrackSession.coll.findOneById( location.sessionId ); firstAction = TrackedAction.coll.find( DBQuery.is("recLocId", new ObjectId( location._id ) ) ).limit(1).sort( new BasicDBObject("ts", 1) ).next(); } catch( Exception e) { return badRequest(); } return ok( view.render( sess, location, firstAction, TrackSession.getLocations( sess ), getDataString( location._id ) ) ); } public static Result download(String locId) { RecordedLocation.Model location; TrackedAction.Model firstAction; TrackSession.Model sess; try { location = RecordedLocation.coll.findOneById(locId); sess = TrackSession.coll.findOneById( location.sessionId ); firstAction = TrackedAction.coll.find( DBQuery.is("recLocId", new ObjectId( location._id ) ) ).limit(1).sort( new BasicDBObject("ts", 1) ).next(); } catch( Exception e) { return badRequest(); } String pageMap; pageMap = AppConfig.temporaryFilesDirectory + Tools.md5Encode(location.location)+".jpg"; File pmap = new File(pageMap); if( !(pmap.exists() && pmap.isFile() && new Date().getTime() - pmap.lastModified() < 86400000 ) ) { String command = AppConfig.pathToHtmlToImageGenerator + " " + location.location + " " + pageMap; try { System.out.println( command ); Process p = Runtime.getRuntime().exec( command ); p.waitFor(); } catch (IOException e) { e.printStackTrace(); return internalServerError(); } catch (InterruptedException e) { e.printStackTrace(); return internalServerError(); } } pmap = new File(pageMap); byte[] pmapBytes; try { pmapBytes = FileUtils.readFileToByteArray(pmap); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return internalServerError(); } InputStream previewJs = Play.application().resourceAsStream("/public/javascripts/preview.js"); String previewJsStr; InputStream jqueryJs = Play.application().resourceAsStream("/public/javascripts/jquery-1.7.1.min.js"); String jqueryJsStr; StringWriter writer; try { writer = new StringWriter(); IOUtils.copy(jqueryJs, writer); jqueryJsStr = writer.toString(); writer = new StringWriter(); IOUtils.copy(previewJs, writer); previewJsStr = writer.toString(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return internalServerError(); } String downloadIframe = download_iframe.render( utils.Base64.encode( pmapBytes ) ).toString(); try { String zipFileName = AppConfig.temporaryFilesDirectory + UUID.randomUUID().toString()+".zip"; ZipOutputStream out = new ZipOutputStream(new FileOutputStream( zipFileName ) ); out.putNextEntry(new ZipEntry("index.html")); byte[] byteArray = download.render( sess, location, firstAction, TrackSession.getLocations( sess ), getDataString( location._id ), jqueryJsStr + "\n" + previewJsStr ).toString().getBytes(); out.write(byteArray, 0, byteArray.length); out.putNextEntry(new ZipEntry("iframe.html")); byte[] byteArray1 = downloadIframe.getBytes(); out.write(byteArray1); // out.putNextEntry(new ZipEntry("site.jpg")); // out.write(pmapBytes); out.close(); response().setHeader("Content-Disposition", "attachment; filename=replay.zip"); return ok( new File( zipFileName ) ); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return internalServerError(); // return ok( download.render( sess, location, firstAction, TrackSession.getLocations( sess ), getDataString( location._id ), utils.Tools.base64Encode( downloadIframe ), jqueryJsStr + "\n" + previewJsStr ) ); } public static Result getData( String locId ) { List<Map<String, String>> data = new ArrayList<Map<String,String>>(); net.vz.mongodb.jackson.DBCursor<TrackedAction.Model> currsor = TrackedAction.coll.find(DBQuery.is("recLocId", new ObjectId( locId ) ) ).sort(new BasicDBObject("ts", 1) ); while(currsor.hasNext()) { TrackedAction.Model act = currsor.next(); HashMap<String, String> tmp = new HashMap<String, String>(); tmp.put("e", act.e+""); tmp.put("ts", act.ts+""); if( act.location != null && !act.location.isEmpty() ) tmp.put("location", act.location); if( act.d != null && !act.d.isEmpty() ) tmp.put("d", act.d); if( act.x != null && act.x >= 0 ) tmp.put("x", act.x+""); if( act.y != null && act.y >= 0 ) tmp.put("y", act.y+""); if( act.w != null && act.w >= 0 ) tmp.put("w", act.w+""); if( act.h != null && act.h >= 0 ) tmp.put("h", act.h+""); if( act.t != null && act.t >= 0 ) tmp.put("t", act.t+""); if( act.l != null && act.l >= 0 ) tmp.put("l", act.l+""); data.add(tmp); } return ok( toJson(data) ); } public static String getDataString( String locId ) { List<Map<String, String>> data = new ArrayList<Map<String,String>>(); net.vz.mongodb.jackson.DBCursor<TrackedAction.Model> currsor = TrackedAction.coll.find(DBQuery.is("recLocId", new ObjectId( locId ) ) ).sort(new BasicDBObject("ts", 1) ); while(currsor.hasNext()) { TrackedAction.Model act = currsor.next(); HashMap<String, String> tmp = new HashMap<String, String>(); tmp.put("e", act.e+""); tmp.put("ts", act.ts+""); if( act.location != null && !act.location.isEmpty() ) tmp.put("location", act.location); if( act.d != null && !act.d.isEmpty() ) tmp.put("d", act.d); if( act.x != null && act.x >= 0 ) tmp.put("x", act.x+""); if( act.y != null && act.y >= 0 ) tmp.put("y", act.y+""); if( act.w != null && act.w >= 0 ) tmp.put("w", act.w+""); if( act.h != null && act.h >= 0 ) tmp.put("h", act.h+""); if( act.t != null && act.t >= 0 ) tmp.put("t", act.t+""); if( act.l != null && act.l >= 0 ) tmp.put("l", act.l+""); data.add(tmp); } return toJson(data).toString(); } public static Result proxy(String locId) { RecordedLocation.Model location; TrackedAction.Model firstAction; try { location = RecordedLocation.coll.findOneById(locId); firstAction = TrackedAction.coll.find( DBQuery.is("recLocId", new ObjectId( location._id ) ) ).limit(1).sort( new BasicDBObject("ts", 1) ).next(); } catch( Exception e) { return badRequest(); } StringBuffer page = new StringBuffer(); Document doc; try { doc = Jsoup.connect( location.location ).get(); } catch( IOException e ) { //TODO: send tonification return internalServerError("IOException"); } //Fix Paths for(Element elem : doc.select("script")){ if( elem.attributes().hasKey("src") ) elem.attr("src", elem.absUrl("src")); else { if( elem.html().indexOf("we3cres") >= 0 && elem.html().indexOf("_we3ctr") >= 0 ) elem = elem.html(""); else if( elem.html().indexOf("google-analytics.com") >= 0 ) elem = elem.html(""); } } for(Element elem : doc.select("link")){ elem.attr("href", elem.absUrl("href")); } for(Element elem : doc.select("a")){ elem.attr("href", elem.absUrl("href")); } for(Element elem : doc.select("img")){ elem.attr("src", elem.absUrl("src")); } response().setHeader("Content-Type", "text/html; charset=utf-8"); return ok( doc.outerHtml() ); } public static Result getActions( String locId ) { return ok(); } }