001 /* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019 package org.apache.wiki.xmlrpc; 020 021 import java.util.Calendar; 022 import java.util.Collection; 023 import java.util.Date; 024 import java.util.Hashtable; 025 import java.util.Iterator; 026 import java.util.Vector; 027 028 import org.apache.wiki.LinkCollector; 029 import org.apache.wiki.WikiContext; 030 import org.apache.wiki.WikiEngine; 031 import org.apache.wiki.WikiPage; 032 import org.apache.wiki.attachment.Attachment; 033 import org.apache.wiki.auth.permissions.PagePermission; 034 import org.apache.wiki.auth.permissions.PermissionFactory; 035 import org.apache.xmlrpc.XmlRpcException; 036 037 /** 038 * Provides handlers for all RPC routines. These routines are used by 039 * the UTF-8 interface. 040 * 041 * @since 1.6.13 042 */ 043 044 public class RPCHandlerUTF8 045 extends AbstractRPCHandler 046 { 047 public String getApplicationName() 048 { 049 checkPermission( PagePermission.VIEW ); 050 051 return m_engine.getApplicationName(); 052 } 053 054 public Vector getAllPages() 055 { 056 checkPermission( PagePermission.VIEW ); 057 058 Collection pages = m_engine.getRecentChanges(); 059 Vector<String> result = new Vector<String>(); 060 061 for( Iterator i = pages.iterator(); i.hasNext(); ) 062 { 063 WikiPage p = (WikiPage) i.next(); 064 065 if( !(p instanceof Attachment) ) 066 { 067 result.add( p.getName() ); 068 } 069 } 070 071 return result; 072 } 073 074 /** 075 * Encodes a single wiki page info into a Hashtable. 076 */ 077 protected Hashtable<String, Object> encodeWikiPage( WikiPage page ) 078 { 079 Hashtable<String, Object> ht = new Hashtable<String, Object>(); 080 081 ht.put( "name", page.getName() ); 082 083 Date d = page.getLastModified(); 084 085 // 086 // Here we reset the DST and TIMEZONE offsets of the 087 // calendar. Unfortunately, I haven't thought of a better 088 // way to ensure that we're getting the proper date 089 // from the XML-RPC thingy, except to manually adjust the date. 090 // 091 092 Calendar cal = Calendar.getInstance(); 093 cal.setTime( d ); 094 cal.add( Calendar.MILLISECOND, 095 - (cal.get( Calendar.ZONE_OFFSET ) + 096 (cal.getTimeZone().inDaylightTime( d ) ? cal.get( Calendar.DST_OFFSET ) : 0 )) ); 097 098 ht.put( "lastModified", cal.getTime() ); 099 ht.put( "version", page.getVersion() ); 100 101 if( page.getAuthor() != null ) 102 { 103 ht.put( "author", page.getAuthor() ); 104 } 105 106 return ht; 107 } 108 109 public Vector getRecentChanges( Date since ) 110 { 111 checkPermission( PagePermission.VIEW ); 112 113 Collection pages = m_engine.getRecentChanges(); 114 Vector<Hashtable<String, Object>> result = new Vector<Hashtable<String, Object>>(); 115 116 Calendar cal = Calendar.getInstance(); 117 cal.setTime( since ); 118 119 // 120 // Convert UTC to our time. 121 // 122 cal.add( Calendar.MILLISECOND, 123 (cal.get( Calendar.ZONE_OFFSET ) + 124 (cal.getTimeZone().inDaylightTime(since) ? cal.get( Calendar.DST_OFFSET ) : 0 ) ) ); 125 since = cal.getTime(); 126 127 for( Iterator i = pages.iterator(); i.hasNext(); ) 128 { 129 WikiPage page = (WikiPage)i.next(); 130 131 if( page.getLastModified().after( since ) && !(page instanceof Attachment) ) 132 { 133 result.add( encodeWikiPage( page ) ); 134 } 135 } 136 137 return result; 138 } 139 140 /** 141 * Simple helper method, turns the incoming page name into 142 * normal Java string, then checks page condition. 143 * 144 * @param pagename Page Name as an RPC string (URL-encoded UTF-8) 145 * @return Real page name, as Java string. 146 * @throws XmlRpcException, if there is something wrong with the page. 147 */ 148 private String parsePageCheckCondition( String pagename ) 149 throws XmlRpcException 150 { 151 if( !m_engine.pageExists(pagename) ) 152 { 153 throw new XmlRpcException( ERR_NOPAGE, "No such page '"+pagename+"' found, o master." ); 154 } 155 156 WikiPage p = m_engine.getPage( pagename ); 157 158 checkPermission( PermissionFactory.getPagePermission( p, PagePermission.VIEW_ACTION ) ); 159 return pagename; 160 } 161 162 public Hashtable getPageInfo( String pagename ) 163 throws XmlRpcException 164 { 165 pagename = parsePageCheckCondition( pagename ); 166 167 return encodeWikiPage( m_engine.getPage(pagename) ); 168 } 169 170 public Hashtable getPageInfoVersion( String pagename, int version ) 171 throws XmlRpcException 172 { 173 pagename = parsePageCheckCondition( pagename ); 174 175 return encodeWikiPage( m_engine.getPage( pagename, version ) ); 176 } 177 178 public String getPage( String pagename ) 179 throws XmlRpcException 180 { 181 pagename = parsePageCheckCondition( pagename ); 182 183 String text = m_engine.getPureText( pagename, -1 ); 184 185 return text; 186 } 187 188 public String getPageVersion( String pagename, int version ) 189 throws XmlRpcException 190 { 191 pagename = parsePageCheckCondition( pagename ); 192 193 return m_engine.getPureText( pagename, version ); 194 } 195 196 public String getPageHTML( String pagename ) 197 throws XmlRpcException 198 { 199 pagename = parsePageCheckCondition( pagename ); 200 201 return m_engine.getHTML( pagename ); 202 } 203 204 public String getPageHTMLVersion( String pagename, int version ) 205 throws XmlRpcException 206 { 207 pagename = parsePageCheckCondition( pagename ); 208 209 return m_engine.getHTML( pagename, version ); 210 } 211 212 public Vector listLinks( String pagename ) 213 throws XmlRpcException 214 { 215 pagename = parsePageCheckCondition( pagename ); 216 217 WikiPage page = m_engine.getPage( pagename ); 218 String pagedata = m_engine.getPureText( page ); 219 220 LinkCollector localCollector = new LinkCollector(); 221 LinkCollector extCollector = new LinkCollector(); 222 LinkCollector attCollector = new LinkCollector(); 223 224 WikiContext context = new WikiContext( m_engine, page ); 225 context.setVariable( WikiEngine.PROP_REFSTYLE, "absolute" ); 226 227 m_engine.textToHTML( context, 228 pagedata, 229 localCollector, 230 extCollector, 231 attCollector ); 232 233 Vector<Hashtable<String, String>> result = new Vector<Hashtable<String, String>>(); 234 235 // FIXME: Contains far too much common with RPCHandler. Refactor! 236 237 // 238 // Add local links. 239 // 240 for( Iterator< String > i = localCollector.getLinks().iterator(); i.hasNext(); ) 241 { 242 String link = i.next(); 243 Hashtable< String, String > ht = new Hashtable< String, String >(); 244 ht.put( "page", link ); 245 ht.put( "type", LINK_LOCAL ); 246 247 if( m_engine.pageExists(link) ) 248 { 249 ht.put( "href", context.getViewURL(link) ); 250 } 251 else 252 { 253 ht.put( "href", context.getURL(WikiContext.EDIT,link) ); 254 } 255 256 result.add( ht ); 257 } 258 259 // 260 // Add links to inline attachments 261 // 262 for( Iterator i = attCollector.getLinks().iterator(); i.hasNext(); ) 263 { 264 String link = (String) i.next(); 265 266 Hashtable<String, String> ht = new Hashtable<String, String>(); 267 268 ht.put( "page", link ); 269 ht.put( "type", LINK_LOCAL ); 270 ht.put( "href", context.getURL(WikiContext.ATTACH,link) ); 271 272 result.add( ht ); 273 } 274 275 // 276 // External links don't need to be changed into XML-RPC strings, 277 // simply because URLs are by definition ASCII. 278 // 279 280 for( Iterator i = extCollector.getLinks().iterator(); i.hasNext(); ) 281 { 282 String link = (String) i.next(); 283 284 Hashtable<String, String> ht = new Hashtable<String, String>(); 285 286 ht.put( "page", link ); 287 ht.put( "type", LINK_EXTERNAL ); 288 ht.put( "href", link ); 289 290 result.add( ht ); 291 } 292 293 return result; 294 } 295 }