/** * Copyright (c) 2003-2005, David A. Czarnecki * All rights reserved. * * Portions Copyright (c) 2003-2005 by Mark Lussier * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the "David A. Czarnecki" and "blojsom" nor the names of * its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Products derived from this software may not be called "blojsom", * nor may "blojsom" appear in their name, without prior written permission of * David A. Czarnecki. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.blojsom.extension.xmlrpc.handlers; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.xmlrpc.XmlRpcException; import org.blojsom.BlojsomException; import org.blojsom.plugin.admin.event.AddBlogEntryEvent; import org.blojsom.plugin.admin.event.UpdatedBlogEntryEvent; import org.blojsom.plugin.admin.event.DeletedBlogEntryEvent; import org.blojsom.blog.BlogCategory; import org.blojsom.blog.BlogEntry; import org.blojsom.blog.BlogUser; import org.blojsom.blog.Blog; import org.blojsom.fetcher.BlojsomFetcher; import org.blojsom.util.BlojsomUtils; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.*; import java.text.SimpleDateFormat; /** * Blojsom XML-RPC Handler for the MetaWeblog API *

* MetaWeblog API pec can be found at http://www.xmlrpc.com/metaWeblogApi * * @author Mark Lussier * @version $Id: MetaWeblogAPIHandler.java,v 1.3.2.1 2005/07/21 04:30:23 johnan Exp $ */ public class MetaWeblogAPIHandler extends AbstractBlojsomAPIHandler { private static final String METAWEBLOG_ACCEPTED_TYPES_IP = "blojsom-extension-metaweblog-accepted-types"; /** * Blogger API "blogid" key */ private static final String MEMBER_BLOGID = "blogid"; /** * Blogger API "blogName" key */ private static final String MEMBER_BLOGNAME = "blogName"; /** * MetaWeblog API "description" key */ private static final String MEMBER_DESCRIPTION = "description"; /** * MetaWeblog API "htmlUrl" key */ private static final String MEMBER_HTML_URL = "htmlUrl"; /** * MetaWeblog API "rssUrl" key */ private static final String MEMBER_RSS_URL = "rssUrl"; /** * MetaWeblog API "title" key */ private static final String MEMBER_TITLE = "title"; /** * MetaWeblog API "link" key */ private static final String MEMBER_LINK = "link"; /** * MetaWeblog API "name" key */ private static final String MEMBER_NAME = "name"; /** * MetaWeblog API "type" key */ private static final String MEMBER_TYPE = "type"; /** * MetaWeblog API "bits" key */ private static final String MEMBER_BITS = "bits"; /** * MetaWeblog API "permaLink" key */ private static final String MEMBER_PERMALINK = "permaLink"; /** * MetaWeblog API "dateCreated" key */ private static final String MEMBER_DATE_CREATED = "dateCreated"; /** * MetaWeblog API "categories" key */ private static final String MEMBER_CATEGORIES = "categories"; /** * MetaWeblog API "postid" key */ private static final String MEMBER_POSTID = "postid"; /** * MetaWeblog API "url" key */ private static final String MEMBER_URL = "url"; private static final String METAWEBLOG_API_PERMISSION = "post_via_metaweblog_api"; public static final String API_PREFIX = "metaWeblog"; private String _uploadDirectory; private HashMap _acceptedMimeTypes; private String _staticURLPrefix; private Log _logger = LogFactory.getLog(MetaWeblogAPIHandler.class); /** * Default constructor */ public MetaWeblogAPIHandler() { } /** * Gets the name of API Handler. Used to bind to XML-RPC * * @return The API Name (ie: metaWeblog) */ public String getName() { return API_PREFIX; } /** * Attach a Blog instance to the API Handler so that it can interact with the blog * * @param blogUser an instance of BlogUser * @throws BlojsomException If there is an error setting the blog instance or properties for the handler * @see org.blojsom.blog.BlogUser */ public void setBlogUser(BlogUser blogUser) throws BlojsomException { _blogUser = blogUser; _blog = _blogUser.getBlog(); _blogEntryExtension = _blog.getBlogProperty(BLOG_XMLRPC_ENTRY_EXTENSION_IP); if (BlojsomUtils.checkNullOrBlank(_blogEntryExtension)) { _blogEntryExtension = DEFAULT_BLOG_XMLRPC_ENTRY_EXTENSION; } _uploadDirectory = _configuration.getQualifiedResourceDirectory(); if (BlojsomUtils.checkNullOrBlank(_uploadDirectory)) { throw new BlojsomException("No upload directory specified in blog configuration"); } if (!_uploadDirectory.endsWith("/")) { _uploadDirectory += "/"; } _logger.debug("Upload directory for user [" + _blogUser.getId() + "] is " + _uploadDirectory); _acceptedMimeTypes = new HashMap(3); String acceptedMimeTypes = _blog.getBlogProperty(METAWEBLOG_ACCEPTED_TYPES_IP); if (acceptedMimeTypes != null && !"".equals(acceptedMimeTypes)) { String[] types = BlojsomUtils.parseCommaList(acceptedMimeTypes); for (int i = 0; i < types.length; i++) { String type = types[i]; type = type.toLowerCase(); _acceptedMimeTypes.put(type, type); } } _staticURLPrefix = _configuration.getResourceDirectory(); if (!_staticURLPrefix.endsWith("/")) { _staticURLPrefix += "/"; } } /** * Returns information on all the blogs a given user is a member of * * @param appkey Unique identifier/passcode of the application sending the post * @param userid Login for a Blogger user who has permission to post to the blog * @param password Password for said username * @throws XmlRpcException If there are no categories or the user was not authenticated correctly * @return Blog category list */ public Object getUsersBlogs(String appkey, String userid, String password) throws Exception { _logger.debug("getUsersBlogs() Called ===[ SUPPORTED ]======="); _logger.debug(" Appkey: " + appkey); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); try { _authorizationProvider.loadAuthenticationCredentials(_blogUser); _authorizationProvider.authorize(_blogUser, null, userid, password); checkXMLRPCPermission(userid, METAWEBLOG_API_PERMISSION); Vector result = new Vector(); BlogCategory[] _categories = _fetcher.fetchCategories(null, _blogUser); if (_categories != null) { for (int x = 0; x < _categories.length; x++) { Hashtable _bloglist = new Hashtable(3); BlogCategory _category = _categories[x]; String _blogid = _category.getCategory(); if (_blogid.length() > 1) { _blogid = BlojsomUtils.removeInitialSlash(_blogid); } String _description = ""; Map _metadata = _category.getMetaData(); if (_metadata != null && _metadata.containsKey(NAME_KEY)) { _description = (String) _metadata.get(NAME_KEY); } else { _description = _category.getEncodedCategory(); } _bloglist.put(MEMBER_URL, _category.getCategoryURL()); _bloglist.put(MEMBER_BLOGID, _blogid); _bloglist.put(MEMBER_BLOGNAME, _description); result.add(_bloglist); } } return result; } catch (BlojsomException e) { _logger.error("Failed to authenticate user [" + userid + "] with password [" + password + "]"); throw new XmlRpcException(AUTHORIZATION_EXCEPTION, AUTHORIZATION_EXCEPTION_MSG); } } /** * Authenticates a user and returns the categories available in the blojsom * * @param blogid Dummy Value for Blojsom * @param userid Login for a MetaWeblog user who has permission to post to the blog * @param password Password for said username * @return Blog category list * @throws XmlRpcException If there are no categories or the user was not authenticated correctly */ public Object getCategories(String blogid, String userid, String password) throws Exception { _logger.debug("getCategories() Called =====[ SUPPORTED ]====="); _logger.debug(" BlogId: " + blogid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); try { _authorizationProvider.loadAuthenticationCredentials(_blogUser); _authorizationProvider.authorize(_blogUser, null, userid, password); checkXMLRPCPermission(userid, METAWEBLOG_API_PERMISSION); Hashtable result; BlogCategory[] categories = _fetcher.fetchCategories(null, _blogUser); if (categories != null) { result = new Hashtable(categories.length); for (int x = 0; x < categories.length; x++) { Hashtable catlist = new Hashtable(3); BlogCategory category = categories[x]; String categoryId = category.getCategory(); if (categoryId.length() > 1) { categoryId = BlojsomUtils.removeInitialSlash(categoryId); } String description; Map metadata = category.getMetaData(); if (metadata != null && metadata.containsKey(DESCRIPTION_KEY)) { description = (String) metadata.get(DESCRIPTION_KEY); } else { description = category.getEncodedCategory(); } catlist.put(MEMBER_DESCRIPTION, description); catlist.put(MEMBER_HTML_URL, category.getCategoryURL()); catlist.put(MEMBER_RSS_URL, category.getCategoryURL() + "?flavor=rss2"); result.put(categoryId, catlist); } } else { throw new XmlRpcException(NOBLOGS_EXCEPTION, NOBLOGS_EXCEPTION_MSG); } return result; } catch (BlojsomException e) { _logger.error("Failed to authenticate user [" + userid + "] with password [" + password + "]"); throw new XmlRpcException(AUTHORIZATION_EXCEPTION, AUTHORIZATION_EXCEPTION_MSG); } } /** * Makes a new post to a designated blog. Optionally, will publish the blog after making the post * * @param blogid Unique identifier of the blog the post will be added to * @param userid Login for a MetaWeblog user who has permission to post to the blog * @param password Password for said username * @param struct Contents of the post * @param publish If true, the blog will be published immediately after the post is made * @return Post ID of the added entry * @throws XmlRpcException If the user was not authenticated correctly or if there was an I/O exception */ public String newPost(String blogid, String userid, String password, Hashtable struct, boolean publish) throws Exception { _logger.debug("newPost() Called ===========[ SUPPORTED ]====="); _logger.debug(" BlogId: " + blogid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); _logger.debug(" Publish: " + publish); blogid = BlojsomUtils.normalize(blogid); if (struct.containsKey(MEMBER_CATEGORIES)) { Vector categories = (Vector) struct.get(MEMBER_CATEGORIES); if (categories.size() > 0) { String categoryForPost = (String) categories.get(0); blogid = BlojsomUtils.normalize(categoryForPost); } } try { _authorizationProvider.loadAuthenticationCredentials(_blogUser); _authorizationProvider.authorize(_blogUser, null, userid, password); checkXMLRPCPermission(userid, METAWEBLOG_API_PERMISSION); String result = null; //Quick verify that the categories are valid File blogCategory = getBlogCategoryDirectory(blogid); if (blogCategory.exists() && blogCategory.isDirectory()) { Hashtable postcontent = struct; String title = (String) postcontent.get(MEMBER_TITLE); String description = (String) postcontent.get(MEMBER_DESCRIPTION); String filename = BlojsomUtils.getBlogEntryFilename(title, description); String outputfile = blogCategory.getAbsolutePath() + File.separator + filename; Date dateCreated = (Date) postcontent.get(MEMBER_DATE_CREATED); try { File sourceFile = new File(outputfile + _blogEntryExtension); int fileTag = 1; while (sourceFile.exists()) { sourceFile = new File(outputfile + "-" + fileTag + _blogEntryExtension); fileTag++; } String postid = blogid + "?" + PERMALINK_PARAM + "=" + BlojsomUtils.urlEncode(sourceFile.getName()); BlogEntry entry = _fetcher.newBlogEntry(); HashMap attributeMap = new HashMap(); HashMap blogEntryMetaData = new HashMap(); attributeMap.put(SOURCE_ATTRIBUTE, sourceFile); entry.setAttributes(attributeMap); entry.setCategory(blogid); if (BlojsomUtils.checkNullOrBlank(title)) { title = null; } entry.setTitle(title); entry.setDescription(description); blogEntryMetaData.put(BLOG_ENTRY_METADATA_AUTHOR, userid); if (dateCreated == null) { blogEntryMetaData.put(BLOG_ENTRY_METADATA_TIMESTAMP, new Long(new Date().getTime()).toString()); } else { blogEntryMetaData.put(BLOG_ENTRY_METADATA_TIMESTAMP, convertDateCreated(dateCreated, _blog)); } entry.setMetaData(blogEntryMetaData); entry.save(_blogUser); entry.load(_blogUser); result = postid; // Send out an add blog entry event _configuration.getEventBroadcaster().broadcastEvent(new AddBlogEntryEvent(this, new Date(), entry, _blogUser)); } catch (BlojsomException e) { _logger.error(e); throw new XmlRpcException(UNKNOWN_EXCEPTION, UNKNOWN_EXCEPTION_MSG); } } return result; } catch (BlojsomException e) { _logger.error("Failed to authenticate user [" + userid + "] with password [" + password + "]"); throw new XmlRpcException(AUTHORIZATION_EXCEPTION, AUTHORIZATION_EXCEPTION_MSG); } } /** * Edits a given post. Optionally, will publish the blog after making the edit * * @param postid Unique identifier of the post to be changed * @param userid Login for a MetaWeblog user who has permission to post to the blog * @param password Password for said username * @param struct Contents of the post * @param publish If true, the blog will be published immediately after the post is made * @return true if the entry was edited, false otherwise * @throws XmlRpcException If the user was not authenticated correctly, if there was an I/O exception, * or if the entry permalink ID is invalid */ public boolean editPost(String postid, String userid, String password, Hashtable struct, boolean publish) throws Exception { _logger.debug("editPost() Called ========[ SUPPORTED ]====="); _logger.debug(" PostId: " + postid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); _logger.debug(" Publish: " + publish); try { _authorizationProvider.loadAuthenticationCredentials(_blogUser); _authorizationProvider.authorize(_blogUser, null, userid, password); checkXMLRPCPermission(userid, METAWEBLOG_API_PERMISSION); boolean result = false; String category = null; String permalink = null; String match = "?" + PERMALINK_PARAM + "="; int pos = postid.indexOf(match); // Look for categories in struct if (pos == -1) { Vector categories = (Vector) struct.get(MEMBER_CATEGORIES); if (categories == null) { throw new XmlRpcException(INVALID_POSTID, INVALID_POSTID_MSG); } else { category = (String) categories.get(0); permalink = postid; } } else if (pos != -1) { category = postid.substring(0, pos); category = BlojsomUtils.normalize(category); category = BlojsomUtils.urlDecode(category); permalink = postid.substring(pos + match.length()); } BlogCategory blogCategory = _fetcher.newBlogCategory(); blogCategory.setCategory(category); blogCategory.setCategoryURL(_blog.getBlogURL() + category); Map fetchMap = new HashMap(); fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, blogCategory); fetchMap.put(BlojsomFetcher.FETCHER_PERMALINK, permalink); BlogEntry[] entries = _fetcher.fetchEntries(fetchMap, _blogUser); if (entries != null && entries.length > 0) { BlogEntry entry = entries[0]; try { Hashtable postcontent = struct; String title = (String) postcontent.get(MEMBER_TITLE); String description = (String) postcontent.get(MEMBER_DESCRIPTION); Date dateCreated = (Date) postcontent.get(MEMBER_DATE_CREATED); if (title == null) { title = "No Title"; } String hashable = description; if (description.length() > MAX_HASHABLE_LENGTH) { hashable = hashable.substring(0, MAX_HASHABLE_LENGTH); } Map blogEntryMetaData = entry.getMetaData(); entry.setTitle(title); entry.setDescription(description); if (dateCreated != null) { blogEntryMetaData.put(BLOG_ENTRY_METADATA_TIMESTAMP, convertDateCreated(dateCreated, _blog)); } entry.save(_blogUser); result = true; // Send out an updated blog entry event _configuration.getEventBroadcaster().broadcastEvent(new UpdatedBlogEntryEvent(this, new Date(), entry, _blogUser)); } catch (BlojsomException e) { _logger.error(e); throw new XmlRpcException(UNKNOWN_EXCEPTION, UNKNOWN_EXCEPTION_MSG); } } else { throw new XmlRpcException(INVALID_POSTID, INVALID_POSTID_MSG); } return result; } catch (BlojsomException e) { _logger.error("Failed to authenticate user [" + userid + "] with password [" + password + "]"); throw new XmlRpcException(AUTHORIZATION_EXCEPTION, AUTHORIZATION_EXCEPTION_MSG); } } /** * Retrieves a given post from the blog * * @param postid Unique identifier of the post to be changed * @param userid Login for a MetaWeblog user who has permission to post to the blog * @param password Password for said username * @return Structure containing the minimal attributes for the MetaWeblog API getPost() method: title, link, and description * @throws XmlRpcException If the user was not authenticated correctly, if there was an I/O exception, * or if the entry permalink ID is invalid * @since blojsom 1.9.4 */ public Object getPost(String postid, String userid, String password) throws Exception { _logger.debug("getPost() Called =========[ SUPPORTED ]====="); _logger.debug(" PostId: " + postid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); try { _authorizationProvider.loadAuthenticationCredentials(_blogUser); _authorizationProvider.authorize(_blogUser, null, userid, password); checkXMLRPCPermission(userid, METAWEBLOG_API_PERMISSION); String category; String permalink; String match = "?" + PERMALINK_PARAM + "="; int pos = postid.indexOf(match); if (pos != -1) { category = postid.substring(0, pos); category = BlojsomUtils.normalize(category); category = BlojsomUtils.urlDecode(category); permalink = postid.substring(pos + match.length()); BlogCategory blogCategory = _fetcher.newBlogCategory(); blogCategory.setCategory(category); blogCategory.setCategoryURL(_blog.getBlogURL() + category); Map fetchMap = new HashMap(); fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, blogCategory); fetchMap.put(BlojsomFetcher.FETCHER_PERMALINK, permalink); BlogEntry[] entries = _fetcher.fetchEntries(fetchMap, _blogUser); if (entries != null && entries.length > 0) { BlogEntry entry = entries[0]; Hashtable postcontent = new Hashtable(3); postcontent.put(MEMBER_TITLE, entry.getTitle()); postcontent.put(MEMBER_LINK, entry.getPermalink()); postcontent.put(MEMBER_DESCRIPTION, entry.getDescription()); postcontent.put(MEMBER_DATE_CREATED, entry.getDate()); postcontent.put(MEMBER_PERMALINK, entry.getLink()); postcontent.put(MEMBER_POSTID, entry.getId()); Vector postCategories = new Vector(1); postCategories.add(entry.getCategory()); postcontent.put(MEMBER_CATEGORIES, postCategories); return postcontent; } else { throw new XmlRpcException(INVALID_POSTID, INVALID_POSTID_MSG); } } else { throw new XmlRpcException(INVALID_POSTID, INVALID_POSTID_MSG); } } catch (BlojsomException e) { _logger.error("Failed to authenticate user [" + userid + "] with password [" + password + "]"); throw new XmlRpcException(AUTHORIZATION_EXCEPTION, AUTHORIZATION_EXCEPTION_MSG); } } /** * Delete a Post * * @param appkey Unique identifier/passcode of the application sending the post * @param postid Unique identifier of the post to be changed * @param userid Login for a Blogger user who has permission to post to the blog * @param password Password for said username * @param publish Ignored * @throws XmlRpcException * @return true if the entry was delete, false otherwise */ public boolean deletePost(String appkey, String postid, String userid, String password, boolean publish) throws Exception { _logger.debug("deletePost() Called =====[ SUPPORTED ]====="); _logger.debug(" Appkey: " + appkey); _logger.debug(" PostId: " + postid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); boolean result = false; try { _authorizationProvider.loadAuthenticationCredentials(_blogUser); _authorizationProvider.authorize(_blogUser, null, userid, password); checkXMLRPCPermission(userid, METAWEBLOG_API_PERMISSION); String category; String permalink; String match = "?" + PERMALINK_PARAM + "="; int pos = postid.indexOf(match); if (pos != -1) { category = postid.substring(0, pos); category = BlojsomUtils.normalize(category); category = BlojsomUtils.urlDecode(category); permalink = postid.substring(pos + match.length()); Map fetchMap = new HashMap(); BlogCategory blogCategory = _fetcher.newBlogCategory(); blogCategory.setCategory(category); blogCategory.setCategoryURL(_blog.getBlogURL() + category); fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, blogCategory); fetchMap.put(BlojsomFetcher.FETCHER_PERMALINK, permalink); BlogEntry[] _entries = _fetcher.fetchEntries(fetchMap, _blogUser); if (_entries != null && _entries.length > 0) { try { _entries[0].delete(_blogUser); } catch (BlojsomException e) { _logger.error(e); throw new XmlRpcException(UNKNOWN_EXCEPTION, UNKNOWN_EXCEPTION_MSG); } result = true; // Send out a deleted blog entry event _configuration.getEventBroadcaster().broadcastEvent(new DeletedBlogEntryEvent(this, new Date(), _entries[0], _blogUser)); } else { throw new XmlRpcException(INVALID_POSTID, INVALID_POSTID_MSG); } } } catch (BlojsomException e) { _logger.error("Failed to authenticate user [" + userid + "] with password [" + password + "]"); throw new XmlRpcException(AUTHORIZATION_EXCEPTION, AUTHORIZATION_EXCEPTION_MSG); } return result; } /** * Retrieves a set of recent posts to the blog * * @param blogid Unique identifier of the blog the post will be added to * @param userid Login for a MetaWeblog user who has permission to post to the blog * @param password Password for said username * @param numberOfPosts Number of posts to be retrieved from the blog * @return Array of structures containing the minimal attributes for the MetaWeblog API getPost() method: title, link, and description * @throws Exception If the user was not authenticated correctly * @since blojsom 1.9.5 */ public Object getRecentPosts(String blogid, String userid, String password, int numberOfPosts) throws Exception { _logger.debug("getRecentPosts() Called =========[ SUPPORTED ]====="); _logger.debug(" BlogId: " + blogid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); try { _authorizationProvider.loadAuthenticationCredentials(_blogUser); _authorizationProvider.authorize(_blogUser, null, userid, password); checkXMLRPCPermission(userid, METAWEBLOG_API_PERMISSION); blogid = BlojsomUtils.normalize(blogid); BlogCategory category = _fetcher.newBlogCategory(); category.setCategory(blogid); category.setCategoryURL(_blog.getBlogURL() + blogid); Map fetchMap = new HashMap(); fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, category); fetchMap.put(BlojsomFetcher.FETCHER_NUM_POSTS_INTEGER, new Integer(numberOfPosts)); BlogEntry[] entries = _fetcher.fetchEntries(fetchMap, _blogUser); Vector blogEntries = new Vector(); Hashtable postcontent; if (entries != null && entries.length > 0) { blogEntries = new Vector(entries.length); BlogEntry entry; for (int i = 0; i < entries.length; i++) { entry = entries[i]; postcontent = new Hashtable(7); postcontent.put(MEMBER_TITLE, entry.getTitle()); postcontent.put(MEMBER_LINK, entry.getPermalink()); postcontent.put(MEMBER_DESCRIPTION, entry.getDescription()); postcontent.put(MEMBER_DATE_CREATED, entry.getDate()); postcontent.put(MEMBER_PERMALINK, entry.getLink()); postcontent.put(MEMBER_POSTID, entry.getId()); Vector postCategories = new Vector(1); postCategories.add(entry.getCategory()); postcontent.put(MEMBER_CATEGORIES, postCategories); blogEntries.add(postcontent); } } return blogEntries; } catch (BlojsomException e) { _logger.error("Failed to authenticate user [" + userid + "] with password [" + password + "]"); throw new XmlRpcException(AUTHORIZATION_EXCEPTION, AUTHORIZATION_EXCEPTION_MSG); } } /** * Uploads an object to the blog to a specified directory * * @param blogid Unique identifier of the blog the post will be added to * @param userid Login for a MetaWeblog user who has permission to post to the blog * @param password Password for said username * @param struct Upload structure defined by the MetaWeblog API * @return Structure containing a link to the uploaded media object * @throws XmlRpcException If the user was not authenticated correctly, if there was an I/O exception, * or if the MIME type of the upload object is not accepted * @since blojsom 1.9.4 */ public Object newMediaObject(String blogid, String userid, String password, Hashtable struct) throws Exception { _logger.debug("newMediaObject() Called =[ SUPPORTED ]====="); _logger.debug(" BlogId: " + blogid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); try { _authorizationProvider.loadAuthenticationCredentials(_blogUser); _authorizationProvider.authorize(_blogUser, null, userid, password); checkXMLRPCPermission(userid, METAWEBLOG_API_PERMISSION); String name = (String) struct.get(MEMBER_NAME); name = BlojsomUtils.getFilenameFromPath(name); _logger.debug("newMediaObject name: " + name); String type = (String) struct.get(MEMBER_TYPE); _logger.debug("newMediaObject type: " + type); byte[] bits = (byte[]) struct.get(MEMBER_BITS); File uploadDirectory = new File(_uploadDirectory); if (!uploadDirectory.exists()) { _logger.error("Upload directory does not exist: " + uploadDirectory.toString()); throw new XmlRpcException(UNKNOWN_EXCEPTION, "Upload directory does not exist: " + uploadDirectory.toString()); } if (_acceptedMimeTypes.containsKey(type.toLowerCase())) { try { File uploadDirectoryForUser = new File(uploadDirectory, _blogUser.getId()); if (!uploadDirectoryForUser.exists()) { if (!uploadDirectoryForUser.mkdir()) { _logger.error("Could not create upload directory for user: " + uploadDirectoryForUser.toString()); throw new XmlRpcException(UNKNOWN_EXCEPTION, "Could not create upload directory for user: " + _blogUser.getId()); } } // create any intermediate dirs... File mediaObjectFile = new File(name); // not absolute File parentDirs = mediaObjectFile.getParentFile(); if (parentDirs != null) { String parentDirsString = parentDirs.toString(); if (parentDirsString.startsWith("/")) { parentDirsString = parentDirsString.substring(1); } File uploadMediaDirectory = new File(uploadDirectoryForUser, parentDirsString); _logger.debug("upload directory for this media object: " + uploadMediaDirectory.toString()); if (!uploadMediaDirectory.exists()) { if (!uploadMediaDirectory.mkdirs()) { _logger.error("Could not create upload directory: " + uploadMediaDirectory.toString()); throw new XmlRpcException(UNKNOWN_EXCEPTION, "Could not create upload directory: " + uploadMediaDirectory.toString()); } } } String slashOrNot = "/"; if (_blogUser.getId().endsWith("/")) { slashOrNot = ""; } BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(uploadDirectoryForUser, name))); bos.write(bits); bos.close(); Hashtable returnStruct = new Hashtable(1); String mediaURL = _blog.getBlogBaseURL() + _staticURLPrefix + BlojsomUtils.removeTrailingSlash(_blogUser.getId()) + "/" + name; _logger.debug("newMediaObject URL: " + mediaURL); returnStruct.put(MEMBER_URL, mediaURL); return returnStruct; } catch (IOException e) { _logger.error(e); throw new XmlRpcException(UNKNOWN_EXCEPTION, UNKNOWN_EXCEPTION_MSG); } } else { _logger.error("MIME type not accepted. Received MIME type: " + type); throw new XmlRpcException(UNKNOWN_EXCEPTION, "MIME type not accepted. Received MIME type: " + type); } } catch (BlojsomException e) { _logger.error("Failed to authenticate user [" + userid + "] with password [" + password + "]"); throw new XmlRpcException(AUTHORIZATION_EXCEPTION, AUTHORIZATION_EXCEPTION_MSG); } } /** * Edits the main or archive index template of a given blog (NOT IMPLEMENTED) * * @param appkey Unique identifier/passcode of the application sending the post * @param blogid Unique identifier of the blog the post will be added to * @param userid Login for a Blogger user who has permission to post to the blog * @param password Password for said username * @param template The text for the new template (usually mostly HTML). Must contain opening and closing tags, since they're needed to publish * @param templateType Determines which of the blog's templates will be returned. Currently, either "main" or "archiveIndex" * @throws XmlRpcException * @return */ public boolean setTemplate(String appkey, String blogid, String userid, String password, String template, String templateType) throws Exception { _logger.debug("setTemplate() Called =====[ UNSUPPORTED ]====="); _logger.debug(" Appkey: " + appkey); _logger.debug(" BlogId: " + blogid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); _logger.debug(" Template: " + template); _logger.debug(" Type: " + templateType); throw new XmlRpcException(UNSUPPORTED_EXCEPTION, UNSUPPORTED_EXCEPTION_MSG); } /** * Returns the main or archive index template of a given blog (NOT IMPLEMENTED) * * @param appkey Unique identifier/passcode of the application sending the post * @param blogid Unique identifier of the blog the post will be added to * @param userid Login for a Blogger user who has permission to post to the blog * @param password Password for said username * @param templateType Determines which of the blog's templates will be returned. Currently, either "main" or "archiveIndex" * @throws XmlRpcException * @return */ public String getTemplate(String appkey, String blogid, String userid, String password, String templateType) throws Exception { _logger.debug("getTemplate() Called =====[ UNSUPPORTED ]====="); _logger.debug(" Appkey: " + appkey); _logger.debug(" BlogId: " + blogid); _logger.debug(" UserId: " + userid); _logger.debug(" Password: *********"); _logger.debug(" Type: " + templateType); throw new XmlRpcException(UNSUPPORTED_EXCEPTION, UNSUPPORTED_EXCEPTION_MSG); } /** * Convert the dateCreated attribute to the local timezone * * @param dateCreated Date indicating the date and time created for the entry * @param blog {@link Blog} infomation * @return Date converted to a long (as String) */ private String convertDateCreated(Date dateCreated, Blog blog) { if (dateCreated == null) { return Long.toString(new Date().getTime()); } else { String timezoneID = blog.getBlogProperty("blog-timezone-id"); TimeZone timezone; if (BlojsomUtils.checkNullOrBlank(timezoneID)) { timezone = TimeZone.getDefault(); } else { timezone = TimeZone.getTimeZone(timezoneID); } SimpleDateFormat simpleDateFormat = new SimpleDateFormat(ISO_8601_DATE_FORMAT); simpleDateFormat.setTimeZone(timezone); long convertedDateTime = dateCreated.getTime(); try { convertedDateTime = Long.parseLong(simpleDateFormat.format(dateCreated)); } catch (NumberFormatException e) { } return Long.toString(convertedDateTime); } } }