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 }