Skip to content

Commit ff2f0e2

Browse files
committed
Merge pull request #127 from surevine/validate-in-validator
Validate in validator
2 parents 9ea2644 + 05f926d commit ff2f0e2

11 files changed

Lines changed: 1356 additions & 628 deletions

File tree

src/main/java/org/buddycloud/channelserver/channel/ValidateEntry.java

Lines changed: 168 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -6,196 +6,243 @@
66
import java.util.UUID;
77

88
import org.apache.log4j.Logger;
9+
import org.buddycloud.channelserver.db.exception.NodeStoreException;
10+
import org.buddycloud.channelserver.pubsub.model.NodeItem;
911
import org.dom4j.Element;
1012
import org.dom4j.dom.DOMElement;
13+
import org.xmpp.packet.JID;
14+
import org.xmpp.packet.PacketError;
1115

1216
public 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

Comments
 (0)