/* * 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.WebClient; 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.core.FacebookTask; import fbpwn.core.FacebookTaskState; import fbpwn.plugins.ui.CloseCircleFriendsDialog; import fbpwn.ui.FacebookGUI; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingUtilities; public class CloseCircleFriendsTask extends FacebookTask { private boolean searchPhotos = false; private boolean searchWallPosts = false; private int wallPages = 0; private int likePoint, commentPoint, tagPoint; private CloseCircleFriendsTask task; private String victimName; private ArrayList<CloseFriend> closeFriends; private ArrayList<String> checkedPosts; public CloseCircleFriendsTask(FacebookGUI FacebookGUI, FacebookAccount facebookProfile, AuthenticatedAccount authenticatedProfile, File workingDirectory) { super(FacebookGUI, facebookProfile, authenticatedProfile, workingDirectory); task = this; } public void setSearchPhotos(boolean SearchPhotos) { this.searchPhotos = SearchPhotos; } public void setSearchWallPosts(boolean SearchWallPosts) { this.searchWallPosts = SearchWallPosts; } public void setCommentPoint(int CommentPoint) { this.commentPoint = CommentPoint; } public void setLikePoint(int LikePoint) { this.likePoint = LikePoint; } public void setTagPoint(int TagPoint) { this.tagPoint = TagPoint; } @Override public boolean run() { try { setMessage("Initializing Module"); setTaskState(FacebookTaskState.Running); getFacebookGUI().updateTaskProgress(this); WebClient tempPage = getAuthenticatedProfile().getBrowser(); //determining search parameters try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { CloseCircleFriendsDialog dialog = new CloseCircleFriendsDialog(null, true, task); wallPages = dialog.ShowCloseCircleFriendsSelectionDialog(); } }); } catch (InterruptedException ex) { Logger.getLogger(AddVictimsFriends.class.getName()).log(Level.SEVERE, "Exception in thread: " + Thread.currentThread().getName(), ex); } catch (InvocationTargetException ex) { Logger.getLogger(AddVictimsFriends.class.getName()).log(Level.SEVERE, "Exception in thread: " + Thread.currentThread().getName(), ex); } String MobileWallPage = getFacebookTargetProfile().getProfilePageURL().replace("www", "m"); HtmlPage VictimWallPage = tempPage.getPage(MobileWallPage); //extracting victime's name victimName = VictimWallPage.getTitleText(); closeFriends = new ArrayList<CloseFriend>(); checkedPosts = new ArrayList<String>(); if (searchPhotos) { setMessage("Searching under Photos"); getFacebookGUI().updateTaskProgress(this); //getting albums links ArrayList<String> albums = getFacebookTargetProfile().getAlbumsURLs(); for (int i = 0; i < albums.size(); i++) { //searching in comments/likes/tags in each albums setMessage("Searching in Album " + (i + 1) + "/" + albums.size()); getFacebookGUI().updateTaskProgress(this); HtmlPage albumPage = tempPage.getPage(albums.get(i)); processAlbum(albumPage, tempPage); } } if (checkForCancel()) { for (int i = 0; i < closeFriends.size(); i++) { closeFriends.get(i).calculatePoints(commentPoint, tagPoint, likePoint); } SortCloseFriends(); //saving close friends to html file writeOutput(); return true; } if (searchWallPosts) { int index = 0; while (index != wallPages) { HtmlElement storiesArea = VictimWallPage.getElementById("m_stream_stories"); DomNodeList<HtmlElement> anchors = storiesArea.getElementsByTagName("a"); for (int i = 0; i < anchors.size(); i++) { if (anchors.get(i).getAttribute("class").equals("sec") && anchors.get(i).getTextContent().contains("Comments") && !checkedPosts.contains("http://m.facebook.com" + anchors.get(i).getAttribute("href"))) { HtmlPage postPage = tempPage.getPage("http://m.facebook.com" + anchors.get(i).getAttribute("href")); processPost(postPage, tempPage); checkedPosts.add("http://m.facebook.com" + anchors.get(i).getAttribute("href")); } } try { VictimWallPage = VictimWallPage.getAnchorByText("See More Posts").click(); } catch (Exception ex) { break; } setMessage("Searching in " + (index + 1) + "/" + (wallPages == -1 ? "all" : wallPages) + " Wall page(s)"); if (wallPages != -1) { setPercentage(((double) (index + 1) / wallPages) * 100); } getFacebookGUI().updateTaskProgress(this); if (checkForCancel()) { for (int i = 0; i < closeFriends.size(); i++) { closeFriends.get(i).calculatePoints(commentPoint, tagPoint, likePoint); } SortCloseFriends(); //saving close friends to html file writeOutput(); return true; } index++; } } //calculating each close friend points setMessage("Calculating each friend points"); setPercentage(0.0); getFacebookGUI().updateTaskProgress(this); for (int i = 0; i < closeFriends.size(); i++) { closeFriends.get(i).calculatePoints(commentPoint, tagPoint, likePoint); } SortCloseFriends(); //saving close friends to html file writeOutput(); } catch (IOException ex) { Logger.getLogger(DictionaryBuilderTask.class.getName()).log(Level.SEVERE, null, ex); } catch (FailingHttpStatusCodeException ex) { Logger.getLogger(DictionaryBuilderTask.class.getName()).log(Level.SEVERE, null, ex); } setMessage("Finished"); setTaskState(FacebookTaskState.Finished); setPercentage(100.0); getFacebookGUI().updateTaskProgress(this); return true; } private void writeOutput() { PrintWriter pw = null; try { pw = new PrintWriter(new File(getDirectory().getAbsolutePath() + System.getProperty("file.separator") + "CloseFriends.html"), "UTF-8"); setMessage("Writing close friends to HTML file"); setPercentage(0.0); getFacebookGUI().updateTaskProgress(this); pw.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"); pw.println("<html>"); pw.println("<head>"); pw.println(); pw.println("<meta http-equiv = \"Content-Type\" content = \"text/html; charset=UTF-8\">"); pw.println(); pw.println("</head>"); pw.println("<body>"); pw.println("<div align=\"center\">"); pw.println("<table border=\"1\">"); for (int i = 0; i < closeFriends.size(); i++) { pw.println("<tr>"); pw.println("<td>"); pw.println("<a href=\"" +closeFriends.get(i).getAccount().getProfilePageURL() + "\">" + closeFriends.get(i).getAccount().getName() + "<//a>"); pw.println("</td>"); pw.println("<td>"); pw.println("Comments = " + closeFriends.get(i).getComments() + "<br>Tags = " + closeFriends.get(i).getTags() + "<br>Likes = " + closeFriends.get(i).getLikes() + "<br>Total Points = " + closeFriends.get(i).getPoints()); pw.println("</td>"); pw.println("</tr>"); } pw.println("</table>"); pw.println("</div>"); pw.println("</body>"); pw.println("</html>"); pw.flush(); pw.close(); } catch (FileNotFoundException ex) { Logger.getLogger(CloseCircleFriendsTask.class.getName()).log(Level.SEVERE, null, ex); } catch (UnsupportedEncodingException ex) { Logger.getLogger(CloseCircleFriendsTask.class.getName()).log(Level.SEVERE, null, ex); } finally { pw.close(); } } private void processAlbum(HtmlPage albumPage, WebClient webClient) 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("contentArea"); anchors = body.getElementsByTagName("a"); for (int j = 0; j < anchors.size(); j++) { if (anchors.get(j).getAttribute("href").contains("fbid")) { photos.add(anchors.get(j).getAttribute("href").replace("www", "m")); } } //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()) { //calculating and sorting for (int i = 0; i < closeFriends.size(); i++) { closeFriends.get(i).calculatePoints(commentPoint, tagPoint, likePoint); } SortCloseFriends(); //saving close friends to text file PrintWriter pw = new PrintWriter(new File(getDirectory().getAbsolutePath() + System.getProperty("file.separator") + "CloseFriends.txt"), "UTF-8"); for (int i = 0; i < closeFriends.size(); i++) { pw.println(closeFriends.get(i).getAccount().getName() + "|Comments = " + closeFriends.get(i).getComments() + "|Tags = " + closeFriends.get(i).getTags() + "|Likes = " + closeFriends.get(i).getLikes() + "|Total Points = " + closeFriends.get(i).getPoints()); } pw.flush(); pw.close(); return; } } //harvesting comments under images in dictionary for (int j = 0; j < photos.size(); j++) { //opening Image Page that containg it's comments HtmlPage photoPage = getAuthenticatedProfile().getBrowser().getPage(photos.get(j)); processPost(photoPage, webClient); checkedPosts.add(photos.get(j)); setPercentage((double) (j + 1) / photos.size() * 100); getFacebookGUI().updateTaskProgress(this); if (checkForCancel()) { //calculating and sorting for (int i = 0; i < closeFriends.size(); i++) { closeFriends.get(i).calculatePoints(commentPoint, tagPoint, likePoint); } SortCloseFriends(); //saving close friends to text file PrintWriter pw = new PrintWriter(new File(getDirectory().getAbsolutePath() + System.getProperty("file.separator") + "CloseFriends.txt"), "UTF-8"); for (int i = 0; i < closeFriends.size(); i++) { pw.println(closeFriends.get(i).getAccount().getName() + "|Comments = " + closeFriends.get(i).getComments() + "|Tags = " + closeFriends.get(i).getTags() + "|Likes = " + closeFriends.get(i).getLikes() + "|Total Points = " + closeFriends.get(i).getPoints()); } pw.flush(); pw.close(); return; } } } private void processPost(HtmlPage postPage, WebClient webClient) throws IOException { DomNodeList<HtmlElement> divisions = postPage.getElementsByTagName("div"); for (int i = 0; i < divisions.size(); i++) { //checking for comments division if (divisions.get(i).getAttribute("class").equals("row aclb apl")) { String profileName = divisions.get(i).getFirstChild().getFirstChild().getTextContent(); String profileURL = "http://www.facebook.com" + divisions.get(i).getElementsByTagName("a").get(0).getAttribute("href"); //saving new friend to victim's close friends if (profileName.equals(victimName)) { continue; } CloseFriend closeFriend = searchForFriend(profileName); if (closeFriend != null) { closeFriend.incrementComments(); } else { FacebookAccount friend = new FacebookAccount(profileURL, webClient); friend.setName(profileName); closeFriend = new CloseFriend(friend); closeFriend.incrementComments(); closeFriends.add(closeFriend); } } //checking for photo tags division if (divisions.get(i).getAttribute("class").equals("acw apl")) { if (divisions.get(i).getFirstChild().getTextContent().contains("with")) { DomNodeList<HtmlElement> tagsDivision = divisions.get(i).getElementsByTagName("div"); DomNodeList<HtmlElement> tagsProfiles = tagsDivision.get(0).getElementsByTagName("span"); //extracting all friends tagged with victim for (int k = 1; k < tagsProfiles.size(); k++) { String profileName = tagsProfiles.get(k).getTextContent(); String ProfileURL = "http://www.facebook.com" + tagsProfiles.get(k).getElementsByTagName("a").get(0).getAttribute("href"); if (profileName.equals(victimName)) { continue; } CloseFriend closeFriend = searchForFriend(profileName); if (closeFriend != null) { closeFriend.incrementTags(); } else { FacebookAccount friend = new FacebookAccount(ProfileURL, webClient); friend.setName(profileName); closeFriend = new CloseFriend(friend); closeFriend.incrementTags(); closeFriends.add(closeFriend); } } } } // checking for likes on photo division if (divisions.get(i).getAttribute("class").equals("likes row aclb apm")) { if (!divisions.get(i).getTextContent().contains("people") && !divisions.get(i).getTextContent().contains("and")) { String profileName = divisions.get(i).getTextContent().replace(" likes this.", ""); String profileURL = "http://www.facebook.com" + divisions.get(i).getElementsByTagName("a").get(0).getAttribute("href"); if (profileName.equals(victimName)) { continue; } CloseFriend closeFriend = searchForFriend(profileName); if (closeFriend != null) { closeFriend.incrementLikes(); } else { FacebookAccount friend = new FacebookAccount(profileURL, webClient); friend.setName(profileName); closeFriend = new CloseFriend(friend); closeFriend.incrementLikes(); closeFriends.add(closeFriend); } } } } //checking for likes on each comments on photo division List<HtmlAnchor> photoAnchors = postPage.getAnchors(); for (int i = 0; i < photoAnchors.size(); i++) { //extracting likes links if (photoAnchors.get(i).getHrefAttribute().contains("/browse/likes/")) { HtmlPage likesPage = photoAnchors.get(i).click(); List<HtmlAnchor> likesAnchors = likesPage.getAnchors(); for (int k = 1; k < likesAnchors.size(); k++) { //extracting profiles with likes on comments if (!likesAnchors.get(k).getTextContent().contains("Add")) { String profileName = likesAnchors.get(k).getTextContent(); String profileURL = "http://www.facebook.com" + likesAnchors.get(k).getHrefAttribute(); if (profileName.equals(victimName)) { continue; } CloseFriend closeFriend = searchForFriend(profileName); if (closeFriend != null) { closeFriend.incrementLikes(); } else { FacebookAccount friend = new FacebookAccount(profileURL, webClient); friend.setName(profileName); closeFriend = new CloseFriend(friend); closeFriend.incrementLikes(); closeFriends.add(closeFriend); } } } } } } /* * search for friends inside the list of close friends by name */ private CloseFriend searchForFriend(String friendName) { for (int i = 0; i < closeFriends.size(); i++) { if (closeFriends.get(i).getAccount().getName().equals(friendName)) { return closeFriends.get(i); } } return null; } private void SortCloseFriends() { Collections.sort(closeFriends, new Comparator<CloseFriend>() { @Override public int compare(CloseFriend arg0, CloseFriend arg1) { if (arg0.getPoints() < arg1.getPoints()) { return 1; } else if (arg0.getPoints() == arg1.getPoints()) { return 0; } else { return -1; } } }); } @Override public void init() { } @Override public String toString() { return "Find close friends"; } } class CloseFriend { private FacebookAccount account; private int Likes; private int Comments; private int Tags; private int Points; public CloseFriend(FacebookAccount account) { this.account = account; Likes = 0; Comments = 0; Tags = 0; Points = 0; } public void incrementLikes() { Likes++; } public void incrementComments() { Comments++; } public void incrementTags() { Tags++; } public void setPoints(int Points) { this.Points = Points; } public int getComments() { return Comments; } public int getLikes() { return Likes; } public int getPoints() { return Points; } public int getTags() { return Tags; } public FacebookAccount getAccount() { return account; } public void calculatePoints(int CommentPoint, int TagPoint, int LikePoint) { Points = (Comments * CommentPoint) + (Tags * TagPoint) + (Likes * LikePoint); } }