package org.xmlrpc.android;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.os.AsyncTask;
import android.text.format.DateUtils;
import com.google.gson.Gson;
import org.wordpress.android.WordPress;
import org.wordpress.android.models.Blog;
import org.wordpress.android.task.MultiAsyncTask;
import org.wordpress.android.util.HttpRequest;
import org.wordpress.android.util.HttpRequest.HttpRequestException;
public class ApiHelper {
/** Called when the activity is first created. */
private static XMLRPCClient client;
@SuppressWarnings("unchecked")
static void refreshComments(final int id, final Context ctx) {
Blog blog;
try {
blog = new Blog(id);
} catch (Exception e1) {
return;
}
client = new XMLRPCClient(blog.getUrl(), blog.getHttpuser(),
blog.getHttppassword());
Map<String, Object> hPost = new HashMap<String, Object>();
hPost.put("status", "");
hPost.put("post_id", "");
hPost.put("number", 30);
Object[] params = { blog.getBlogId(), blog.getUsername(),
blog.getPassword(), hPost };
Object[] result = null;
try {
result = (Object[]) client.call("wp.getComments", params);
} catch (XMLRPCException e) {
}
if (result != null) {
if (result.length > 0) {
String author, postID, commentID, comment, status, authorEmail, authorURL, postTitle;
Map<Object, Object> contentHash = new HashMap<Object, Object>();
List<Map<String, String>> dbVector = new Vector<Map<String, String>>();
Date d = new Date();
// loop this!
for (int ctr = 0; ctr < result.length; ctr++) {
Map<String, String> dbValues = new HashMap<String, String>();
contentHash = (Map<Object, Object>) result[ctr];
comment = contentHash.get("content").toString();
author = contentHash.get("author").toString();
status = contentHash.get("status").toString();
postID = contentHash.get("post_id").toString();
commentID = contentHash.get("comment_id").toString();
d = (Date) contentHash.get("date_created_gmt");
authorURL = contentHash.get("author_url").toString();
authorEmail = contentHash.get("author_email").toString();
postTitle = contentHash.get("post_title").toString();
String formattedDate = d.toString();
try {
int flags = 0;
flags |= android.text.format.DateUtils.FORMAT_SHOW_DATE;
flags |= android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
flags |= android.text.format.DateUtils.FORMAT_SHOW_YEAR;
flags |= android.text.format.DateUtils.FORMAT_SHOW_TIME;
formattedDate = DateUtils.formatDateTime(ctx,
d.getTime(), flags);
} catch (Exception e) {
}
dbValues.put("blogID", String.valueOf(id));
dbValues.put("postID", postID);
dbValues.put("commentID", commentID);
dbValues.put("author", author);
dbValues.put("comment", comment);
dbValues.put("commentDate", formattedDate);
dbValues.put("commentDateFormatted", formattedDate);
dbValues.put("status", status);
dbValues.put("url", authorURL);
dbValues.put("email", authorEmail);
dbValues.put("postTitle", postTitle);
dbVector.add(ctr, dbValues);
}
WordPress.wpDB.saveComments(dbVector);
}
}
}
public static class getPostFormatsTask extends
AsyncTask<List<?>, Void, Object> {
Context ctx;
Blog blog;
boolean isPage, loadMore;
protected void onPostExecute(Object result) {
try {
Map<?, ?> postFormats = (HashMap<?, ?>) result;
if (postFormats.size() > 0) {
Gson gson = new Gson();
String postFormatsJson = gson.toJson(postFormats);
if (postFormatsJson != null) {
blog.setPostFormats(postFormatsJson);
blog.save(null);
}
}
} catch (Exception e) {
//e.printStackTrace();
}
}
@Override
protected Object doInBackground(List<?>... args) {
List<?> arguments = args[0];
blog = (Blog) arguments.get(0);
ctx = (Context) arguments.get(1);
client = new XMLRPCClient(blog.getUrl(), blog.getHttpuser(),
blog.getHttppassword());
Object result = null;
Object[] params = { blog.getBlogId(), blog.getUsername(),
blog.getPassword(), "show-supported" };
try {
result = (Object) client.call("wp.getPostFormats", params);
} catch (XMLRPCException e) {
//e.printStackTrace();
}
return result;
}
}
/**
* Task to refresh blog level information (WP version number) and stuff
* related to the active theme (available post types, recent comments, etc).
*/
public static class RefreshBlogContentTask extends
MultiAsyncTask<Boolean, Void, Boolean> {
/** Blog being refresh. */
private Blog blog;
/** Application context. */
private Context context;
public RefreshBlogContentTask(Context context, Blog blog) {
this.blog = blog;
this.context = context;
}
@Override
protected Boolean doInBackground(Boolean... params) {
boolean commentsOnly = params[0];
XMLRPCClient client = new XMLRPCClient(blog.getUrl(),
blog.getHttpuser(), blog.getHttppassword());
if (!commentsOnly) {
// check the WP number if self-hosted
Map<String, String> hPost = new HashMap<String, String>();
hPost.put("software_version", "software_version");
hPost.put("post_thumbnail", "post_thumbnail");
hPost.put("jetpack_client_id", "jetpack_client_id");
hPost.put("blog_public", "blog_public");
hPost.put("home_url", "home_url");
hPost.put("admin_url", "admin_url");
hPost.put("login_url", "login_url");
Object[] vParams = { blog.getBlogId(), blog.getUsername(),
blog.getPassword(), hPost };
Object versionResult = new Object();
try {
versionResult = (Object) client.call("wp.getOptions",
vParams);
} catch (XMLRPCException e) {
return false;
}
if (versionResult != null) {
try {
Map<?, ?> blogOptions = (HashMap<?, ?>) versionResult;
Gson gson = new Gson();
String blogOptionsJson = gson.toJson(blogOptions);
if (blogOptionsJson != null)
blog.setBlogOptions(blogOptionsJson);
// Software version
if (!blog.isDotcomFlag()) {
Map<?, ?> sv = (HashMap<?, ?>) blogOptions
.get("software_version");
String wpVersion = sv.get("value").toString();
if (wpVersion.length() > 0) {
blog.setWpVersion(wpVersion);
}
}
// Featured image support
Map<?, ?> featuredImageHash = (HashMap<?, ?>) blogOptions
.get("post_thumbnail");
if (featuredImageHash != null) {
boolean featuredImageCapable = Boolean
.parseBoolean(featuredImageHash
.get("value").toString());
blog.setFeaturedImageCapable(featuredImageCapable);
} else {
blog.setFeaturedImageCapable(false);
}
if (WordPress.getCurrentBlog() != null
&& WordPress.getCurrentBlog().isActive())
blog.save("");
} catch (Exception e) {
}
}
// get theme post formats
List<Object> args = new Vector<Object>();
args.add(blog);
args.add(context);
new ApiHelper.getPostFormatsTask().execute(args);
}
// refresh the comments
Map<String, Object> hPost = new HashMap<String, Object>();
hPost.put("number", 30);
Object[] commentParams = { blog.getBlogId(), blog.getUsername(),
blog.getPassword(), hPost };
try {
ApiHelper.refreshComments(context, commentParams);
} catch (XMLRPCException e) {
return false;
}
return true;
}
}
public static Map<Integer, Map<?, ?>> refreshComments(Context ctx,
Object[] commentParams) throws XMLRPCException {
Blog blog = WordPress.getCurrentBlog();
if (blog == null)
return null;
client = new XMLRPCClient(blog.getUrl(), blog.getHttpuser(),
blog.getHttppassword());
String author, postID, comment, status, authorEmail, authorURL, postTitle;
int commentID;
Map<Integer, Map<?, ?>> allComments = new HashMap<Integer, Map<?, ?>>();
Map<?, ?> contentHash = new HashMap<Object, Object>();
List<Map<?, ?>> dbVector = new Vector<Map<?, ?>>();
Date d = new Date();
Object[] result;
try {
result = (Object[]) client.call("wp.getComments", commentParams);
} catch (XMLRPCException e) {
throw new XMLRPCException(e);
}
if (result.length == 0)
return null;
// loop this!
for (int ctr = 0; ctr < result.length; ctr++) {
Map<Object, Object> dbValues = new HashMap<Object, Object>();
contentHash = (Map<?, ?>) result[ctr];
allComments.put(
Integer.parseInt(contentHash.get("comment_id").toString()),
contentHash);
comment = contentHash.get("content").toString();
author = contentHash.get("author").toString();
status = contentHash.get("status").toString();
postID = contentHash.get("post_id").toString();
commentID = Integer.parseInt(contentHash.get("comment_id")
.toString());
d = (Date) contentHash.get("date_created_gmt");
authorURL = contentHash.get("author_url").toString();
authorEmail = contentHash.get("author_email").toString();
postTitle = contentHash.get("post_title").toString();
String formattedDate = d.toString();
try {
int flags = 0;
flags |= android.text.format.DateUtils.FORMAT_SHOW_DATE;
flags |= android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
flags |= android.text.format.DateUtils.FORMAT_SHOW_YEAR;
flags |= android.text.format.DateUtils.FORMAT_SHOW_TIME;
formattedDate = DateUtils.formatDateTime(ctx, d.getTime(),
flags);
} catch (Exception e) {
}
dbValues.put("blogID", String.valueOf(blog.getId()));
dbValues.put("postID", postID);
dbValues.put("commentID", commentID);
dbValues.put("author", author);
dbValues.put("comment", comment);
dbValues.put("commentDate", formattedDate);
dbValues.put("commentDateFormatted", formattedDate);
dbValues.put("status", status);
dbValues.put("url", authorURL);
dbValues.put("email", authorEmail);
dbValues.put("postTitle", postTitle);
dbVector.add(ctr, dbValues);
}
WordPress.wpDB.saveComments(dbVector);
return allComments;
}
/**
* Discover the XML-RPC endpoint for the WordPress API associated with the
* specified blog URL.
*
* @param urlString
* URL of the blog to get the XML-RPC endpoint for.
* @return XML-RPC endpoint for the specified blog, or null if unable to
* discover endpoint.
*/
public static String getXMLRPCUrl(String urlString) {
Pattern xmlrpcLink = Pattern.compile(
"<api\\s*?name=\"WordPress\".*?apiLink=\"(.*?)\"",
Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
String html = getResponse(urlString);
if (html != null) {
Matcher matcher = xmlrpcLink.matcher(html);
if (matcher.find()) {
String href = matcher.group(1);
return href;
}
}
return null; // never found the rsd tag
}
/**
* Discover the RSD homepage URL associated with the specified blog URL.
*
* @param urlString
* URL of the blog to get the link for.
* @return RSD homepage URL for the specified blog, or null if unable to
* discover URL.
*/
public static String getHomePageLink(String urlString) {
Pattern xmlrpcLink = Pattern.compile(
"<homePageLink>(.*?)</homePageLink>", Pattern.CASE_INSENSITIVE
| Pattern.DOTALL);
String html = getResponse(urlString);
if (html != null) {
Matcher matcher = xmlrpcLink.matcher(html);
if (matcher.find()) {
String href = matcher.group(1);
return href;
}
}
return null; // never found the rsd tag
}
/**
* Fetch the content stream of the resource at the specified URL.
*
* @param urlString
* URL to fetch contents for.
* @return content stream, or null if URL was invalid or resource could not
* be retrieved.
*/
public static InputStream getResponseStream(String urlString) {
HttpRequest request = getHttpRequest(urlString);
if (request != null) {
return request.buffer();
} else {
return null;
}
}
/**
* Fetch the content of the resource at the specified URL.
*
* @param urlString
* URL to fetch contents for.
* @return content of the resource, or null if URL was invalid or resource
* could not be retrieved.
*/
public static String getResponse(String urlString) {
HttpRequest request = getHttpRequest(urlString);
if (request != null) {
try {
String body = request.body();
return body;
} catch (HttpRequestException e) {
return null;
}
} else {
return null;
}
}
/**
* Fetch the specified HTTP resource.
*
* The URL class will automatically follow up to five redirects, with the
* exception of redirects between HTTP and HTTPS URLs. This method manually
* handles one additional redirect to allow for this protocol switch.
*
* @param urlString
* URL to fetch.
* @return the request / response object or null if the resource could not
* be retrieved.
*/
public static HttpRequest getHttpRequest(String urlString) {
if (urlString == null)
return null;
try {
HttpRequest request = HttpRequest.get(urlString);
// manually follow one additional redirect to support protocol switching
if (request != null) {
if (request.code() == HttpURLConnection.HTTP_MOVED_PERM
|| request.code() == HttpURLConnection.HTTP_MOVED_TEMP) {
String location = request.location();
if (location != null) {
request = HttpRequest.get(location);
}
}
}
return request;
} catch (HttpRequestException e) {
return null;
}
}
}