66import java .util .UUID ;
77
88import org .apache .log4j .Logger ;
9+ import org .buddycloud .channelserver .db .exception .NodeStoreException ;
10+ import org .buddycloud .channelserver .pubsub .model .NodeItem ;
911import org .dom4j .Element ;
1012import org .dom4j .dom .DOMElement ;
13+ import org .xmpp .packet .JID ;
14+ import org .xmpp .packet .PacketError ;
1115
1216public class ValidateEntry {
1317
14- private static Logger LOGGER = Logger .getLogger (ValidateEntry .class );
15-
18+ public static final String MISSING_CONTENT_ELEMENT = "content-element-required" ;
19+ public static final String MISSING_ENTRY_ELEMENT = "entry-element-required" ;
20+ public static final String UNSUPPORTED_CONTENT_TYPE = "unsupported-content-type" ;
21+ public static final String MAX_THREAD_DEPTH_EXCEEDED = "max-thread-depth-exceeded" ;
22+ public static final String PARENT_ITEM_NOT_FOUND = "parent-item-not-found" ;
23+
24+ public static final String CONTENT_TEXT = "text" ;
25+ public static final String CONTENT_XHTML = "xhtml" ;
26+
27+ public static final String NS_ATOM = "http://www.w3.org/2005/Atom" ;
28+ public static final String NS_ACTIVITYSTREAM = "http://activitystrea.ms/spec/1.0/" ;
29+ public static final String NS_ATOM_THREAD = "http://purl.org/syndication/thread/1.0" ;
30+ public static final String NS_GEOLOCATION = "http://jabber.org/protocol/geoloc" ;
31+
32+ public static final String AUTHOR_URI_PREFIX = "acct:" ;
33+ public static final String AUTHOR_TYPE = "person" ;
34+
35+ public static final String POST_TYPE_NOTE = "note" ;
36+ public static final String POST_TYPE_COMMENT = "comment" ;
37+
38+ public static final String ACTIVITY_VERB_POST = "post" ;
39+
40+ private static Logger logger = Logger .getLogger (ValidateEntry .class );
41+
1642 private Element entry ;
17-
18- private String errorMsg = "" ;
43+
44+ private String errorMessage = "" ;
1945 private String inReplyTo ;
2046 private Element meta ;
2147 private Element media ;
2248
23- Map <String , String >params = new HashMap <String , String >();
24-
49+ private JID jid ;
50+ private String channelServerDomain ;
51+ private String node ;
52+ private ChannelManager channelManager ;
53+
54+ Map <String , String > params = new HashMap <String , String >();
55+
2556 private Element geoloc ;
2657
58+ public ValidateEntry () {}
59+
2760 public ValidateEntry (Element entry ) {
28- this . entry = entry ;
61+ setEntry ( entry ) ;
2962 }
3063
31- public String getErrorMsg () {
32- return this .errorMsg ;
64+ public void setEntry (Element entry ) {
65+ this .entry = entry ;
66+ }
67+
68+ public String getErrorMessage () {
69+ return this .errorMessage ;
3370 }
3471
72+ public void setChannelManager (ChannelManager channelManager ) {
73+ this .channelManager = channelManager ;
74+ }
75+
3576 /**
3677 * This is a big hackety-hack.
78+ * @throws InterruptedException
79+ * @throws NodeStoreException
3780 */
38- public boolean isValid ()
39- {
81+ public boolean isValid () throws NodeStoreException {
4082 if (this .entry == null ) {
41- this .errorMsg = "Dude, the entry is missing." ;
83+ this .errorMessage = MISSING_ENTRY_ELEMENT ;
4284 return false ;
4385 }
44-
45- /*
46- <entry xmlns="http://www.w3.org/2005/Atom">
47- <id>1</id>
48- <title>Status update.</title>
49- <content>This is my new status!</content>
50- <updated>2011-06-18T09:08:57Z</updated>
51- <author>
52- <name>tuomas@koski.com</name>
53- </author>
54- </entry>
55- */
56-
86+
5787 Element id = this .entry .element ("id" );
58- if (id == null || id .getText ().isEmpty ()) {
59- LOGGER .debug ("ID of the entry was missing. We add a default one to it: 1" );
88+ if ((id == null ) || (true == id .getText ().isEmpty ())) {
89+ if (null != id )
90+ id .detach ();
91+ logger .debug ("ID of the entry was missing. We add a default one to it: 1" );
6092 this .entry .addElement ("id" ).setText ("1" );
6193 }
6294
6395 Element title = this .entry .element ("title" );
64- if ( title == null ) {
65- LOGGER .debug ("Title of the entry was missing. We add a default one to it: 'Post'." );
96+ if ( null == title ) {
97+ logger .debug ("Title of the entry was missing. We add a default one to it: 'Post'." );
6698 title = this .entry .addElement ("title" );
6799 title .setText ("Post" );
68100 }
69101 this .params .put ("title" , title .getText ());
70-
102+
71103 Element content = this .entry .element ("content" );
72- if (content == null ) {
73- this .errorMsg = "Mandatory element content is missing." ;
104+ if (null == content ) {
105+ this .errorMessage = MISSING_CONTENT_ELEMENT ;
106+ return false ;
107+ }
108+ String contentType = content .attributeValue ("type" );
109+ if (null == contentType ) {
110+ contentType = CONTENT_TEXT ;
111+ }
112+ if ((false == contentType .equals (CONTENT_TEXT ))
113+ && (false == contentType .equals (CONTENT_XHTML ))) {
114+ this .errorMessage = UNSUPPORTED_CONTENT_TYPE ;
74115 return false ;
75116 }
76117 this .params .put ("content" , content .getText ());
77-
118+ this .params .put ("content-type" , contentType );
119+
78120 Element updated = this .entry .element ("updated" );
79- if ( updated == null ) {
80-
121+ if ( null == updated ) {
122+
81123 String updateTime = Conf .formatDate (new Date ());
82-
83- LOGGER . debug ( "Update of the entry was missing. We add a default one to it: '" + updateTime + "'." );
124+ logger . debug ( "Update of the entry was missing. We add a default one to it: '"
125+ + updateTime + "'." );
84126 this .entry .addElement ("updated" ).setText (updateTime );
85127 }
86-
128+
87129 this .geoloc = this .entry .element ("geoloc" );
88-
130+
89131 Element reply = this .entry .element ("in-reply-to" );
90- if (null != reply ) {
91- inReplyTo = reply .attributeValue ("ref" ).toString ();
92- if (true == inReplyTo .matches (",+" )) {
93- String [] tokens = inReplyTo .split ("," );
94- inReplyTo = tokens [2 ];
95- }
132+ if ((null != reply ) && (false == validateInReplyToElement (reply ))) {
133+ return false ;
96134 }
135+
97136 Element meta = this .entry .element ("meta" );
98137 if (null != meta ) {
99138 this .meta = meta ;
100139 }
101-
140+
102141 Element media = this .entry .element ("media" );
103142 if (null != media ) {
104143 this .media = media ;
105144 }
106-
145+
107146 return true ;
108147 }
109-
110- public Element createBcCompatible (String bareJID , String channelServerJID , String node ) {
111-
112- Element entry = new DOMElement ("entry" , new org .dom4j .Namespace ("" , "http://www.w3.org/2005/Atom" ));
113- entry .add (new org .dom4j .Namespace ("activity" , "http://activitystrea.ms/spec/1.0/" ));
114-
115- /**
116- * We are going to build this now.
117- *
118- <entry xmlns="http://www.w3.org/2005/Atom" xmlns:activity="http://activitystrea.ms/spec/1.0/">
119- <id>tag:channels.koski.com,/user/tuomas@koski.com/status,1dfs5-6s8e-zerf-4494</id>
120- <title>Status update.</title>
121- <content>This is my new status!</content>
122- <updated>2011-08-03T09:58:57Z</updated>
123- <author>
124- <name>tuomas@koski.com</name>
125- <uri>acct:tuomas@koski.com</uri>
126- <activity:object-type>person</activity:object-type>
127- </author>
128- <activity:verb>post</activity:verb>
129- <activity:object>
130- <activity:object-type>note</activity:object-type>
131- </activity:object>
132- <meta>
133- ... additional meta ...
134- </meta>
135- <media>
136- <item id="mediaId" channel="channel@example.com"/>
137- </media>
138- </entry>
139- */
140- String id = UUID .randomUUID ().toString ();
141- String postType = "note" ;
142-
143- entry .addElement ("id" )
144- .setText ("tag:" + channelServerJID + "," + node + "," + id );
145-
146- entry .addElement ("title" )
147- .setText (this .params .get ("title" ));
148-
149- entry .addElement ("content" )
150- .setText (this .params .get ("content" ));
151-
152- String leData = Conf .formatDate (new Date ());
153-
154- entry .addElement ("published" )
155- .setText (leData );
156-
157- entry .addElement ("updated" )
158- .setText (leData );
159-
148+
149+ public Element getPayload () {
150+
151+ Element entry = new DOMElement ("entry" , new org .dom4j .Namespace ("" ,
152+ NS_ATOM ));
153+ entry .add (new org .dom4j .Namespace ("activity" , NS_ACTIVITYSTREAM ));
154+
155+ String id = UUID .randomUUID ().toString ();
156+ String postType = POST_TYPE_NOTE ;
157+ String activityVerb = ACTIVITY_VERB_POST ;
158+
159+ entry .addElement ("id" ).setText (
160+ "tag:" + channelServerDomain + "," + node + "," + id );
161+
162+ entry .addElement ("title" ).setText (this .params .get ("title" ));
163+
164+ Element content = entry .addElement ("content" );
165+ content .setText (this .params .get ("content" ));
166+ content .addAttribute ("type" , this .params .get ("content-type" ));
167+
168+ String publishedDate = Conf .formatDate (new Date ());
169+
170+ entry .addElement ("published" ).setText (publishedDate );
171+
172+ entry .addElement ("updated" ).setText (publishedDate );
173+
160174 Element author = entry .addElement ("author" );
161-
162- author .addElement ("name" )
163- .setText (bareJID );
164-
165- author .addElement ("uri" )
166- .setText ("acct:" + bareJID );
167-
168- author .addElement ("activity:object-type" )
169- .setText ("person" );
175+
176+ author .addElement ("name" ).setText (jid .toBareJID ());
177+
178+ author .addElement ("uri" ).setText (AUTHOR_URI_PREFIX + jid .toBareJID ());
179+
180+ author .addElement ("activity:object-type" ).setText (AUTHOR_TYPE );
170181
171182 if (this .geoloc != null ) {
172183 entry .add (this .geoloc .createCopy ());
173184 }
185+
174186 if (this .inReplyTo != null ) {
175187 Element reply = entry .addElement ("in-reply-to" );
176- reply .addNamespace ("" , "http://purl.org/syndication/thread/1.0" );
188+ reply .addNamespace ("" , NS_ATOM_THREAD );
177189 reply .addAttribute ("ref" , inReplyTo );
178- postType = "comment" ;
190+ postType = POST_TYPE_COMMENT ;
179191 }
180-
192+
181193 this .geoloc = this .entry .element ("geoloc" );
182-
183- entry .addElement ("activity:verb" )
184- .setText ("post" );
185-
186- Element activity_object = entry .addElement ("activity:object" );
187- activity_object .addElement ("activity:object-type" )
188- .setText (postType );
189-
194+
195+ entry .addElement ("activity:verb" ).setText (activityVerb );
196+
197+ Element activityObject = entry .addElement ("activity:object" );
198+ activityObject .addElement ("activity:object-type" ).setText (postType );
199+
190200 if (null != meta ) {
191201 entry .add (meta .createCopy ());
192202 }
193-
203+
194204 if (null != media ) {
195205 entry .add (media .createCopy ());
196206 }
197-
207+
198208 return entry ;
199209 }
210+
211+ public void setUser (JID jid ) {
212+ this .jid = jid ;
213+ }
214+
215+ public void setNode (String node ) {
216+ this .node = node ;
217+ }
218+
219+ public void setTo (String channelServerDomain ) {
220+ this .channelServerDomain = channelServerDomain ;
221+ }
200222
201- }
223+
224+ private boolean validateInReplyToElement (Element reply ) throws NodeStoreException {
225+
226+ inReplyTo = reply .attributeValue ("ref" );
227+ if (-1 != inReplyTo .indexOf ("," )) {
228+ String [] tokens = inReplyTo .split ("," );
229+ inReplyTo = tokens [2 ];
230+ }
231+
232+ String [] inReplyToParts = reply .attributeValue ("ref" ).split ("," );
233+ inReplyTo = inReplyToParts [inReplyToParts .length - 1 ];
234+
235+ NodeItem nodeItem = null ;
236+ if (null == (nodeItem = channelManager .getNodeItem (node , inReplyTo ))) {
237+ this .errorMessage = PARENT_ITEM_NOT_FOUND ;
238+ return false ;
239+ }
240+ if (null != nodeItem .getInReplyTo ()) {
241+ logger .error ("User is attempting to reply to a reply" );
242+ this .errorMessage = MAX_THREAD_DEPTH_EXCEEDED ;
243+ return false ;
244+ }
245+ return true ;
246+ }
247+
248+ }
0 commit comments