diff --git a/Builder/IISMainHandler/build.txt b/Builder/IISMainHandler/build.txt index 0c7f592..e1f2760 100644 --- a/Builder/IISMainHandler/build.txt +++ b/Builder/IISMainHandler/build.txt @@ -1 +1 @@ -604 \ No newline at end of file +613 \ No newline at end of file diff --git a/Builder/IISUploadHandler/build.txt b/Builder/IISUploadHandler/build.txt index 4b74f22..d35d5f7 100644 --- a/Builder/IISUploadHandler/build.txt +++ b/Builder/IISUploadHandler/build.txt @@ -1 +1 @@ -338 \ No newline at end of file +347 \ No newline at end of file diff --git a/Common/Common.csproj b/Common/Common.csproj index c1bcce0..6ce5168 100644 --- a/Common/Common.csproj +++ b/Common/Common.csproj @@ -88,6 +88,7 @@ + diff --git a/Common/actions/ChangeSet.cs b/Common/actions/ChangeSet.cs index 2006e74..ce40e6a 100644 --- a/Common/actions/ChangeSet.cs +++ b/Common/actions/ChangeSet.cs @@ -22,7 +22,7 @@ namespace FLocal.Common.actions { dataobjects.Thread.TableSpec.TABLE, //thread should come first because of Board.newThread locking order with two changesets dataobjects.Board.TableSpec.TABLE, dataobjects.Post.TableSpec.TABLE, - dataobjects.Post.RevisionTableSpec.TABLE, + dataobjects.Revision.TableSpec.TABLE, dataobjects.Account.TableSpec.TABLE, dataobjects.User.TableSpec.TABLE, dataobjects.AccountSettings.TableSpec.TABLE, diff --git a/Common/dataobjects/Post.cs b/Common/dataobjects/Post.cs index 02640fd..f4308aa 100644 --- a/Common/dataobjects/Post.cs +++ b/Common/dataobjects/Post.cs @@ -5,6 +5,7 @@ using System.Text; using System.Xml.Linq; using FLocal.Core; using FLocal.Core.DB; +using FLocal.Core.DB.conditions; using FLocal.Common; using FLocal.Common.actions; @@ -29,20 +30,6 @@ namespace FLocal.Common.dataobjects { public void refreshSqlObject(int id) { Refresh(id); } } - public class RevisionTableSpec : ISqlObjectTableSpec { - public const string TABLE = "Revisions"; - public const string FIELD_ID = "Id"; - public const string FIELD_POSTID = "PostId"; - public const string FIELD_CHANGEDATE = "ChangeDate"; - public const string FIELD_TITLE = "Title"; - public const string FIELD_BODY = "Body"; - public const string FIELD_NUMBER = "Number"; - public static readonly RevisionTableSpec instance = new RevisionTableSpec(); - public string name { get { return TABLE; } } - public string idName { get { return FIELD_ID; } } - public void refreshSqlObject(int id) { } - } - protected override ISqlObjectTableSpec table { get { return TableSpec.instance; } } private int _posterId; @@ -67,8 +54,8 @@ namespace FLocal.Common.dataobjects { } } - private DateTime? _lastChangeDate; - public DateTime? lastChangeDate { + private DateTime _lastChangeDate; + public DateTime lastChangeDate { get { this.LoadIfNotLoaded(); return this._lastChangeDate; @@ -82,6 +69,31 @@ namespace FLocal.Common.dataobjects { return this._revision; } } + public Revision latestRevision { + get { + return Revision.LoadById( + int.Parse( + Config.instance.mainConnection.LoadIdsByConditions( + Revision.TableSpec.instance, + new ComplexCondition( + ConditionsJoinType.AND, + new ComparisonCondition( + Revision.TableSpec.instance.getColumnSpec(Revision.TableSpec.FIELD_POSTID), + ComparisonType.EQUAL, + this.id.ToString() + ), + new ComparisonCondition( + Revision.TableSpec.instance.getColumnSpec(Revision.TableSpec.FIELD_NUMBER), + ComparisonType.EQUAL, + this.revision.ToString() + ) + ), + Diapasone.unlimited + ).Single() + ) + ); + } + } private int _layerId; public int layerId { @@ -145,8 +157,8 @@ namespace FLocal.Common.dataobjects { protected override void doFromHash(Dictionary data) { this._posterId = int.Parse(data[TableSpec.FIELD_POSTERID]); - this._postDate = new DateTime(long.Parse(data[TableSpec.FIELD_POSTDATE])); - this._lastChangeDate = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_LASTCHANGEDATE]); + this._postDate = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_POSTDATE]).Value; + this._lastChangeDate = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_LASTCHANGEDATE]).Value; this._revision = Util.ParseInt(data[TableSpec.FIELD_REVISION]); this._layerId = int.Parse(data[TableSpec.FIELD_LAYERID]); this._title = data[TableSpec.FIELD_TITLE]; @@ -175,15 +187,16 @@ namespace FLocal.Common.dataobjects { new XElement("id", this.id), new XElement("poster", this.poster.exportToXmlForViewing(context)), new XElement("postDate", this.postDate.ToXml()), - new XElement("lastChangeDate", this.postDate.ToXml()), - new XElement("revision", this.revision), + new XElement("lastChangeDate", this.lastChangeDate.ToXml()), + new XElement("revision", this.revision.ToString()), new XElement("layerId", this.layerId), new XElement("layerName", this.layer.name), new XElement("title", this.title), new XElement("body", context.outputParams.preprocessBodyIntermediate(this.body)), //this.XMLBody(context), new XElement("bodyShort", this.bodyShort), - new XElement("threadId", this.threadId) + new XElement("threadId", this.threadId), + new XElement("isOwner", ((context.account != null) && (this.poster.id == context.account.user.id)).ToPlainString()) ); if(includeParentPost) { if(this.parentPostId.HasValue) { @@ -213,5 +226,41 @@ namespace FLocal.Common.dataobjects { return Post.LoadById(changes.Key.getId().Value); } + private readonly object Edit_locker = new object(); //TODO: move locking to DB + public void Edit(User user, string newTitle, string newBody, PostLayer newDesiredLayer) { + if(this.poster.id != user.id) { + throw new AccessViolationException(); + } + PostLayer actualLayer = poster.getActualLayer(this.thread.board, newDesiredLayer); + if(actualLayer.id < this.layer.id) { + actualLayer = this.layer; + } + lock(this.Edit_locker) { + ChangeSetUtil.ApplyChanges( + new InsertChange( + Revision.TableSpec.instance, + new Dictionary { + { Revision.TableSpec.FIELD_POSTID, new ScalarFieldValue(this.id.ToString()) }, + { Revision.TableSpec.FIELD_CHANGEDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, + { Revision.TableSpec.FIELD_TITLE, new ScalarFieldValue(newTitle) }, + { Revision.TableSpec.FIELD_BODY, new ScalarFieldValue(newBody) }, + { Revision.TableSpec.FIELD_NUMBER, new ScalarFieldValue((this.revision + 1).ToString()) }, + } + ), + new UpdateChange( + TableSpec.instance, + new Dictionary { + { TableSpec.FIELD_TITLE, new ScalarFieldValue(newTitle) }, + { TableSpec.FIELD_BODY, new ScalarFieldValue(UBBParser.UBBToIntermediate(newBody)) }, + { TableSpec.FIELD_LASTCHANGEDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, + { TableSpec.FIELD_REVISION, new IncrementFieldValue() }, + { TableSpec.FIELD_LAYERID, new ScalarFieldValue(actualLayer.id.ToString()) }, + }, + this.id + ) + ); + } + } + } } diff --git a/Common/dataobjects/Revision.cs b/Common/dataobjects/Revision.cs new file mode 100644 index 0000000..2453c77 --- /dev/null +++ b/Common/dataobjects/Revision.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FLocal.Core; +using System.Xml.Linq; + +namespace FLocal.Common.dataobjects { + public class Revision : SqlObject { + + public class TableSpec : ISqlObjectTableSpec { + public const string TABLE = "Revisions"; + public const string FIELD_ID = "Id"; + public const string FIELD_POSTID = "PostId"; + public const string FIELD_CHANGEDATE = "ChangeDate"; + public const string FIELD_TITLE = "Title"; + public const string FIELD_BODY = "Body"; + public const string FIELD_NUMBER = "Number"; + public static readonly TableSpec instance = new TableSpec(); + public string name { get { return TABLE; } } + public string idName { get { return FIELD_ID; } } + public void refreshSqlObject(int id) { } + } + + protected override ISqlObjectTableSpec table { get { return TableSpec.instance; } } + + private int _postId; + public int postId { + get { + this.LoadIfNotLoaded(); + return this._postId; + } + } + public Post post { + get { + return Post.LoadById(this.postId); + } + } + + private DateTime _changeDate; + public DateTime changeDate { + get { + this.LoadIfNotLoaded(); + return this._changeDate; + } + } + + private string _title; + public string title { + get { + this.LoadIfNotLoaded(); + return this._title; + } + } + + private string _body; + public string body { + get { + this.LoadIfNotLoaded(); + return this._body; + } + } + + private int _number; + public int number { + get { + this.LoadIfNotLoaded(); + return this._number; + } + } + + protected override void doFromHash(Dictionary data) { + this._postId = int.Parse(data[TableSpec.FIELD_POSTID]); + this._changeDate = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_CHANGEDATE]).Value; + this._title = data[TableSpec.FIELD_TITLE]; + this._body = data[TableSpec.FIELD_BODY]; + this._number = int.Parse(data[TableSpec.FIELD_NUMBER]); + } + + + public XElement exportToXml(UserContext context) { + return new XElement("revision", + new XElement("id", this.id), + new XElement("title", this.title), + new XElement("body", this.body) + ); + } + } +} diff --git a/Common/dataobjects/Thread.cs b/Common/dataobjects/Thread.cs index da50f5f..6c5452b 100644 --- a/Common/dataobjects/Thread.cs +++ b/Common/dataobjects/Thread.cs @@ -410,13 +410,13 @@ namespace FLocal.Common.dataobjects { AbstractFieldValue postReference = new ReferenceFieldValue(postInsert); AbstractFieldValue postIndexReference = new TwoWayReferenceFieldValue(postInsert, TwoWayReferenceFieldValue.GREATEST); AbstractChange revisionInsert = new InsertChange( - Post.RevisionTableSpec.instance, + Revision.TableSpec.instance, new Dictionary { - { Post.RevisionTableSpec.FIELD_POSTID, postReference }, - { Post.RevisionTableSpec.FIELD_NUMBER, new ScalarFieldValue("0") }, - { Post.RevisionTableSpec.FIELD_CHANGEDATE, new ScalarFieldValue(date.ToUTCString()) }, - { Post.RevisionTableSpec.FIELD_TITLE, new ScalarFieldValue(title) }, - { Post.RevisionTableSpec.FIELD_BODY, new ScalarFieldValue(body) }, + { Revision.TableSpec.FIELD_POSTID, postReference }, + { Revision.TableSpec.FIELD_NUMBER, new ScalarFieldValue("0") }, + { Revision.TableSpec.FIELD_CHANGEDATE, new ScalarFieldValue(date.ToUTCString()) }, + { Revision.TableSpec.FIELD_TITLE, new ScalarFieldValue(title) }, + { Revision.TableSpec.FIELD_BODY, new ScalarFieldValue(body) }, } ); Dictionary threadData = new Dictionary { diff --git a/IISMainHandler/HandlersFactory.cs b/IISMainHandler/HandlersFactory.cs index c07f855..3e6a12c 100644 --- a/IISMainHandler/HandlersFactory.cs +++ b/IISMainHandler/HandlersFactory.cs @@ -57,6 +57,8 @@ namespace FLocal.IISHandler { return new handlers.PostHandler(); } switch(context.requestParts[2].ToLower()) { + case "edit": + return new handlers.response.EditHandler(); case "reply": return new handlers.response.ReplyHandler(); case "pmreply": @@ -129,6 +131,8 @@ namespace FLocal.IISHandler { return new handlers.request.LogoutHandler(); case "migrateaccount": return new handlers.request.MigrateAccountHandler(); + case "edit": + return new handlers.request.EditHandler(); case "reply": return new handlers.request.ReplyHandler(); case "newthread": diff --git a/IISMainHandler/IISMainHandler.csproj b/IISMainHandler/IISMainHandler.csproj index da49621..402d90f 100644 --- a/IISMainHandler/IISMainHandler.csproj +++ b/IISMainHandler/IISMainHandler.csproj @@ -61,6 +61,7 @@ + @@ -75,6 +76,7 @@ + diff --git a/IISMainHandler/handlers/request/EditHandler.cs b/IISMainHandler/handlers/request/EditHandler.cs new file mode 100644 index 0000000..ad5e13d --- /dev/null +++ b/IISMainHandler/handlers/request/EditHandler.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using FLocal.Common.dataobjects; + +namespace FLocal.IISHandler.handlers.request { + class EditHandler : AbstractNewMessageHandler { + + protected override string templateName { + get { + return "result/MessageEdited.xslt"; + } + } + + protected override XElement[] Do(WebContext context) { + + Post post = Post.LoadById(int.Parse(context.httprequest.Form["postId"])); + XElement postXml = post.exportToXmlWithoutThread(context, false); + post.Edit( + context.session.account.user, + this.getTitle(context), + this.getBody(context), + PostLayer.LoadById(int.Parse(context.httprequest.Form["layerId"])) + ); + + return new XElement[] { + post.thread.board.exportToXml(context, false), + postXml + }; + } + + } +} diff --git a/IISMainHandler/handlers/response/EditHandler.cs b/IISMainHandler/handlers/response/EditHandler.cs new file mode 100644 index 0000000..ee9520f --- /dev/null +++ b/IISMainHandler/handlers/response/EditHandler.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.Xml.Linq; +using FLocal.Core; +using FLocal.Common; +using FLocal.Common.dataobjects; + +namespace FLocal.IISHandler.handlers.response { + + class EditHandler : AbstractGetHandler { + + override protected string templateName { + get { + return "PostEdit.xslt"; + } + } + + override protected XElement[] getSpecificData(WebContext context) { + Post post = Post.LoadById(int.Parse(context.requestParts[1])); + + return new XElement[] { + post.thread.board.exportToXml(context, false), + post.thread.exportToXml(context, false), + post.exportToXmlWithoutThread(context, false), + post.latestRevision.exportToXml(context), + new XElement("layers", + from layer in PostLayer.allLayers select layer.exportToXml(context) + ), + }; + } + } + +} \ No newline at end of file diff --git a/templates/Full/PostEdit.xslt b/templates/Full/PostEdit.xslt new file mode 100644 index 0000000..853bf14 --- /dev/null +++ b/templates/Full/PostEdit.xslt @@ -0,0 +1,99 @@ + + + + + + + + + +
+ + + + + + + + + + +
+ Èçìåíåíèå ñîîáùåíèÿ ( + + ) +
+ Çàïîëíèòå ïðèâåäåííóþ íèæå ôîðìó äëÿ èçìåíåíèÿ ñîîáùåíèÿ +
+
+ + + + Ïîëüçîâàòåëü: + +
+
+ Òåìà: +
+ + + + Ñëîé ñîîáùåíèÿ: + +
+
+ + + +
+ + ß õî÷ó ïðåäâàðèòåëüíî ïðîñìîòðåòü ñîîáùåíèå ïåðåä îòïðàâêîé +
+
+ + Ïðîâåðèòü ïðàâîïèñàíèå +
+
+ + +
+
+ +
+ + + + + +
+ + + + + + + + + + +
+ Îòâåò íà ñîîáùåíèå +
+ + Àâòîð: + +
+ Òåìà: + +
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/templates/Full/elems/PostInfo.xslt b/templates/Full/elems/PostInfo.xslt index 670fb31..aec1b8c 100644 --- a/templates/Full/elems/PostInfo.xslt +++ b/templates/Full/elems/PostInfo.xslt @@ -66,6 +66,9 @@ + + /Post//Edit/ + Ïðàâêà ñîîáùåíèÿ @@ -116,6 +119,22 @@ + + + + + + Ýòî ñîîáùåíèå áûëî îòðåäàêòèðîâàíî ïîëüçîâàòåëåì + + ðàç, ïîñëåäíèé ðàç + +
+
+
+ + +
+
diff --git a/templates/Full/result/MessageEdited.xslt b/templates/Full/result/MessageEdited.xslt new file mode 100644 index 0000000..09e9b84 --- /dev/null +++ b/templates/Full/result/MessageEdited.xslt @@ -0,0 +1,47 @@ + + + + + + + + + + + +
+ + + + +
+ Èçìåíåíèå ñîîáùåíèÿ +
+
+ + + + +
+

Âàøå ñîîáùåíèå áûëî óñïåøíî èçìåíåíî

+

+ [←] + + /Board// + Âåðíóòüñÿ â ðàçäåë + + | + + /Thread//p + Ïðîñìîòðåòü ñîîáùåíèå + + [→] +

+ +
+
+
+ +
\ No newline at end of file