File Source: RollerAtomHandler.java

         /* 
    P/P   *  Method: org.apache.roller.weblogger.webservices.atomprotocol.RollerAtomHandler$1__static_init
          */
     1  /*
     2  * Licensed to the Apache Software Foundation (ASF) under one or more
     3  *  contributor license agreements.  The ASF licenses this file to You
     4  * under the Apache License, Version 2.0 (the "License"); you may not
     5  * use this file except in compliance with the License.
     6  * You may obtain a copy of the License at
     7  *
     8  *     http://www.apache.org/licenses/LICENSE-2.0
     9  *
    10  * Unless required by applicable law or agreed to in writing, software
    11  * distributed under the License is distributed on an "AS IS" BASIS,
    12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  * See the License for the specific language governing permissions and
    14  * limitations under the License.  For additional information regarding
    15  * copyright in this work, please see the NOTICE file in the top level
    16  * directory of this distribution.
    17  */
    18  package org.apache.roller.weblogger.webservices.atomprotocol;
    19  import java.io.File;
    20  import java.io.FileInputStream;
    21  import java.io.FileOutputStream;
    22  import java.io.InputStream;
    23  import java.sql.Timestamp;
    24  import java.util.ArrayList;
    25  import java.util.Date;
    26  import java.util.Iterator;
    27  import java.util.List;
    28  import java.util.StringTokenizer;
    29  import java.util.Collections;
    30  import javax.activation.MimetypesFileTypeMap;
    31  import javax.servlet.http.HttpServletRequest;
    32  import org.apache.commons.codec.binary.Base64;
    33  import org.apache.commons.logging.Log;
    34  import org.apache.commons.logging.LogFactory;
    35  import org.apache.roller.weblogger.business.FileManager;
    36  import org.apache.roller.weblogger.business.FileNotFoundException;
    37  import org.apache.roller.weblogger.business.FilePathException;
    38  import org.apache.roller.weblogger.business.Weblogger;
    39  import org.apache.roller.weblogger.business.WebloggerFactory;
    40  import org.apache.roller.weblogger.pojos.User;
    41  import org.apache.roller.weblogger.pojos.WeblogPermission;
    42  import org.apache.roller.weblogger.pojos.WeblogCategory;
    43  import org.apache.roller.weblogger.pojos.WeblogEntry;
    44  import org.apache.roller.weblogger.pojos.Weblog;
    45  import org.apache.roller.weblogger.util.Utilities;
    46  import org.apache.roller.weblogger.util.WSSEUtilities;
    47  import com.sun.syndication.feed.atom.Content;
    48  import com.sun.syndication.feed.atom.Category;
    49  import com.sun.syndication.feed.atom.Entry;
    50  import com.sun.syndication.feed.atom.Feed;
    51  import com.sun.syndication.feed.atom.Link;
    52  import com.sun.syndication.feed.atom.Person;
    53  import java.text.SimpleDateFormat;
    54  import java.util.Comparator;
    55  import java.util.Map;
    56  import java.util.SortedSet;
    57  import java.util.TreeSet;
    58  import java.util.UUID;
    59  import javax.activation.FileTypeMap;
    60  import org.apache.commons.lang.StringUtils;
    61  import org.apache.roller.weblogger.WebloggerException;
    62  import org.apache.roller.weblogger.business.FileIOException;
    63  import org.apache.roller.weblogger.business.URLStrategy;
    64  import org.apache.roller.weblogger.business.UserManager;
    65  import org.apache.roller.weblogger.config.WebloggerConfig;
    66  import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
    67  import org.apache.roller.weblogger.business.WeblogManager;
    68  import org.apache.roller.weblogger.business.search.IndexManager;
    69  import org.apache.roller.weblogger.pojos.RuntimeConfigProperty;
    70  import org.apache.roller.weblogger.pojos.WeblogEntryTag;
    71  import org.apache.roller.weblogger.pojos.ThemeResource;
    72  import org.apache.roller.weblogger.util.cache.CacheManager;
    73  
    74  /**
    75   * Weblogger's ROME-based Atom Protocol implementation.
    76   * 
    77   * Each Weblogger workspace has two collections, one that accepts entries and 
    78   * that accepts everything. The entries collection represents the weblog 
    79   * entries in a single weblog and the everything collection represents that 
    80   * weblog's uploaded-files. 
    81   * 
    82   * Here are the APP URIs suppored by Weblogger:
    83   * 
    84   * <pre>
    85   *    /roller-services/app
    86   *    Introspection doc
    87   * 
    88   *    /roller-services/app/[weblog-handle>/entries
    89   *    Entry collection for a blog
    90   * 
    91   *    /roller-services/app/[weblog-handle]/entries/[offset]
    92   *    Entry collection for a blog, with offset
    93   * 
    94   *    /roller-services/app/[weblog-handle]/entry/[id]
    95   *    Individual entry (i.e. edit URI)
    96   * 
    97   *    /roller-services/app/[weblog-handle]/resources
    98   *    Resource (i.e. file-uploads) collection for a blog
    99   * 
   100   *    /roller-services/app/[weblog-handle]/resources/[offset]
   101   *    Resource collection for a blog, with offset
   102   * 
   103   *    /roller-services/app/[weblog-handle]/resource/*.media-link[name]
   104   *    Individual resource metadata (i.e. edit URI)
   105   * 
   106   *    /roller-services/app/[weblog-handle]/resource/[name]
   107   *    Individual resource data (i.e. media-edit URI)
   108   * 
   109   * </pre>
   110   * 
   111   * @author David M Johnson
   112   */
   113  public class RollerAtomHandler implements AtomHandler {
   114      private Weblogger roller;
   115      private User      user;
   116      private int       maxEntries = 20;
   117      
   118      private final String atomURL;
   119      
             /* 
    P/P       *  Method: org.apache.roller.weblogger.webservices.atomprotocol.RollerAtomHandler__static_init
              * 
              *  Presumptions:
              *    org.apache.commons.logging.LogFactory:getFactory(...)@122 != null
              * 
              *  Postconditions:
              *    init'ed(log)
              *    init'ed(throttle)
              */
   120      private static boolean throttle = true;
   121      
   122      private static Log log =
   123              LogFactory.getFactory().getInstance(RollerAtomHandler.class);
   124      
   125      static {
   126          throttle = WebloggerConfig
   127              .getBooleanProperty("webservices.atomprotocol.oneSecondThrottle");
   128      }
   129      
   130      //---------------------------------------------------------------- construction
   131      
   132      /**
   133       * Create Atom handler for a request and attempt to authenticate user.
   134       * If user is authenticated, then getAuthenticatedUsername() will return
   135       * then user's name, otherwise it will return null.
   136       */
             /* 
    P/P       *  Method: void org.apache.roller.weblogger.webservices.atomprotocol.RollerAtomHandler(HttpServletRequest)
              * 
              *  Preconditions:
              *    (soft) log != null
              *    (soft) request != null
              * 
              *  Presumptions:
              *    org.apache.roller.weblogger.business.Weblogger:getUrlStrategy(...)@151 != null
              *    org.apache.roller.weblogger.business.Weblogger:getUserManager(...)@145 != null
              *    org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@138 != null
              *    org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@151 != null
              * 
              *  Postconditions:
              *    init'ed(this.atomURL)
              *    this.maxEntries == 20
              *    (soft) this.roller != null
              *    init'ed(this.user)
              */
   137      public RollerAtomHandler(HttpServletRequest request) {
   138          roller = WebloggerFactory.getWeblogger();
   139          
   140          // TODO: decide what to do about authentication, is WSSE going to fly?
   141          //String userName = authenticateWSSE(request);
   142          String userName = authenticateBASIC(request);
   143          if (userName != null) {
   144              try {
   145                  this.user = roller.getUserManager().getUserByUserName(userName);
   146              } catch (Exception neverHappen) {
   147                  log.debug("Getting user", neverHappen);
   148              } 
   149          }
   150          
   151          atomURL = WebloggerFactory.getWeblogger().getUrlStrategy().getAtomProtocolURL(true);
   152      }
   153      
   154      /**
   155       * Return weblogHandle of authenticated user or null if there is none.
   156       */
   157      public String getAuthenticatedUsername() {
                 /* 
    P/P           *  Method: String getAuthenticatedUsername()
                  * 
                  *  Preconditions:
                  *    init'ed(this.user)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    this.user: Addr_Set{null}, Inverse{null}
                  */
   158          String ret = null;
   159          if (this.user != null) {
   160              ret = user.getUserName();
   161          }
   162          return ret;
   163      }
   164      
   165      //---------------------------------------------------------------- introspection
   166      
   167      /**
   168       * Return Atom service document for site, getting blog-name from pathInfo.
   169       * The workspace will contain collections for entries, categories and resources.
   170       */
   171      public AtomService getIntrospection() throws AtomException {
                 /* 
    P/P           *  Method: AtomService getIntrospection()
                  * 
                  *  Preconditions:
                  *    log != null
                  *    this.roller != null
                  *    init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    dirs.length@239 <= 232-1
                  *    java.lang.Boolean.TRUE != null
                  *    java.util.Iterator:next(...)@188 != null
                  *    java.util.Iterator:next(...)@211 != null
                  *    org.apache.roller.weblogger.business.FileManager:getDirectories(...)@239 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    return_value == &new AtomService(getIntrospection#1)
                  *    new ArrayList(AtomService#1) num objects == 1
                  *    new AtomService(getIntrospection#1) num objects == 1
                  *    new AtomService(getIntrospection#1).workspaces == &new ArrayList(AtomService#1)
                  * 
                  *  Test Vectors:
                  *    java.lang.Boolean:equals(...)@191: {1}, {0}
                  *    java.util.Iterator:hasNext(...)@187: {0}, {1}
                  *    java.util.Iterator:hasNext(...)@210: {0}, {1}
                  *    org.apache.roller.weblogger.business.UserManager:getAllPermissions(...)@176: Addr_Set{null}, Inverse{null}
                  */
   172          log.debug("Entering");
   173          AtomService service = new AtomService();
   174          List perms = null;
   175          try {
   176              perms = roller.getUserManager().getAllPermissions(user);
   177          } catch (WebloggerException re) {
   178              throw new AtomException("Getting user's weblogs", re);
   179          }
+  180          List uploadAccepts = new ArrayList();
   181          try {           
   182              uploadAccepts = getAcceptedContentTypeRange();
   183          } catch (WebloggerException re) {
   184              throw new AtomException("Getting site's accept range", re);
   185          }
   186          if (perms != null) {
   187              for (Iterator iter=perms.iterator(); iter.hasNext();) {
   188                  WeblogPermission perm = (WeblogPermission)iter.next();
   189                  
   190                  // only include weblog's that have client API support enabled
   191                  if (!Boolean.TRUE.equals(perm.getWebsite().getEnableBloggerApi())) continue;
   192                                  
   193                  // Create workspace to represent weblog
   194                  Workspace workspace = new Workspace(
   195                      Utilities.removeHTML(perm.getWebsite().getName()), "text");
   196                  service.addWorkspace(workspace);
   197                  
   198                  // Create collection for entries within that workspace
   199                  String handle = perm.getWebsite().getHandle();
   200                  Collection entryCol = new Collection("Weblog Entries", "text", 
   201                      atomURL+"/"+handle+"/entries");
   202                  entryCol.addAccept("application/atom+xml;type=entry");
   203                  try {  
   204                      // Add fixed categories using scheme that points to 
   205                      // weblog because categories are weblog specific
   206                      Categories cats = new Categories();
   207                      cats.setFixed(true);
   208                      cats.setScheme(getWeblogCategoryScheme(perm.getWebsite()));
   209                      List rollerCats = roller.getWeblogManager().getWeblogCategories(perm.getWebsite(), false);
   210                      for (Iterator it = rollerCats.iterator(); it.hasNext();) {
   211                          WeblogCategory rollerCat = (WeblogCategory)it.next();
   212                          Category cat = new Category();
   213                          cat.setTerm(rollerCat.getPath().substring(1));
   214                          cat.setLabel(rollerCat.getName());
   215                          cats.addCategory(cat);
   216                      } 
   217                      entryCol.addCategories(cats);
   218                      
   219                      // Add tags as free-form categories using scheme that points
   220                      // to site because tags can be considered site-wide
   221                      Categories tags = new Categories();
   222                      tags.setFixed(false);
   223                      entryCol.addCategories(tags);
   224                      
   225                  } catch (Exception e) {
   226                      throw new AtomException("Fetching weblog categories");
   227                  }                               
   228                  workspace.addCollection(entryCol);
   229  
   230                  // Add media collection for upload dir
   231                  Collection uploadCol = new Collection("Media Files", "text", 
   232                      atomURL+"/"+handle+"/resources/");
   233                  uploadCol.setAccepts(uploadAccepts);
   234                  workspace.addCollection(uploadCol);
   235  
   236                  // And add one media collection for each of weblog's upload sub-directories
   237                  ThemeResource[] dirs;
   238                  try {
   239                      dirs = roller.getFileManager().getDirectories(perm.getWebsite());
   240                      for (int i=0; i<dirs.length; i++) {
+  241                          Collection uploadSubCol = new Collection(
   242                              "Media Files: " + dirs[i].getPath(), "text",
   243                              atomURL+"/"+handle+"/resources/" + dirs[i].getPath());
   244                          uploadSubCol.setAccepts(uploadAccepts);
   245                          workspace.addCollection(uploadSubCol);
   246                      }
   247                  } catch (FilePathException fpe) {
   248                      throw new AtomException("Getting uploads directories information", fpe);
   249                  } catch (FileNotFoundException fnfe) {
   250                      throw new AtomException("Getting uploads directories information", fnfe);
   251                  }
   252  
   253              }
   254          }
   255          log.debug("Exiting");
   256          return service;
   257      }
   258      
   259      /**
   260       * Build accept range by taking things that appear to be content-type rules 
   261       * from site's file-upload allowed extensions.
   262       */
   263      private List getAcceptedContentTypeRange() throws WebloggerException {
                 /* 
    P/P           *  Method: List getAcceptedContentTypeRange()
                  * 
                  *  Presumptions:
                  *    java.util.Map:get(...)@267 != null
                  *    org.apache.commons.lang.StringUtils:split(...)@268 != null
                  *    org.apache.roller.weblogger.business.PropertiesManager:getProperties(...)@266 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getPropertiesManager(...)@266 != null
                  *    org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@265 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    return_value == &new ArrayList(getAcceptedContentTypeRange#1)
                  *    new ArrayList(getAcceptedContentTypeRange#1) num objects == 1
                  */
   264          List accepts = new ArrayList();
   265          Weblogger roller = WebloggerFactory.getWeblogger();
   266          Map config = roller.getPropertiesManager().getProperties();        
   267          String allows = ((RuntimeConfigProperty)config.get("uploads.types.allowed")).getValue();
   268          String[] rules = StringUtils.split(StringUtils.deleteWhitespace(allows), ",");
   269          for (int i=0; i<rules.length; i++) {
+  270              if (rules[i].indexOf("/") == -1) continue;
   271              accepts.add(rules[i]);
   272          }
   273          return accepts;             
   274      }   
   275      
   276      //----------------------------------------------------------------- collections
   277      
   278      /**
   279       * Return collection specified by pathinfo.
   280       * <pre>
   281       * Supports these URI forms:
   282       *    /<blog-name>/entries
   283       *    /<blog-name>/entries/offset
   284       *    /<blog-name>/resources
   285       *    /<blog-name>/resources/offset
   286       * </pre>
   287       */
   288      public Feed getCollection(String[] pathInfo) throws AtomException {
                 /* 
    P/P           *  Method: Feed getCollection(String[])
                  * 
                  *  Preconditions:
                  *    log != null
                  *    pathInfo[1] != null
                  *    pathInfo != null
                  *    this.roller != null
                  *    (soft) pathInfo[2] != null
                  *    (soft) init'ed(pathInfo[...])
                  *    (soft) pathInfo.length in 2..232-1
                  *    (soft) init'ed(pathInfo[0])
                  *    (soft) this.maxEntries <= 232-2
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    java.lang.String:equals(...)@291 == 1
                  * 
                  *  Postconditions:
                  *    init'ed(pathInfo[1])
                  *    init'ed(pathInfo[2])
                  *    (soft) init'ed(pathInfo[...])
                  *    return_value in Addr_Set{&new Feed(getCollectionOfEntries#4),&new Feed(getCollectionOfResources#5)}
                  *    new Feed(getCollectionOfEntries#4) num objects <= 1
                  *    new Feed(getCollectionOfResources#5) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    java.lang.String:equals(...)@289: {0}, {1}
                  */
   289          if (pathInfo.length > 0 && pathInfo[1].equals("entries")) {
   290              return getCollectionOfEntries(pathInfo);
   291          } else if (pathInfo.length > 0 && pathInfo[1].equals("resources")) {
   292              return getCollectionOfResources(pathInfo);
   293          }
   294          throw new AtomNotFoundException("Cannot find collection specified");
   295      }
   296      
   297      /**
   298       * Helper method that returns collection of entries, called by getCollection().
   299       */
   300      public Feed getCollectionOfEntries(String[] pathInfo) throws AtomException {
                 /* 
    P/P           *  Method: Feed getCollectionOfEntries(String[])
                  * 
                  *  Preconditions:
                  *    log != null
                  *    pathInfo != null
                  *    pathInfo.length >= 1
                  *    init'ed(pathInfo[0])
                  *    this.maxEntries <= 232-2
                  *    this.roller != null
                  *    (soft) pathInfo[2] != null
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    java.util.Iterator:next(...)@350 != null
                  *    org.apache.roller.weblogger.business.UserManager:getWebsiteByHandle(...)@315 != null
                  *    org.apache.roller.weblogger.business.WeblogManager:getWeblogEntries(...)@322 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getUserManager(...)@315 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getWeblogManager(...)@322 != null
                  * 
                  *  Postconditions:
                  *    return_value == &new Feed(getCollectionOfEntries#4)
                  *    new Feed(getCollectionOfEntries#4) num objects == 1
                  * 
                  *  Test Vectors:
                  *    pathInfo.length: {1,2}, {3..+Inf}
                  *    java.util.Iterator:hasNext(...)@349: {0}, {1}
                  *    java.util.List:size(...)@377: {-231..0}, {1..232-1}
                  */
   301          log.debug("Entering");
   302          try {
   303              int start = 0;
   304              int max = maxEntries;
   305              if (pathInfo.length > 2) {
   306                  try {
   307                      String s = pathInfo[2].trim();
   308                      start = Integer.parseInt(s);
   309                  } catch (Throwable t) {
   310                      log.warn("Unparsable range: " + pathInfo[2]);
   311                  }
   312              }        
   313              String handle = pathInfo[0];
   314              String absUrl = WebloggerRuntimeConfig.getAbsoluteContextURL();
   315              Weblog website = roller.getUserManager().getWebsiteByHandle(handle);
   316              if (website == null) {
   317                  throw new AtomNotFoundException("Cannot find specified weblog");
   318              }
   319              if (!canView(website)) {
+  320                  throw new AtomNotAuthorizedException("Not authorized to access website: " + handle);
   321              }
   322              List entries = roller.getWeblogManager().getWeblogEntries( 
   323                      website,           // website
   324                      null,              // user
   325                      null,              // startDate
   326                      null,              // endDate
   327                      null,              // catName
   328                      null,              // tags
   329                      null,              // status
   330                      null,              // text
   331                      "updateTime",      // sortby
   332                      null,
   333                      null,              // locale
   334                      start,             // offset (for range paging)
   335                      max + 1);          // maxEntries
   336              Feed feed = new Feed();
   337              feed.setId(atomURL
   338                  +"/"+website.getHandle() + "/entries/" + start);
   339              feed.setTitle(website.getName());
   340  
   341              Link link = new Link();
   342              link.setHref(absUrl + "/" + website.getHandle());
   343              link.setRel("alternate");
   344              link.setType("text/html");
   345              feed.setAlternateLinks(Collections.singletonList(link));
   346  
   347              List atomEntries = new ArrayList();
   348              int count = 0;
   349              for (Iterator iter = entries.iterator(); iter.hasNext() && count < maxEntries; count++) {
   350                  WeblogEntry rollerEntry = (WeblogEntry)iter.next();
   351                  Entry entry = createAtomEntry(rollerEntry);
   352                  atomEntries.add(entry);
   353                  if (count == 0) {
   354                      // first entry is most recent
   355                      feed.setUpdated(entry.getUpdated());
   356                  }
   357              }
   358              List links = new ArrayList();
   359              if (entries.size() > max) { // add next link
   360                  int nextOffset = start + max;
   361                  String url = atomURL+"/"
   362                          + website.getHandle() + "/entries/" + nextOffset;
   363                  Link nextLink = new Link();
   364                  nextLink.setRel("next");
   365                  nextLink.setHref(url);
   366                  links.add(nextLink);
   367              }
   368              if (start > 0) { // add previous link
   369                  int prevOffset = start > max ? start - max : 0;
   370                  String url = atomURL+"/"
   371                          +website.getHandle() + "/entries/" + prevOffset;
   372                  Link prevLink = new Link();
   373                  prevLink.setRel("previous");
   374                  prevLink.setHref(url);
   375                  links.add(prevLink);
   376              }
   377              if (links.size() > 0) feed.setOtherLinks(links);
   378              // Use collection URI as id
   379              feed.setEntries(atomEntries);
   380              
   381              log.debug("Exiting");
   382              return feed;
   383          
   384          } catch (WebloggerException re) {
   385              throw new AtomException("Getting entry collection");
   386          }
   387      }
   388      
   389      /**
   390       * Helper method that returns collection of resources, called by getCollection().
   391       *   /handle/resources/offset
   392       *   /handle/resources/path/offset
   393       */
   394      public Feed getCollectionOfResources(String[] rawPathInfo) throws AtomException {
                 /* 
    P/P           *  Method: Feed getCollectionOfResources(String[])
                  * 
                  *  Preconditions:
                  *    log != null
                  *    rawPathInfo != null
                  *    init'ed(this.maxEntries)
                  *    this.roller != null
                  *    (soft) init'ed(rawPathInfo[...])
                  *    (soft) rawPathInfo.length in 1..232-1
                  *    (soft) init'ed(rawPathInfo[0])
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    files.length@434 <= 232-1
                  *    init'ed(java.io.File.separator)
                  *    java.lang.Integer:parseInt(...)@402 >= 0
                  *    java.util.SortedSet:size(...)@451 >= 0
                  *    java.util.SortedSet:toArray(...)@451 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    (soft) init'ed(rawPathInfo[...])
                  *    return_value == &new Feed(getCollectionOfResources#5)
                  *    new Feed(getCollectionOfResources#5) num objects == 1
                  * 
                  *  Test Vectors:
                  *    rawPathInfo.length: {1,2}, {3..232-1}
                  *    java.lang.String:equals(...)@410: {1}, {0}
                  *    org.apache.roller.weblogger.business.FileManager:getFiles(...)@434: Addr_Set{null}, Inverse{null}
                  */
   395          log.debug("Entering");
   396          try {
   397              int start = 0;
   398              int max = maxEntries;
   399              String[] pathInfo = rawPathInfo;
   400              if (rawPathInfo.length > 2) {
   401                  try {
   402                      start = Integer.parseInt(rawPathInfo[rawPathInfo.length - 1]);
   403                      pathInfo = new String[rawPathInfo.length - 1];
   404                      for (int i=0; i<rawPathInfo.length - 1; i++) {
   405                          pathInfo[i] = rawPathInfo[i];
   406                      }
   407                  } catch (Exception ingored) {}
   408              }
   409              String path = filePathFromPathInfo(pathInfo);
+  410              if (!path.equals("")) path = path + File.separator;
   411              
   412              String handle = pathInfo[0];
   413              String absUrl = WebloggerRuntimeConfig.getAbsoluteContextURL();
   414              Weblog website = roller.getUserManager().getWebsiteByHandle(handle);
   415              if (website == null) {
   416                  throw new AtomNotFoundException("Cannot find weblog: " + handle);
   417              }
+  418              if (!canView(website)) {
   419                  throw new AtomNotAuthorizedException("Not authorized to access website");
   420              }
   421                          
   422              Feed feed = new Feed();
   423              feed.setId(atomURL
   424                  +"/"+website.getHandle() + "/resources/" + path + start);                
   425              feed.setTitle(website.getName());
   426  
   427              Link link = new Link();
   428              link.setHref(absUrl + "/" + website.getHandle());
   429              link.setRel("alternate");
   430              link.setType("text/html");
   431              feed.setAlternateLinks(Collections.singletonList(link));
   432  
   433              FileManager fmgr = roller.getFileManager();
   434              ThemeResource[] files = fmgr.getFiles(website, path);
   435  
                     /* 
    P/P               *  Method: void org.apache.roller.weblogger.webservices.atomprotocol.RollerAtomHandler$1(RollerAtomHandler)
                      */
   436              SortedSet sortedSet = new TreeSet(new Comparator() {
   437                  public int compare(Object o1, Object o2) {
                             /* 
    P/P                       *  Method: int compare(Object, Object)
                              * 
                              *  Preconditions:
                              *    o1 != null
                              *    o2 != null
                              * 
                              *  Postconditions:
                              *    return_value in -1..1
                              */
   438                      ThemeResource f1 = (ThemeResource)o1;
   439                      ThemeResource f2 = (ThemeResource)o2;
   440                      if (f1.getLastModified() < f2.getLastModified()) return 1;
   441                      else if (f1.getLastModified() == f2.getLastModified()) return 0;
   442                      else return -1;
   443                  }
   444              });
   445                                      
   446              if (files != null && start < files.length) {  
   447                  for (int j=0; j<files.length; j++) {
   448                      sortedSet.add(files[j]);
   449                  }
   450                  int count = 0;
   451                  ThemeResource[] sortedResources = 
   452                     (ThemeResource[])sortedSet.toArray(new ThemeResource[sortedSet.size()]);
   453                  List atomEntries = new ArrayList();
+  454                  for (int i=start; i<(start + max) && i<(sortedResources.length); i++) {
+  455                      Entry entry = createAtomResourceEntry(website, sortedResources[i]);
   456                      atomEntries.add(entry);
   457                      if (count == 0) {
   458                          // first entry is most recent
   459                          feed.setUpdated(entry.getUpdated());
   460                      }
+  461                      count++;
   462                  }
   463  
   464                  List otherLinks = new ArrayList();
   465                  if (start + count < files.length) { // add next link
   466                      int nextOffset = start + max;
   467                      String url = atomURL
   468                          +"/"+ website.getHandle() + "/resources/" + path + nextOffset;
   469                      Link nextLink = new Link();
   470                      nextLink.setRel("next");
   471                      nextLink.setHref(url);
   472                      otherLinks.add(nextLink);
   473                  }
   474                  if (start > 0) { // add previous link
   475                      int prevOffset = start > max ? start - max : 0;
   476                      String url = atomURL
   477                          +"/"+website.getHandle() + "/resources/" + path + prevOffset;
   478                      Link prevLink = new Link();
   479                      prevLink.setRel("previous");
   480                      prevLink.setHref(url);
   481                      otherLinks.add(prevLink);
   482                  }
   483                  feed.setOtherLinks(otherLinks);
   484                  feed.setEntries(atomEntries);
   485              }
   486              
   487              log.debug("Existing");
   488              return feed;
   489         
   490          } catch (WebloggerException re) {
   491              throw new AtomException("Getting resource collection");
   492          }
   493      }
   494      
   495      //--------------------------------------------------------------------- entries
   496  
   497      /**
   498       * Create entry in the entry collection (a Weblogger blog has only one).
   499       */
   500      public Entry postEntry(String[] pathInfo, Entry entry) throws AtomException {
                 /* 
    P/P           *  Method: Entry postEntry(String[], Entry)
                  * 
                  *  Preconditions:
                  *    entry != null
                  *    log != null
                  *    pathInfo != null
                  *    pathInfo.length >= 1
                  *    init'ed(pathInfo[0])
                  *    this.roller != null
                  *    init'ed(throttle)
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    org.apache.roller.weblogger.business.UserManager:getWebsiteByHandle(...)@505 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getIndexManager(...)@527 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getUserManager(...)@505 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getWeblogManager(...)@517 != null
                  * 
                  *  Postconditions:
                  *    return_value == &new Entry(createAtomEntry#1)
                  *    new Entry(createAtomEntry#1) num objects == 1
                  * 
                  *  Test Vectors:
                  *    throttle: {0}, {1}
                  *    org.apache.roller.weblogger.pojos.WeblogEntry:isPublished(...)@526: {0}, {1}
                  */
   501          log.debug("Entering");
   502          try {
   503              // authenticated client posted a weblog entry
   504              String handle = pathInfo[0];
   505              Weblog website = 
   506                  roller.getUserManager().getWebsiteByHandle(handle);
   507              if (website == null) {
   508                  throw new AtomNotFoundException("Cannot find weblog: " + handle);
   509              }
   510              if (!canEdit(website)) {
+  511                  throw new AtomNotAuthorizedException("Not authorized to access website: " + handle);
   512              }
   513              
   514              if (throttle) oneSecondThrottle();
   515              
   516              // Save it and commit it
   517              WeblogManager mgr = roller.getWeblogManager();
   518              WeblogEntry rollerEntry = new WeblogEntry();
   519              rollerEntry.setWebsite(website);
   520              rollerEntry.setCreator(this.user);
   521              copyToRollerEntry(entry, rollerEntry);
   522              mgr.saveWeblogEntry(rollerEntry);
   523              roller.flush();
   524  
   525              CacheManager.invalidate(website);
   526              if (rollerEntry.isPublished()) {
   527                  roller.getIndexManager().addEntryReIndexOperation(rollerEntry);
   528              }
   529              
   530              log.debug("Exiting");
   531              return createAtomEntry(rollerEntry);
   532  
   533          } catch (WebloggerException re) {
   534              throw new AtomException("Posting entry", re);
   535          }
   536      }
   537      
   538      /**
   539       * Retrieve entry, URI like this /blog-name/entry/id
   540       */
   541      public Entry getEntry(String[] pathInfo) throws AtomException {
                 /* 
    P/P           *  Method: Entry getEntry(String[])
                  * 
                  *  Preconditions:
                  *    log != null
                  *    pathInfo != null
                  *    pathInfo[1] != null
                  *    this.roller != null
                  *    (soft) pathInfo.length in 3..232-1
                  *    (soft) init'ed(pathInfo[0])
                  *    (soft) pathInfo[2] != null
                  *    (soft) pathInfo[...] != null
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    java.lang.String:endsWith(...)@557 == 1
                  *    java.lang.String:equals(...)@557 == 1
                  *    java.lang.String:length(...)@559 - java.lang.String:length(...)@559 in -232+1..231
                  *    org.apache.roller.weblogger.business.FileManager:getFile(...)@563 != null
                  *    org.apache.roller.weblogger.business.UserManager:getWebsiteByHandle(...)@561 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    return_value in Addr_Set{&new Entry(createAtomResourceEntry#3),&new Entry(createAtomEntry#1)}
                  *    new Entry(createAtomEntry#1) num objects <= 1
                  *    new Entry(createAtomResourceEntry#3) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    java.lang.String:equals(...)@546: {0}, {1}
                  */
   542          log.debug("Entering");
   543          try {
   544              if (pathInfo.length > 2) // URI is /blogname/entries/entryid
   545              {
   546                  if (pathInfo[1].equals("entry")) {
   547                      WeblogEntry entry = 
   548                          roller.getWeblogManager().getWeblogEntry(pathInfo[2]);
   549                      if (entry == null) {
   550                          throw new AtomNotFoundException("Cannot find specified entry/resource");
   551                      }
+  552                      if (!canView(entry)) {
   553                          throw new AtomNotAuthorizedException("Not authorized to view entry");
   554                      } else {
   555                          return createAtomEntry(entry);
   556                      }
   557                  } else if (pathInfo[1].equals("resource") && pathInfo[pathInfo.length - 1].endsWith(".media-link")) {
   558                      String filePath = filePathFromPathInfo(pathInfo);
+  559                      filePath = filePath.substring(0, filePath.length() - ".media-link".length());
   560                      String handle = pathInfo[0];
   561                      Weblog website = 
   562                          roller.getUserManager().getWebsiteByHandle(handle);                    
   563                      ThemeResource resource = 
   564                          roller.getFileManager().getFile(website, filePath);
   565                      
   566                      log.debug("Exiting");
   567                      if (resource != null) return createAtomResourceEntry(website, resource);
   568                  }
   569              }
   570              throw new AtomNotFoundException("Cannot find specified entry/resource");
   571          } catch (WebloggerException re) {
   572              throw new AtomException("Getting entry");
   573          }
   574      }
   575      
   576      /**
   577       * Expects pathInfo of form /blog-name/resource/path/name
   578       */
   579      public AtomMediaResource getMediaResource(String[] pathInfo) throws AtomException {
                 /* 
    P/P           *  Method: AtomMediaResource getMediaResource(String[])
                  * 
                  *  Preconditions:
                  *    log != null
                  *    pathInfo != null
                  *    pathInfo.length in 2..232-1
                  *    init'ed(pathInfo[0])
                  *    this.roller != null
                  *    (soft) init'ed(pathInfo[...])
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    org.apache.roller.weblogger.business.FileManager:getFile(...)@595 != null
                  *    org.apache.roller.weblogger.business.UserManager:getWebsiteByHandle(...)@587 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getFileManager(...)@585 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getUserManager(...)@586 != null
                  * 
                  *  Postconditions:
                  *    return_value == &new AtomMediaResource(getMediaResource#3)
                  *    new AtomMediaResource(getMediaResource#3) num objects == 1
                  *    init'ed(new AtomMediaResource(getMediaResource#3).contentLength)
                  *    init'ed(new AtomMediaResource(getMediaResource#3).contentType)
                  *    init'ed(new AtomMediaResource(getMediaResource#3).inputStream)
                  *    new AtomMediaResource(getMediaResource#3).lastModified == &new Date(AtomMediaResource#1)
                  *    new Date(AtomMediaResource#1) num objects == 1
                  */
   580          log.debug("Entering");
   581          try {
   582              // authenticated client posted a weblog entry
   583              File tempFile = null;
   584              String handle = pathInfo[0];
   585              FileManager fmgr = roller.getFileManager();
   586              UserManager umgr = roller.getUserManager();
   587              Weblog website = umgr.getWebsiteByHandle(handle);
   588              if (!canEdit(website)) {
+  589                  throw new AtomNotAuthorizedException("Not authorized to edit weblog: " + handle);
   590              }
   591              if (pathInfo.length > 1) {
   592                  try {                                        
   593                      // Parse pathinfo to determine file path
   594                      String filePath = filePathFromPathInfo(pathInfo);
   595                      ThemeResource resource = fmgr.getFile(website, filePath);                    
   596                      return new AtomMediaResource(resource);
   597                  } catch (Exception e) {
   598                      throw new AtomException(
   599                          "Unexpected error during file upload", e);
   600                  }
   601              }
   602              throw new AtomException("Incorrect path information");
   603          
   604          } catch (WebloggerException re) {
   605              throw new AtomException("Posting media");
   606          }
   607      }
   608      
   609      /**
   610       * Update entry, URI like this /blog-name/entry/id
   611       */
   612      public Entry putEntry(String[] pathInfo, Entry entry) throws AtomException {
                 /* 
    P/P           *  Method: Entry putEntry(String[], Entry)
                  * 
                  *  Preconditions:
                  *    entry != null
                  *    log != null
                  *    pathInfo != null
                  *    pathInfo.length == 3
                  *    init'ed(pathInfo[2])
                  *    this.roller != null
                  *    init'ed(throttle)
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    org.apache.roller.weblogger.business.WeblogManager:getWeblogEntry(...)@617 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getIndexManager(...)@635 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getWeblogManager(...)@617 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getWeblogManager(...)@627 != null
                  * 
                  *  Postconditions:
                  *    return_value == &new Entry(createAtomEntry#1)
                  *    new Entry(createAtomEntry#1) num objects == 1
                  * 
                  *  Test Vectors:
                  *    throttle: {0}, {1}
                  *    org.apache.roller.weblogger.pojos.WeblogEntry:isPublished(...)@634: {0}, {1}
                  */
   613          log.debug("Entering");
   614          try {
   615              if (pathInfo.length == 3) // URI is /blogname/entries/entryid
   616              {
   617                  WeblogEntry rollerEntry =
   618                      roller.getWeblogManager().getWeblogEntry(pathInfo[2]);
   619                  if (rollerEntry == null) {
   620                      throw new AtomNotFoundException(
   621                          "Cannot find specified entry/resource");  
   622                  }
+  623                  if (canEdit(rollerEntry)) {
   624              
   625                      if (throttle) oneSecondThrottle();
   626                      
   627                      WeblogManager mgr = roller.getWeblogManager();
   628                      copyToRollerEntry(entry, rollerEntry);
   629                      rollerEntry.setUpdateTime(new Timestamp(new Date().getTime()));
   630                      mgr.saveWeblogEntry(rollerEntry);
   631                      roller.flush();
   632                      
   633                      CacheManager.invalidate(rollerEntry.getWebsite());
   634                      if (rollerEntry.isPublished()) {
   635                          roller.getIndexManager().addEntryReIndexOperation(rollerEntry);
   636                      }
   637                      log.debug("Exiting");
   638                      return createAtomEntry(rollerEntry);
   639                  }
   640                  throw new AtomNotAuthorizedException("ERROR not authorized to update entry");
   641              }
   642              throw new AtomNotFoundException("Cannot find specified entry/resource");
   643              
   644          } catch (WebloggerException re) {
   645              throw new AtomException("Updating entry");
   646          }
   647      }
   648      
   649      /**
   650       * Delete entry, URI like this /blog-name/entry/id
   651       */
   652      public void deleteEntry(String[] pathInfo) throws AtomException {
                 /* 
    P/P           *  Method: void deleteEntry(String[])
                  * 
                  *  Preconditions:
                  *    log != null
                  *    pathInfo != null
                  *    pathInfo[1] != null
                  *    this.roller != null
                  *    (soft) pathInfo.length in 3..232-1
                  *    (soft) init'ed(pathInfo[0])
                  *    (soft) init'ed(pathInfo[2])
                  *    (soft) init'ed(pathInfo[...])
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    java.lang.String:equals(...)@671 == 1
                  *    java.lang.String:length(...)@680 - java.lang.String:length(...)@680 in -232+1..231
                  *    org.apache.roller.weblogger.business.UserManager:getWebsiteByHandle(...)@673 != null
                  *    org.apache.roller.weblogger.business.WeblogManager:getWeblogEntry(...)@658 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getFileManager(...)@681 != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    java.lang.String:equals(...)@656: {0}, {1}
                  */
   653          log.debug("Entering");
   654          try {
   655              if (pathInfo.length > 2) {
   656                  if (pathInfo[1].equals("entry")) // URI is /blogname/entry/entryid
   657                  {                    
   658                      WeblogEntry rollerEntry = roller.getWeblogManager().getWeblogEntry(pathInfo[2]);
   659                      if (rollerEntry == null) {
   660                          throw new AtomNotFoundException("cannot find specified entry/resource");
   661                      }
   662                      if (canEdit(rollerEntry)) {
   663                          WeblogManager mgr = roller.getWeblogManager();                                                
   664                          CacheManager.invalidate(rollerEntry.getWebsite());                        
   665                          reindexEntry(rollerEntry);
   666                          mgr.removeWeblogEntry(rollerEntry);
   667                          log.debug("Deleted entry:" + rollerEntry.getAnchor());
   668                          roller.flush();
   669                          return;
   670                      } 
   671                  } else if (pathInfo[1].equals("resource")) {
   672                      String handle = pathInfo[0];
   673                      Weblog website = roller.getUserManager().getWebsiteByHandle(handle);
   674                      if (website == null) {
   675                          throw new AtomNotFoundException("cannot find specified weblog");
   676                      }
+  677                      if (canEdit(website) && pathInfo.length > 1) {
   678                          try {                            
   679                              String path = filePathFromPathInfo(pathInfo);
+  680                              String fileName = path.substring(0, path.length() - ".media-link".length());
   681                              FileManager fmgr = roller.getFileManager();
   682                              fmgr.deleteFile(website, fileName);
   683                              log.debug("Deleted resource: " + fileName);
   684                          } catch (Exception e) {
   685                              String msg = "ERROR in atom.deleteResource";
   686                              log.error(msg,e);
   687                              throw new AtomException(msg);
   688                          }
   689                          return;
   690                      }               
   691                  }
+  692                  throw new AtomNotAuthorizedException("ERROR not authorized to delete entry");
   693              }
   694              throw new AtomNotFoundException("cannot find specified entry/resource");
   695              
   696          } catch (WebloggerException re) {
   697              throw new AtomException("deleting entry");
   698          }
   699      }
   700      
   701      //-------------------------------------------------------------------- resources
   702      
   703      /**
   704       * Create new resource in generic collection (a Weblogger blog has only one).
   705       * TODO: can we avoid saving temporary file?
   706       * TODO: do we need to handle mutli-part MIME uploads?
   707       * TODO: use Jakarta Commons File-upload?
   708       */
   709      public Entry postMedia(String[] pathInfo,
   710              String title, String slug, String contentType, InputStream is)
   711              throws AtomException {
                 /* 
    P/P           *  Method: Entry postMedia(String[], String, String, String, InputStream)
                  * 
                  *  Preconditions:
                  *    log != null
                  *    pathInfo != null
                  *    pathInfo.length in 2..232-1
                  *    init'ed(pathInfo[0])
                  *    this.roller != null
                  *    (soft) contentType != null
                  *    (soft) init'ed(pathInfo[...])
                  *    (soft) init'ed(this.user)
                  * 
                  *  Presumptions:
                  *    init'ed(java.io.File.separator)
                  *    java.io.File:createTempFile(...)@728 != null
                  *    org.apache.roller.weblogger.business.FileManager:getFile(...)@741 != null
                  *    org.apache.roller.weblogger.business.UserManager:getWebsiteByHandle(...)@719 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getFileManager(...)@717 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    return_value == &new Entry(createAtomResourceEntry#3)
                  *    new Entry(createAtomResourceEntry#3) num objects == 1
                  * 
                  *  Test Vectors:
                  *    java.lang.String:length(...)@736: {0}, {1..232-1}
                  */
   712          log.debug("Entering");
   713          try {
   714              // authenticated client posted a weblog entry
   715              File tempFile = null;
   716              String handle = pathInfo[0];
   717              FileManager fmgr = roller.getFileManager();
   718              UserManager umgr = roller.getUserManager();
   719              Weblog website = umgr.getWebsiteByHandle(handle);
   720              if (!canEdit(website)) {
+  721                  throw new AtomNotAuthorizedException("Not authorized to edit weblog: " + handle);
   722              }
   723              if (pathInfo.length > 1) {
   724                  // Save to temp file
   725                  String fileName = createFileName(website, 
   726                      (slug != null) ? slug : Utilities.replaceNonAlphanumeric(title,' '), contentType);
   727                  try {
   728                      tempFile = File.createTempFile(fileName, "tmp");
   729                      FileOutputStream fos = new FileOutputStream(tempFile);
   730                      Utilities.copyInputToOutput(is, fos);
   731                      fos.close();
   732                                          
   733                      // Parse pathinfo to determine file path
   734                      String path = filePathFromPathInfo(pathInfo);
   735                      
+  736                      if (path.length() > 0) path = path + File.separator;
   737                      FileInputStream fis = new FileInputStream(tempFile);  
   738                      fmgr.saveFile(website, path + fileName, contentType, tempFile.length(), fis);
   739                      fis.close();
   740                      
   741                      ThemeResource resource = fmgr.getFile(website, path + fileName);
   742                      
   743                      log.debug("Exiting");
   744                      return createAtomResourceEntry(website, resource);
   745  
   746                  } catch (FileIOException fie) {
   747                      throw new AtomException(
   748                          "File upload disabled, over-quota or other error", fie);
   749                  } catch (Exception e) {
   750                      throw new AtomException(
   751                          "Unexpected error during file upload", e);
   752                  } finally {
   753                      if (tempFile != null) tempFile.delete();
   754                  }
   755              }
   756              throw new AtomException("Incorrect path information");
   757          
   758          } catch (WebloggerException re) {
   759              throw new AtomException("Posting media");
   760          }
   761      }
   762      
   763      /**
   764       * Creates a file name for a file based on a weblog, title string and a 
   765       * content-type. 
   766       * 
   767       * @param weblog      Weblog for which file name is being created
   768       * @param title       Title to be used as basis for file name (or null)
   769       * @param contentType Content type of file (must not be null)
   770       * 
   771       * If a title is specified, the method will apply the same create-anchor 
   772       * logic we use for weblog entries to create a file name based on the title.
   773       *
   774       * If title is null, the base file name will be the weblog handle plus a 
   775       * YYYYMMDDHHSS timestamp. 
   776       *
   777       * The extension will be formed by using the part of content type that
   778       * comes after he slash. 
   779       *
   780       * For example:
   781       *    weblog.handle = "daveblog"
   782       *    title         = "Port Antonio"
   783       *    content-type  = "image/jpg"
   784       * Would result in port_antonio.jpg
   785       *
   786       * Another example:
   787       *    weblog.handle = "daveblog"
   788       *    title         = null
   789       *    content-type  = "image/jpg"
   790       * Might result in daveblog-200608201034.jpg
   791       */
   792      private String createFileName(Weblog weblog, String slug, String contentType) {
   793          
                 /* 
    P/P           *  Method: String createFileName(Weblog, String, String)
                  *    createFileName fails for all possible inputs
                  * 
                  *  Preconditions:
                  *    (soft) contentType != null
                  *    (soft) weblog != null
                  * 
                  *  Postconditions:
                  *    init'ed(java.lang.StringBuilder:toString(...)._tainted)
                  *    java.lang.StringBuilder:toString(...)._tainted == 0
                  *    init'ed(java.util.StringTokenizer:nextToken(...)._tainted)
                  *    return_value != null
                  * 
                  *  Test Vectors:
                  *    slug: Addr_Set{null}, Inverse{null}
                  *    java.lang.String:endsWith(...)@817: {1}, {0}
                  *    java.lang.String:equals(...)@806: {1}, {0}
                  *    java.util.StringTokenizer:hasMoreTokens(...)@811: {0}, {1}
                  */
   794          if (weblog == null) throw new IllegalArgumentException("weblog cannot be null");
   795          if (contentType == null) throw new IllegalArgumentException("contentType cannot be null");
   796          
   797          String fileName = null;
   798          
   799          // Determine the extension based on the contentType. This is a hack.
   800          // The info we need to map from contentType to file extension is in 
   801          // JRE/lib/content-type.properties, but Java Activation doesn't provide 
   802          // a way to do a reverse mapping or to get at the data.
   803          String[] typeTokens = contentType.split("/");
+  804          String ext = typeTokens[1];
   805          
   806          if (slug != null && !slug.trim().equals("")) {              
   807              // We've got a title, so use it to build file name
   808              StringTokenizer toker = new StringTokenizer(slug);
   809              String tmp = null;
   810              int count = 0;
   811              while (toker.hasMoreTokens() && count < 5) {
   812                  String s = toker.nextToken();
   813                  s = s.toLowerCase();
   814                  tmp = (tmp == null) ? s : tmp + "_" + s;
   815                  count++;
   816              }
+  817              if (!tmp.endsWith("." + ext)) {
   818                  fileName = tmp + "." + ext;
   819              } else {
   820                  fileName = tmp;
   821              }            
   822          } else {            
   823              // No title or text, so instead we'll use the item's date
   824              // in YYYYMMDD format to form the file name
   825              SimpleDateFormat sdf = new SimpleDateFormat();
   826              sdf.applyPattern("yyyyMMddHHSS");
   827              fileName = weblog.getHandle()+"-"+sdf.format(new Date())+"."+ext;
   828          }
   829          
   830          return fileName;
   831      }
   832      
   833      
   834      /**
   835       * Update resource specified by pathInfo using data from input stream.
   836       * Expects pathInfo of form /blog-name/resource/path/name
   837       */
   838      public Entry putMedia(String[] pathInfo,
   839              String contentType, InputStream is) throws AtomException {
   840          try {
   841              // authenticated client posted a weblog entry
                     /* 
    P/P               *  Method: Entry putMedia(String[], String, InputStream)
                      * 
                      *  Preconditions:
                      *    pathInfo != null
                      *    pathInfo.length in 2..232-1
                      *    init'ed(pathInfo[0])
                      *    this.roller != null
                      *    (soft) log != null
                      *    (soft) init'ed(pathInfo[...])
                      *    (soft) init'ed(this.user)
                      * 
                      *  Presumptions:
                      *    java.io.File:createTempFile(...)@853 != null
                      *    java.util.UUID:randomUUID(...)@853 != null
                      *    org.apache.roller.weblogger.business.FileManager:getFile(...)@862 != null
                      *    org.apache.roller.weblogger.business.UserManager:getWebsiteByHandle(...)@846 != null
                      *    org.apache.roller.weblogger.business.Weblogger:getFileManager(...)@844 != null
                      *    ...
                      * 
                      *  Postconditions:
                      *    return_value == &new Entry(createAtomResourceEntry#3)
                      *    new Entry(createAtomResourceEntry#3) num objects == 1
                      */
   842              File tempFile = null;
   843              String handle = pathInfo[0];
   844              FileManager fmgr = roller.getFileManager();
   845              UserManager umgr = roller.getUserManager();
   846              Weblog website = umgr.getWebsiteByHandle(handle);
   847              if (!canEdit(website)) {
+  848                  throw new AtomNotAuthorizedException("Not authorized to edit weblog: " + handle);
   849              }
   850              if (pathInfo.length > 1) {
   851                  // Save to temp file
   852                  try {
   853                      tempFile = File.createTempFile(UUID.randomUUID().toString(), "tmp");
   854                      FileOutputStream fos = new FileOutputStream(tempFile);
   855                      Utilities.copyInputToOutput(is, fos);
   856                      fos.close();
   857                                          
   858                      // Parse pathinfo to determine file path
   859                      String path = filePathFromPathInfo(pathInfo);
   860                      
   861                      // Attempt to load file, to ensure it exists
   862                      ThemeResource resource = fmgr.getFile(website, path);                    
   863                      
   864                      FileInputStream fis = new FileInputStream(tempFile);  
   865                      fmgr.saveFile(website, path, contentType, tempFile.length(), fis);
   866                      fis.close();
   867                      
   868                      log.debug("Exiting");
   869                      return createAtomResourceEntry(website, resource);
   870  
   871                  } catch (FileIOException fie) {
   872                      throw new AtomException(
   873                          "File upload disabled, over-quota or other error", fie);
   874                  } catch (Exception e) {
   875                      throw new AtomException(
   876                          "Unexpected error during file upload", e);
   877                  } finally {
   878                      if (tempFile != null) tempFile.delete();
   879                  }
   880              }
   881              throw new AtomException("Incorrect path information");
   882          
   883          } catch (WebloggerException re) {
   884              throw new AtomException("Posting media");
   885          }
   886  
   887      }
   888              
   889      //------------------------------------------------------------------ URI testers
   890      
   891      /**
   892       * True if URL is the introspection URI.
   893       */
   894      public boolean isIntrospectionURI(String[] pathInfo) {
                 /* 
    P/P           *  Method: bool isIntrospectionURI(String[])
                  * 
                  *  Preconditions:
                  *    pathInfo != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    pathInfo.length: {1..+Inf}, {0}
                  */
   895          if (pathInfo.length==0) return true;
   896          return false;
   897      }
   898      
   899      /**
   900       * True if URL is a entry URI.
   901       */
   902      public boolean isEntryURI(String[] pathInfo) {
                 /* 
    P/P           *  Method: bool isEntryURI(String[])
                  * 
                  *  Preconditions:
                  *    pathInfo != null
                  *    (soft) pathInfo.length <= 232
                  *    (soft) pathInfo[...] != null
                  *    (soft) pathInfo[1] != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    pathInfo.length: {0..2}, {3..232}
                  *    java.lang.String:endsWith(...)@904: {0}, {1}
                  *    java.lang.String:equals(...)@903: {0}, {1}
                  *    java.lang.String:equals(...)@904: {0}, {1}
                  */
   903          if (pathInfo.length > 2 && pathInfo[1].equals("entry")) return true;
   904          if (pathInfo.length > 2 && pathInfo[1].equals("resource") && pathInfo[pathInfo.length-1].endsWith(".media-link")) return true;
   905          return false;
   906      }
   907          
   908      /**
   909       * True if URL is media edit URI. Media can be udpated, but not metadata.
   910       */
   911      public boolean isMediaEditURI(String[] pathInfo) {
                 /* 
    P/P           *  Method: bool isMediaEditURI(String[])
                  * 
                  *  Preconditions:
                  *    pathInfo != null
                  *    (soft) pathInfo[1] != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    pathInfo.length: {0,1}, {2..+Inf}
                  *    java.lang.String:equals(...)@912: {0}, {1}
                  */
   912          if (pathInfo.length > 1 && pathInfo[1].equals("resource")) return true;
   913          return false;
   914      }
   915          
   916      /**
   917       * True if URL is a collection URI of any sort.
   918       */
   919      public boolean isCollectionURI(String[] pathInfo) {
                 /* 
    P/P           *  Method: bool isCollectionURI(String[])
                  * 
                  *  Preconditions:
                  *    pathInfo != null
                  *    (soft) pathInfo[1] != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    pathInfo.length: {0,1}, {2..+Inf}
                  *    java.lang.String:equals(...)@920: {0}, {1}
                  *    java.lang.String:equals(...)@921: {0}, {1}
                  *    java.lang.String:equals(...)@922: {0}, {1}
                  */
   920          if (pathInfo.length > 1 && pathInfo[1].equals("entries")) return true;
   921          if (pathInfo.length > 1 && pathInfo[1].equals("resources")) return true;
   922          if (pathInfo.length > 1 && pathInfo[1].equals("categories")) return true;
   923          return false;
   924      }
   925      
   926      //------------------------------------------------------------------ permissions
   927      
   928      /**
   929       * Return true if user is allowed to edit an entry.
   930       */
   931      private boolean canEdit(WeblogEntry entry) {
   932          try {
                     /* 
    P/P               *  Method: bool canEdit(WeblogEntry)
                      * 
                      *  Preconditions:
                      *    (soft) entry != null
                      *    (soft) log != null
                      *    (soft) init'ed(this.user)
                      * 
                      *  Postconditions:
                      *    init'ed(return_value)
                      */
   933              return entry.hasWritePermissions(this.user);
   934          } catch (Exception e) {
   935              log.error("Checking website.canSave()");
   936          }
   937          return false;
   938      }
   939      
   940      /**
   941       * Return true if user is allowed to create/edit weblog entries and file uploads in a website.
   942       */
   943      private boolean canEdit(Weblog website) {
   944          try {
                     /* 
    P/P               *  Method: bool canEdit(Weblog)
                      * 
                      *  Preconditions:
                      *    (soft) log != null
                      *    (soft) init'ed(this.user)
                      *    (soft) website != null
                      * 
                      *  Presumptions:
                      *    init'ed(org.apache.roller.weblogger.pojos.WeblogPermission.AUTHOR)
                      * 
                      *  Postconditions:
                      *    init'ed(return_value)
                      */
   945              return website.hasUserPermissions(this.user,WeblogPermission.AUTHOR);
   946          } catch (Exception e) {
   947              log.error("Checking website.hasUserPermissions()");
   948          }
   949          return false;
   950      }
   951      
   952      /**
   953       * Return true if user is allowed to view an entry.
   954       */
   955      private boolean canView(WeblogEntry entry) {
                 /* 
    P/P           *  Method: bool canView(WeblogEntry)
                  * 
                  *  Preconditions:
                  *    (soft) entry != null
                  *    (soft) log != null
                  *    (soft) init'ed(this.user)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   956          return canEdit(entry);
   957      }
   958      
   959      /**
   960       * Return true if user is allowed to view a website.
   961       */
   962      private boolean canView(Weblog website) {
                 /* 
    P/P           *  Method: bool canView(Weblog)
                  * 
                  *  Preconditions:
                  *    (soft) log != null
                  *    (soft) init'ed(this.user)
                  *    (soft) website != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   963          return canEdit(website);
   964      }
   965      
   966      //-------------------------------------------------------------- authentication
   967      
   968      /**
   969       * Perform WSSE authentication based on information in request.
   970       * Will not work if Weblogger password encryption is turned on.
   971       */
   972      protected String authenticateWSSE(HttpServletRequest request) {
                 /* 
    P/P           *  Method: String authenticateWSSE(HttpServletRequest)
                  * 
                  *  Preconditions:
                  *    request != null
                  *    (soft) log != null
                  *    (soft) this.roller != null
                  * 
                  *  Presumptions:
                  *    org.apache.roller.weblogger.business.UserManager:getUserByUserName(...)@1001 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getUserManager(...)@1001 != null
                  *    org.apache.roller.weblogger.pojos.User:getPassword(...)@1002 != null
                  *    org.apache.roller.weblogger.util.WSSEUtilities:generateDigest(...)@1002 != null
                  * 
                  *  Postconditions:
                  *    return_value == null
                  * 
                  *  Test Vectors:
                  *    java.lang.String:equals(...)@1006: {0}, {1}
                  *    javax.servlet.http.HttpServletRequest:getHeader(...)@973: Inverse{null}, Addr_Set{null}
                  */
   973          String wsseHeader = request.getHeader("X-WSSE");
   974          if (wsseHeader == null) return null;
   975          
   976          String ret = null;
   977          String userName = null;
   978          String created = null;
   979          String nonce = null;
   980          String passwordDigest = null;
   981          String[] tokens = wsseHeader.split(",");
+  982          for (int i = 0; i < tokens.length; i++) {
+  983              int index = tokens[i].indexOf('=');
   984              if (index != -1) {
   985                  String key = tokens[i].substring(0, index).trim();
   986                  String value = tokens[i].substring(index + 1).trim();
   987                  value = value.replaceAll("\"", "");
   988                  if (key.startsWith("UsernameToken")) {
   989                      userName = value;
   990                  } else if (key.equalsIgnoreCase("nonce")) {
   991                      nonce = value;
   992                  } else if (key.equalsIgnoreCase("passworddigest")) {
   993                      passwordDigest = value;
   994                  } else if (key.equalsIgnoreCase("created")) {
   995                      created = value;
   996                  }
   997              }
   998          }
   999          String digest = null;
  1000          try {
  1001              User user = roller.getUserManager().getUserByUserName(userName);
+ 1002              digest = WSSEUtilities.generateDigest(
  1003                      WSSEUtilities.base64Decode(nonce),
  1004                      created.getBytes("UTF-8"),
  1005                      user.getPassword().getBytes("UTF-8"));
  1006              if (digest.equals(passwordDigest)) {
  1007                  ret = userName;
  1008              }
  1009          } catch (Exception e) {
  1010              log.error("During wsseAuthenticataion: " + e.getMessage(), e);
  1011          }
  1012          return ret;
  1013      }
  1014      
  1015      /**
  1016       * BASIC authentication.
  1017       */
  1018      public String authenticateBASIC(HttpServletRequest request) {
                 /* 
    P/P           *  Method: String authenticateBASIC(HttpServletRequest)
                  * 
                  *  Preconditions:
                  *    (soft) log != null
                  *    (soft) request != null
                  *    (soft) this.roller != null
                  * 
                  *  Presumptions:
                  *    java.lang.String:indexOf(...)@1031 <= 232-2
                  *    org.apache.roller.weblogger.business.UserManager:getUserByUserName(...)@1034 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getUserManager(...)@1034 != null
                  *    org.apache.roller.weblogger.pojos.User:getEnabled(...)@1035 != null
                  *    org.apache.roller.weblogger.pojos.User:getPassword(...)@1045 != null
                  * 
                  *  Postconditions:
                  *    java.lang.String:substring(...)._tainted == 0
                  *    return_value in Addr_Set{null,&java.lang.String:substring(...)}
                  * 
                  *  Test Vectors:
                  *    java.lang.Boolean:booleanValue(...)@1035: {0}, {1}
                  *    java.lang.String:equalsIgnoreCase(...)@1028: {0}, {1}
                  *    java.lang.String:equalsIgnoreCase(...)@1041: {0}, {1}
                  *    java.lang.String:indexOf(...)@1031: {-1}, {-231..-2, 0..232-2}
                  *    java.util.StringTokenizer:hasMoreTokens(...)@1026: {0}, {1}
                  *    javax.servlet.http.HttpServletRequest:getHeader(...)@1023: Addr_Set{null}, Inverse{null}
                  */
  1019          boolean valid = false;
  1020          String userID = null;
  1021          String password = null;
  1022          try {
  1023              String authHeader = request.getHeader("Authorization");
  1024              if (authHeader != null) {
  1025                  StringTokenizer st = new StringTokenizer(authHeader);
  1026                  if (st.hasMoreTokens()) {
  1027                      String basic = st.nextToken();
  1028                      if (basic.equalsIgnoreCase("Basic")) {
  1029                          String credentials = st.nextToken();
  1030                          String userPass = new String(Base64.decodeBase64(credentials.getBytes()));
  1031                          int p = userPass.indexOf(":");
  1032                          if (p != -1) {
  1033                              userID = userPass.substring(0, p);
  1034                              User user = roller.getUserManager().getUserByUserName(userID);
  1035                              boolean enabled = user.getEnabled().booleanValue();
  1036                              if (enabled) {
  1037                                  // are passwords encrypted?
  1038                                  String encrypted =
  1039                                          WebloggerConfig.getProperty("passwds.encryption.enabled");
  1040                                  password = userPass.substring(p+1);
  1041                                  if ("true".equalsIgnoreCase(encrypted)) {
  1042                                      password = Utilities.encodePassword(password,
  1043                                              WebloggerConfig.getProperty("passwds.encryption.algorithm"));
  1044                                  }
  1045                                  valid = user.getPassword().equals(password);
  1046                              }
  1047                          }
  1048                      }
  1049                  }
  1050              }
  1051          } catch (Exception e) {
  1052              log.debug(e);
  1053          }
  1054          if (valid) return userID;
  1055          return null;
  1056      }
  1057      
  1058      //----------------------------------------------------------- internal utilities
  1059      
  1060      /**
  1061       * Create a Rome Atom entry based on a Weblogger entry.
  1062       * Content is escaped.
  1063       * Link is stored as rel=alternate link.
  1064       */
  1065      private Entry createAtomEntry(WeblogEntry entry) {
                 /* 
    P/P           *  Method: Entry createAtomEntry(WeblogEntry)
                  * 
                  *  Preconditions:
                  *    entry != null
                  * 
                  *  Presumptions:
                  *    java.util.Iterator:next(...)@1104 != null
                  *    org.apache.roller.weblogger.pojos.WeblogCategory:getPath(...)@1099 != null
                  *    org.apache.roller.weblogger.pojos.WeblogEntry:getCategory(...)@1099 != null
                  *    org.apache.roller.weblogger.pojos.WeblogEntry:getCreator(...)@1089 != null
                  *    org.apache.roller.weblogger.pojos.WeblogEntry:getTags(...)@1103 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    return_value == &new Entry(createAtomEntry#1)
                  *    new Entry(createAtomEntry#1) num objects == 1
                  * 
                  *  Test Vectors:
                  *    java.util.Iterator:hasNext(...)@1103: {0}, {1}
                  *    org.apache.commons.lang.StringUtils:isNotEmpty(...)@1082: {0}, {1}
                  */
  1066          Entry atomEntry = new Entry();
  1067          
  1068          String absUrl = WebloggerRuntimeConfig.getAbsoluteContextURL();
  1069          atomEntry.setId(        absUrl + entry.getPermaLink());
  1070          atomEntry.setTitle(     entry.getTitle());
  1071          atomEntry.setPublished( entry.getPubTime());
  1072          atomEntry.setUpdated(   entry.getUpdateTime());
  1073          
  1074          Content content = new Content();
  1075          content.setType(Content.HTML);
  1076          content.setValue(entry.getText());
  1077          List contents = new ArrayList();
  1078          contents.add(content);
  1079          
  1080          atomEntry.setContents(contents);
  1081          
  1082          if (StringUtils.isNotEmpty(entry.getSummary())) {
  1083              Content summary = new Content();
  1084              summary.setType(Content.HTML);
  1085              summary.setValue(entry.getSummary());
  1086              atomEntry.setSummary(summary);
  1087          }
  1088          
  1089          User creator = entry.getCreator();
  1090          Person author = new Person();
  1091          author.setName(         creator.getUserName());
  1092          author.setEmail(        creator.getEmailAddress());
  1093          atomEntry.setAuthors(   Collections.singletonList(author));
  1094          
  1095          // Add Atom category for Weblogger category, using category scheme
  1096          List categories = new ArrayList();
  1097          Category atomCat = new Category();
  1098          atomCat.setScheme(getWeblogCategoryScheme(entry.getWebsite()));
  1099          atomCat.setTerm(entry.getCategory().getPath().substring(1));
  1100          categories.add(atomCat);
  1101          
  1102          // Add Atom categories for each Weblogger tag with null scheme
  1103          for (Iterator tagit = entry.getTags().iterator(); tagit.hasNext();) {
  1104              WeblogEntryTag tag = (WeblogEntryTag) tagit.next();
  1105              Category newcat = new Category();
  1106              newcat.setTerm(tag.getName());
  1107              categories.add(newcat);
  1108          }        
  1109          atomEntry.setCategories(categories);
  1110          
  1111          Link altlink = new Link();
  1112          altlink.setRel("alternate");
  1113          altlink.setHref(absUrl + entry.getPermaLink());
  1114          List altlinks = new ArrayList();
  1115          altlinks.add(altlink);
  1116          atomEntry.setAlternateLinks(altlinks);
  1117          
  1118          Link editlink = new Link();
  1119          editlink.setRel("edit");
  1120          editlink.setHref(
  1121                  atomURL
  1122                  +"/"+entry.getWebsite().getHandle() + "/entry/" + entry.getId());
  1123          List otherlinks = new ArrayList();
  1124          otherlinks.add(editlink);
  1125          atomEntry.setOtherLinks(otherlinks);
  1126          
  1127          List modules = new ArrayList();
  1128          AppModule app = new AppModuleImpl();
  1129          app.setDraft(!WeblogEntry.PUBLISHED.equals(entry.getStatus()));
  1130          app.setEdited(entry.getUpdateTime());
  1131          modules.add(app);
  1132          atomEntry.setModules(modules);
  1133          
  1134          return atomEntry;
  1135      }
  1136      
  1137      private Entry createAtomResourceEntry(Weblog website, ThemeResource file) {
                 /* 
    P/P           *  Method: Entry createAtomResourceEntry(Weblog, ThemeResource)
                  * 
                  *  Preconditions:
                  *    file != null
                  *    website != null
                  * 
                  *  Presumptions:
                  *    javax.activation.FileTypeMap:getDefaultFileTypeMap(...)@1150 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getUrlStrategy(...)@1147 != null
                  *    org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@1147 != null
                  *    org.apache.roller.weblogger.pojos.ThemeResource:getPath(...)@1139 != null
                  * 
                  *  Postconditions:
                  *    return_value == &new Entry(createAtomResourceEntry#3)
                  *    new Entry(createAtomResourceEntry#3) num objects == 1
                  * 
                  *  Test Vectors:
                  *    java.lang.String:startsWith(...)@1139: {0}, {1}
                  */
+ 1138          String absUrl = WebloggerRuntimeConfig.getAbsoluteContextURL();
  1139          String filePath = 
  1140              file.getPath().startsWith("/") ? file.getPath().substring(1) : file.getPath();
  1141          String editURI = 
  1142                  atomURL+"/"+website.getHandle()
  1143                  + "/resource/" + filePath + ".media-link";
  1144          String editMediaURI = 
  1145                  atomURL+"/"+ website.getHandle()
  1146                  + "/resource/" + filePath;
  1147          URLStrategy urlStrategy = WebloggerFactory.getWeblogger().getUrlStrategy();
  1148          String viewURI = urlStrategy.getWeblogResourceURL(website, filePath, true);
  1149          
  1150          FileTypeMap map = FileTypeMap.getDefaultFileTypeMap();
  1151          // TODO: figure out why PNG is missing from Java MIME types
  1152          if (map instanceof MimetypesFileTypeMap) {
  1153              try {
  1154                  ((MimetypesFileTypeMap)map).addMimeTypes("image/png png PNG");
  1155              } catch (Exception ignored) {}
  1156          }
  1157          String contentType = map.getContentType(file.getName());
  1158          
  1159          Entry entry = new Entry();
  1160          entry.setId(editMediaURI);
  1161          entry.setTitle(file.getName());
  1162          entry.setUpdated(new Date(file.getLastModified()));
  1163          
  1164          List otherlinks = new ArrayList();        
  1165          entry.setOtherLinks(otherlinks);
  1166          Link editlink = new Link();
  1167              editlink.setRel("edit");
  1168              editlink.setHref(editURI);        
  1169              otherlinks.add(editlink);            
  1170          Link editMedialink = new Link();
  1171              editMedialink.setRel("edit-media");
  1172              editMedialink.setHref(editMediaURI);        
  1173              otherlinks.add(editMedialink);
  1174          
  1175          Content content = new Content();
  1176          content.setSrc(viewURI);
  1177          content.setType(contentType);
  1178          List contents = new ArrayList();
  1179          contents.add(content);
  1180          entry.setContents(contents);
  1181          
  1182          List modules = new ArrayList();
  1183          AppModule app = new AppModuleImpl();
  1184          app.setDraft(false);
  1185          app.setEdited(entry.getUpdated());
  1186          modules.add(app);
  1187          entry.setModules(modules);
  1188          
  1189          return entry;
  1190      }
  1191      
  1192      /**
  1193       * Copy fields from ROME entry to Weblogger entry.
  1194       */
  1195      private void copyToRollerEntry(Entry entry, WeblogEntry rollerEntry) throws WebloggerException {
  1196          
                 /* 
    P/P           *  Method: void copyToRollerEntry(Entry, WeblogEntry)
                  * 
                  *  Preconditions:
                  *    entry != null
                  *    rollerEntry != null
                  *    (soft) this.roller != null
                  * 
                  *  Presumptions:
                  *    com.sun.syndication.feed.atom.Category:getScheme(...)@1234 != null
                  *    com.sun.syndication.feed.atom.Entry:getContents(...)@1207 != null
                  *    com.sun.syndication.feed.atom.Entry:getContents(...)@1208 != null
                  *    com.sun.syndication.feed.atom.Entry:getPublished(...)@1201 != null
                  *    com.sun.syndication.feed.atom.Entry:getSummary(...)@1212 != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    com.sun.syndication.feed.atom.Category:getScheme(...)@1234: Addr_Set{null}, Inverse{null}
                  *    com.sun.syndication.feed.atom.Category:getScheme(...)@1260: Inverse{null}, Addr_Set{null}
                  *    com.sun.syndication.feed.atom.Category:getTerm(...)@1235: Addr_Set{null}, Inverse{null}
                  *    com.sun.syndication.feed.atom.Entry:getCategories(...)@1229: Addr_Set{null}, Inverse{null}
                  *    com.sun.syndication.feed.atom.Entry:getContents(...)@1207: Addr_Set{null}, Inverse{null}
                  *    com.sun.syndication.feed.atom.Entry:getModule(...)@1217: Addr_Set{null}, Inverse{null}
                  *    com.sun.syndication.feed.atom.Entry:getPublished(...)@1200: Addr_Set{null}, Inverse{null}
                  *    com.sun.syndication.feed.atom.Entry:getSummary(...)@1211: Addr_Set{null}, Inverse{null}
                  *    com.sun.syndication.feed.atom.Entry:getUpdated(...)@1203: Addr_Set{null}, Inverse{null}
                  *    control.draft@1217: {0}, {1}
                  *    ...
                  */
  1197          Timestamp current = new Timestamp(System.currentTimeMillis());
  1198          Timestamp pubTime = current;
  1199          Timestamp updateTime = current;
  1200          if (entry.getPublished() != null) {
  1201              pubTime = new Timestamp( entry.getPublished().getTime() );
  1202          }
  1203          if (entry.getUpdated() != null) {
  1204              updateTime = new Timestamp( entry.getUpdated().getTime() );
  1205          }
  1206          rollerEntry.setTitle(entry.getTitle());
  1207          if (entry.getContents() != null && entry.getContents().size() > 0) {
  1208              Content content = (Content)entry.getContents().get(0);
  1209              rollerEntry.setText(content.getValue());
  1210          }
  1211          if (entry.getSummary() != null) {
  1212              rollerEntry.setSummary(entry.getSummary().getValue());
  1213          }
  1214          rollerEntry.setPubTime(pubTime);
  1215          rollerEntry.setUpdateTime(updateTime);
  1216          
  1217          AppModule control =
  1218                  (AppModule)entry.getModule(AppModule.URI);
  1219          if (control!=null && control.getDraft()) {
  1220              rollerEntry.setStatus(WeblogEntry.DRAFT);
  1221          } else {
  1222              rollerEntry.setStatus(WeblogEntry.PUBLISHED);
  1223          }
  1224                  
  1225          // Process incoming categories:
  1226          // Atom categories with weblog-level scheme are Weblogger categories.
  1227          // Atom supports multiple cats, but Weblogger supports one/entry
  1228          // so here we take accept the first category that exists.
  1229          List categories = entry.getCategories();
  1230          if (categories != null && categories.size() > 0) {
  1231              for (int i=0; i<categories.size(); i++) {
  1232                  Category cat = (Category)categories.get(i);
  1233                  
  1234                  if (cat.getScheme() != null && cat.getScheme().equals(getWeblogCategoryScheme(rollerEntry.getWebsite()))) {                
  1235                      String catString = cat.getTerm();
  1236                      if (catString != null) {
  1237                          WeblogCategory rollerCat =
  1238                                  roller.getWeblogManager().getWeblogCategoryByPath(
  1239                                  rollerEntry.getWebsite(), catString);
  1240                          if (rollerCat != null) {
  1241                              // Found a valid category, so break out
  1242                              rollerEntry.setCategory(rollerCat);
  1243                              break;
  1244                          }
  1245                      }
  1246                  }
  1247              }
  1248          }
  1249          if (rollerEntry.getCategory() == null) {
  1250              // Didn't find a category? Fall back to the default Blogger API category.
  1251              rollerEntry.setCategory(rollerEntry.getWebsite().getBloggerCategory());
  1252          }
  1253          
  1254          // Now process incoming categories that are tags:
  1255          // Atom categories with no scheme are considered tags.
  1256          String tags = "";
  1257          if (categories != null && categories.size() > 0) {
  1258              for (int i=0; i<categories.size(); i++) {
  1259                  Category cat = (Category)categories.get(i);            
  1260                  if (cat.getScheme() == null) {
  1261                      tags = tags + " " + cat.getTerm();
  1262                  }                
  1263              }
  1264          }
  1265          rollerEntry.setTagsAsString(tags);        
  1266      }
  1267          
  1268      private String getWeblogCategoryScheme(Weblog website) {
                 /* 
    P/P           *  Method: String getWeblogCategoryScheme(Weblog)
                  * 
                  *  Presumptions:
                  *    org.apache.roller.weblogger.business.Weblogger:getUrlStrategy(...)@1269 != null
                  *    org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@1269 != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
  1269          return WebloggerFactory.getWeblogger().getUrlStrategy().getWeblogURL(website, null, true);
  1270      }
  1271      
  1272  
  1273      private String filePathFromPathInfo(String[] pathInfo) {
                 /* 
    P/P           *  Method: String filePathFromPathInfo(String[])
                  * 
                  *  Preconditions:
                  *    pathInfo != null
                  *    pathInfo.length <= 232-1
                  *    (soft) init'ed(pathInfo[...])
                  * 
                  *  Presumptions:
                  *    init'ed(java.io.File.separator)
                  * 
                  *  Postconditions:
                  *    init'ed(java.lang.StringBuilder:toString(...)._tainted)
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    pathInfo.length: {2}, {3..232-1}
                  *    java.lang.String:length(...)@1277: {0}, {1..232-1}
                  */
  1274          String path = null;
  1275          if (pathInfo.length > 2) {
  1276              for (int i = 2; i < pathInfo.length; i++) {
  1277                  if (path != null && path.length() > 0)
  1278                      path = path + File.separator + pathInfo[i];
  1279                  else
  1280                      path = pathInfo[i];
  1281              }
  1282          } if (pathInfo.length == 2) {
  1283              path = "";
  1284          }
  1285          return path;
  1286      }
  1287      
  1288      private void reindexEntry(WeblogEntry entry) throws WebloggerException {
                 /* 
    P/P           *  Method: void reindexEntry(WeblogEntry)
                  * 
                  *  Preconditions:
                  *    entry != null
                  *    this.roller != null
                  * 
                  *  Presumptions:
                  *    org.apache.roller.weblogger.business.Weblogger:getIndexManager(...)@1289 != null
                  * 
                  *  Test Vectors:
                  *    org.apache.roller.weblogger.pojos.WeblogEntry:isPublished(...)@1295: {0}, {1}
                  */
  1289          IndexManager manager = roller.getIndexManager();
  1290          
  1291          // TODO: figure out what's up here and at WeblogEntryFormAction line 696
  1292          //manager.removeEntryIndexOperation(entry);
  1293          
  1294          // if published, index the entry
  1295          if (entry.isPublished()) {
  1296              manager.addEntryReIndexOperation(entry);
  1297          }
  1298      }
  1299      
  1300      private void oneSecondThrottle() {
  1301          // Throttle one entry per second per weblog because time-
  1302          // stamp in MySQL and other DBs has only 1 sec resolution
  1303          try { 
                     /* 
    P/P               *  Method: void oneSecondThrottle()
                      */
  1304              synchronized (getClass()) { 
  1305                  Thread.sleep(1000); 
  1306              }  
  1307          } catch (Exception ignored) {} 
  1308      }
  1309  
  1310  }
  1311  
  1312  
  1313  








SofCheck Inspector Build Version : 2.18479
RollerAtomHandler.java 2009-Jan-02 14:25:12
RollerAtomHandler.class 2009-Sep-04 03:12:46
RollerAtomHandler$1.class 2009-Sep-04 03:12:46