Permalink
Browse files

completed implementation of webfinger plus publishing of hcards

  • Loading branch information...
1 parent 0038564 commit 0c8880a25772bb88733cd9f6cf5632d1ab20d86d dcheng committed Mar 7, 2011
@@ -197,6 +197,50 @@ private void setConnectionProperties() {
private void prepareFolders() {
prepareTempFolder();
prepareUploadFolder();
+ prepareWebfingerAccountsFolder();
+ prepareWebfingerProfilesFolder();
+ }
+
+ private void prepareWebfingerAccountsFolder(){
+ final String accountsPath = JiveGlobals.getProperty("onesocialweb.webfinger.accounts");
+ if (accountsPath != null) {
+ File accountsFolder = new File(accountsPath);
+ if (accountsFolder.exists() && accountsFolder.canWrite()) {
+ return;
+ }
+ JiveGlobals.deleteProperty("onesocialweb.webfinger.accounts");
+ Log.error("Specified upload folder does not exist or read-only (" + accountsPath + ")");
+ }
+
+ File accountsFolder = new File(pluginDirectory, "accounts");
+ if (!accountsFolder.exists()) {
+ if (accountsFolder.mkdirs() && accountsFolder.canWrite()) {
+ Log.info("Created the upload folder at " + accountsFolder.getAbsolutePath());
+ JiveGlobals.setProperty("onesocialweb.webfinger.accounts", accountsFolder.getAbsolutePath());
+ }
+ }
+ }
+
+ private void prepareWebfingerProfilesFolder(){
+ final String profilesPath = JiveGlobals.getProperty("onesocialweb.webfinger.profiles.path");
+ if (profilesPath != null) {
+ File profilesFolder = new File(profilesPath);
+ if (profilesFolder.exists() && profilesFolder.canWrite()) {
+ return;
+ }
+ JiveGlobals.deleteProperty("onesocialweb.webfinger.profiles.path");
+ Log.error("Specified upload folder does not exist or read-only (" + profilesPath + ")");
+ }
+
+ File profilesFolder = new File(pluginDirectory, "profiles");
+ if (!profilesFolder.exists()) {
+ if (profilesFolder.mkdirs() && profilesFolder.canWrite()) {
+ Log.info("Created the upload folder at " + profilesFolder.getAbsolutePath());
+ JiveGlobals.setProperty("onesocialweb.webfinger.profiles.path", profilesFolder.getAbsolutePath());
+ }
+ }
+
+
}
private void prepareUploadFolder() {
@@ -0,0 +1,182 @@
+package org.onesocialweb.openfire.web;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jivesoftware.admin.AuthCheckFilter;
+import org.jivesoftware.openfire.XMPPServer;
+import org.jivesoftware.openfire.user.UserNotFoundException;
+import org.jivesoftware.util.JiveGlobals;
+import org.jivesoftware.util.Log;
+import org.onesocialweb.model.acl.AclAction;
+import org.onesocialweb.model.acl.AclFactory;
+import org.onesocialweb.model.acl.AclRule;
+import org.onesocialweb.model.acl.AclSubject;
+import org.onesocialweb.model.vcard4.Field;
+import org.onesocialweb.model.vcard4.Profile;
+import org.onesocialweb.model.vcard4.exception.CardinalityException;
+import org.onesocialweb.model.vcard4.exception.UnsupportedFieldException;
+import org.onesocialweb.model.xml.hcard.HCardWriter;
+import org.onesocialweb.openfire.OswPlugin;
+import org.onesocialweb.openfire.model.acl.PersistentAclFactory;
+import org.onesocialweb.openfire.model.vcard4.PersistentProfile;
+
+@SuppressWarnings("serial")
+public class HCardServlet extends HttpServlet {
+
+ private static int BUFFSIZE = 64000;
+ private AclFactory aclFactory;
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) {
+ try{
+ doProcess(request, response);
+ }catch (UserNotFoundException e){
+ //manage the exception nicely, please ...
+ }
+ catch (IOException ioe){
+ //manage the exception nicely, please ...
+ }
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) {
+ try{
+ doProcess(request, response);
+ }
+ catch (UserNotFoundException e){
+ //manage the exception nicely, please ...
+ }
+ catch (IOException ioe){
+ //manage the exception nicely, please ...
+ }
+ }
+
+
+ private void doProcess(HttpServletRequest request, HttpServletResponse response) throws UserNotFoundException, IOException{
+ String username = request.getParameter("u");
+ String profilesPath= JiveGlobals.getProperty("onesocialweb.webfinger.profiles.path");
+
+ /* if (profileExists(profilesPath, username)){
+ serveFile(response, profilesPath, username);
+ }
+ else { */
+ Profile publicProfile= getPublicProfile(username + "@" + XMPPServer.getInstance().getServerInfo().getXMPPDomain());
+ HCardWriter writer = new HCardWriter();
+
+ String hCardHTML=writer.buildProfilePage(publicProfile, username, profilesPath);
+ serveFile(response, hCardHTML);
+ //write the html file to disc
+ //serve the location
+ // }
+ }
+
+ private void serveFile(HttpServletResponse response, String hCardHTML){
+
+ try{
+
+ // Send the headers
+ response.setContentType("text/html");
+ // Stream the file
+ //final byte[] bbuf = new byte[BUFFSIZE];
+ final OutputStream os = response.getOutputStream();
+
+ os.write(hCardHTML.getBytes());
+ os.flush();
+ os.close();
+ }
+
+ catch (IOException ioe){
+ Log.error("error serving the hcard");
+
+ }
+ }
+
+ public boolean profileExists(String profilePath, String username){
+ //find the profile file
+ String fileLoc=profilePath+ "/"+username+ ".html";
+ File f = new File(fileLoc);
+ if (f.exists()) return true;
+ else return false;
+ }
+
+ public Profile getPublicProfile(String targetJID) throws UserNotFoundException {
+
+
+ final EntityManager em = OswPlugin.getEmFactory().createEntityManager();
+ PersistentProfile profile = em.find(PersistentProfile.class, targetJID);
+ em.close();
+ if (profile != null) {
+
+ // We should filter all fields that are not public
+
+
+ final AclAction viewAction = aclFactory.aclAction(AclAction.ACTION_VIEW, AclAction.PERMISSION_GRANT);
+ List<Field> fields =profile.getFields();
+ List<Field> canSeefields= new ArrayList<Field>();
+ for (Field field: fields)
+ {
+ boolean canSee=false;
+ List<AclRule> rules= field.getAclRules();
+ //this is a patch, so that the profile and its fields can be retrieved even when the acl rules where not set...
+ // currently the vodafonernd.com DB has many profiles without any ACL rules, which retrieves empty profiles...
+ if (rules.isEmpty())
+ canSee=true;
+ for (AclRule rule: rules)
+ {
+ if ((rule.hasAction(viewAction)) && (isPublic(rule)))
+ canSee=true;
+ }
+ if (canSee)
+ canSeefields.add(field);
+ }
+
+ profile.removeAll();
+ try{
+ for (Field f: canSeefields){
+ f.setAclRules(new ArrayList<AclRule>());
+ profile.addField(f);
+ }
+ }catch (CardinalityException ce){
+ }catch (UnsupportedFieldException ufe){
+ }
+ return profile;
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ aclFactory = new PersistentAclFactory();
+
+ AuthCheckFilter.addExclude("osw-openfire-plugin");
+ AuthCheckFilter.addExclude("osw-openfire-plugin/profiles/");
+ AuthCheckFilter.addExclude("osw-openfire-plugin/profiles");
+ }
+
+ public boolean isPublic(AclRule rule){
+
+ final List<AclSubject> subjects = rule.getSubjects();
+ for (AclSubject aclSubject : subjects) {
+ if (aclSubject.getType().equals(AclSubject.EVERYONE)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
@@ -0,0 +1,125 @@
+package org.onesocialweb.openfire.web;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jivesoftware.admin.AuthCheckFilter;
+import org.jivesoftware.openfire.XMPPServer;
+import org.jivesoftware.util.JiveGlobals;
+import org.jivesoftware.util.Log;
+import org.onesocialweb.xml.dom.XrdWriter;
+
+@SuppressWarnings("serial")
+public class WebfingerServlet extends HttpServlet{
+
+ private static int BUFFSIZE = 64000;
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) {
+ doProcess(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) {
+ doProcess(request, response);
+ }
+
+ private void doProcess(HttpServletRequest request, HttpServletResponse response){
+ try{
+ String jid = request.getParameter("q");
+ if (jid==null){
+ PrintWriter out = response.getWriter();
+ out.println("Please specify a valid account on this domain");
+ return;
+ }
+ else{
+ if (jid.startsWith("acct:"))
+ jid=jid.substring(5);
+ }
+
+ String accountsPath = JiveGlobals.getProperty("onesocialweb.webfinger.accounts");
+ String profilesUrl= JiveGlobals.getProperty("onesocialweb.webfinger.profiles.url");
+ if (profilesUrl== null){
+ profilesUrl=XMPPServer.getInstance().getServerInfo().getXMPPDomain()+"/profiles";
+ }
+
+ //validate the jid here ...
+
+ if (xrdExists(accountsPath, jid)){
+ serveFile(response, accountsPath, jid);
+ }
+ else {
+ XrdWriter writer = new XrdWriter();
+ writer.writeAccount(jid, accountsPath, profilesUrl);
+ serveFile(response, accountsPath, jid);
+ //write the xml to disc
+ //serve the location
+ }
+ }catch (IOException e){
+
+ }
+ }
+
+ private boolean xrdExists(String path, String jid){
+ //find the xrd file
+ String fileLoc=path+ "/"+jid+ ".xml";
+ File f = new File(fileLoc);
+ if (f.exists()) return true;
+ else return false;
+ }
+
+ private void serveFile(HttpServletResponse response, String path, String jid){
+
+ try{
+
+ DataInputStream is = new DataInputStream(new FileInputStream(path+ "/"+jid+ ".xml"));
+
+ // Send the headers
+ response.setContentType("application/xrd+xml");
+
+ // Stream the file
+ final byte[] bbuf = new byte[BUFFSIZE];
+ final OutputStream os = response.getOutputStream();
+
+ int length = 0;
+ while ((is != null) && ((length = is.read(bbuf)) != -1)) {
+ os.write(bbuf, 0, length);
+ }
+
+ is.close();
+ os.flush();
+ os.close();
+ }
+ catch (FileNotFoundException fe){
+ //we can swallow this one...
+ }
+ catch (IOException ioe){
+ Log.error("error serving the account xrd file");
+
+ }
+ }
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+
+ // Exclude this servlet from requering the user to login
+ AuthCheckFilter.addExclude("osw-openfire-plugin");
+ AuthCheckFilter.addExclude("osw-openfire-plugin/webfinger/");
+ AuthCheckFilter.addExclude("osw-openfire-plugin/webfinger");
+
+
+ }
+
+}
@@ -6,11 +6,27 @@
<servlet-name>FileServlet</servlet-name>
<servlet-class>org.onesocialweb.openfire.web.FileServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>WebfingerServlet</servlet-name>
+ <servlet-class>org.onesocialweb.openfire.web.WebfingerServlet</servlet-class>
+ </servlet>
+ <servlet>
+ <servlet-name>HCardServlet</servlet-name>
+ <servlet-class>org.onesocialweb.openfire.web.HCardServlet</servlet-class>
+ </servlet>
<!-- Servlet mappings -->
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/file</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>WebfingerServlet</servlet-name>
+ <url-pattern>/webfinger</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>HCardServlet</servlet-name>
+ <url-pattern>/profiles</url-pattern>
+ </servlet-mapping>
</web-app>

0 comments on commit 0c8880a

Please sign in to comment.