Merge branch 'develop' into event_signing

Conflicts:
	synapse/federation/replication.py
This commit is contained in:
Mark Haines 2014-10-17 17:33:58 +01:00
commit dc3c2823ac
21 changed files with 101 additions and 849 deletions

View File

@ -1,510 +0,0 @@
/*
* basic.css
* ~~~~~~~~~
*
* Sphinx stylesheet -- basic theme.
*
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
img {
border: 0;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li div.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable {
width: 100%;
}
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable dl, table.indextable dd {
margin-top: 0;
margin-bottom: 0;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
div.modindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
div.genindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
/* -- general body styles --------------------------------------------------- */
a.headerlink {
visibility: hidden;
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink {
visibility: visible;
}
div.document p.caption {
text-align: inherit;
}
div.document td {
text-align: left;
}
.field-list ul {
padding-left: 1em;
}
.first {
margin-top: 0 !important;
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
.align-left {
text-align: left;
}
.align-center {
clear: both;
text-align: center;
}
.align-right {
text-align: right;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px 7px 0 7px;
background-color: #ffe;
width: 40%;
float: right;
}
p.sidebar-title {
font-weight: bold;
}
/* -- topics ---------------------------------------------------------------- */
div.topic {
border: 1px solid #ccc;
padding: 7px 7px 0 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
div.admonition dl {
margin-bottom: 0;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.document p.centered {
text-align: center;
margin-top: 25px;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
border: 0;
border-collapse: collapse;
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 5px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.field-list td, table.field-list th {
border: 0 !important;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
th {
text-align: left;
padding-right: 5px;
}
table.citation {
border-left: solid 1px gray;
margin-left: 1px;
}
table.citation td {
border-bottom: none;
}
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
list-style: decimal;
}
ol.loweralpha {
list-style: lower-alpha;
}
ol.upperalpha {
list-style: upper-alpha;
}
ol.lowerroman {
list-style: lower-roman;
}
ol.upperroman {
list-style: upper-roman;
}
dl {
margin-bottom: 15px;
}
dd p {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dt:target, .highlighted {
background-color: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.refcount {
color: #060;
}
.optional {
font-size: 1.3em;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #ffa
}
.line-block {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}
.line-block .line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 1.5em;
}
.guilabel, .menuselection {
font-family: sans-serif;
}
.accelerator {
text-decoration: underline;
}
.classifier {
font-style: oblique;
}
/* -- code displays --------------------------------------------------------- */
pre {
overflow: auto;
}
td.linenos pre {
padding: 5px 0px;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
tt.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
tt.descclassname {
background-color: transparent;
}
tt.xref, a tt {
background-color: transparent;
font-weight: bold;
}
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
background-color: transparent;
}
.viewcode-link {
float: right;
}
.viewcode-back {
float: right;
font-family: sans-serif;
}
div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.document div.math p {
text-align: center;
}
span.eqno {
float: right;
}
/* -- printout stylesheet --------------------------------------------------- */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0 !important;
width: 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
#top-link {
display: none;
}
}

View File

@ -1,14 +0,0 @@
#!/bin/bash
MATRIXDOTORG=$HOME/workspace/matrix.org
rst2html-2.7.py --stylesheet=basic.css,nature.css ../docs/specification.rst > $MATRIXDOTORG/docs/spec/index.html
rst2html-2.7.py --stylesheet=basic.css,nature.css ../docs/client-server/howto.rst > $MATRIXDOTORG/docs/howtos/client-server.html
perl -pi -e 's#<head>#<head><link rel="stylesheet" href="/site.css">#' $MATRIXDOTORG/docs/spec/index.html $MATRIXDOTORG/docs/howtos/client-server.html
perl -pi -e 's#<body>#<body><div id="header"><div id="headerContent">&nbsp;</div></div><div id="page"><div id="wrapper"><div style="text-align: center; padding: 40px;"><a href="/"><img src="/matrix.png" width="305" height="130" alt="[matrix]"/></a></div>#' $MATRIXDOTORG/docs/spec/index.html $MATRIXDOTORG/docs/howtos/client-server.html
perl -pi -e 's#</body>#</div></div><div id="footer"><div id="footerContent">&copy 2014 Matrix.org</div></div></body>#' $MATRIXDOTORG/docs/spec/index.html $MATRIXDOTORG/docs/howtos/client-server.html
scp -r $MATRIXDOTORG/docs matrix@ldc-prd-matrix-001:/sites/matrix

View File

@ -1,270 +0,0 @@
/*
* nature.css_t
* ~~~~~~~~~~~~
*
* Sphinx stylesheet -- nature theme.
*
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/* -- page layout ----------------------------------------------------------- */
body {
font-family: Arial, sans-serif;
font-size: 100%;
/*background-color: #111;*/
color: #555;
margin: 0;
padding: 0;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
hr {
border: 1px solid #B1B4B6;
}
/*
div.document {
background-color: #eee;
}
*/
div.document {
background-color: #ffffff;
color: #3E4349;
padding: 0 30px 30px 30px;
font-size: 0.9em;
}
div.footer {
color: #555;
width: 100%;
padding: 13px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #444;
text-decoration: underline;
}
div.related {
background-color: #6BA81E;
line-height: 32px;
color: #fff;
text-shadow: 0px 1px 0 #444;
font-size: 0.9em;
}
div.related a {
color: #E2F3CC;
}
div.sphinxsidebar {
font-size: 0.75em;
line-height: 1.5em;
}
div.sphinxsidebarwrapper{
padding: 20px 0;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
font-family: Arial, sans-serif;
color: #222;
font-size: 1.2em;
font-weight: normal;
margin: 0;
padding: 5px 10px;
background-color: #ddd;
text-shadow: 1px 1px 0 white
}
div.sphinxsidebar h4{
font-size: 1.1em;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p {
color: #888;
padding: 5px 20px;
}
div.sphinxsidebar p.topless {
}
div.sphinxsidebar ul {
margin: 10px 20px;
padding: 0;
color: #000;
}
div.sphinxsidebar a {
color: #444;
}
div.sphinxsidebar input {
border: 1px solid #ccc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar input[type=text]{
margin-left: 20px;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #005B81;
text-decoration: none;
}
a:hover {
color: #E32E00;
text-decoration: underline;
}
div.document h1,
div.document h2,
div.document h3,
div.document h4,
div.document h5,
div.document h6 {
font-family: Arial, sans-serif;
background-color: #BED4EB;
font-weight: normal;
color: #212224;
margin: 30px 0px 10px 0px;
padding: 5px 0 5px 10px;
text-shadow: 0px 1px 0 white
}
div.document h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
div.document h2 { font-size: 150%; background-color: #C8D5E3; }
div.document h3 { font-size: 120%; background-color: #D8DEE3; }
div.document h4 { font-size: 110%; background-color: #D8DEE3; }
div.document h5 { font-size: 100%; background-color: #D8DEE3; }
div.document h6 { font-size: 100%; background-color: #D8DEE3; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.document p, div.document dd, div.document li {
line-height: 1.5em;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.highlight{
background-color: white;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 10px;
background-color: White;
color: #222;
line-height: 1.2em;
border: 1px solid #C6C9CB;
font-size: 1.1em;
margin: 1.5em 0 1.5em 0;
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
-moz-box-shadow: 1px 1px 1px #d8d8d8;
}
tt {
background-color: #ecf0f3;
color: #222;
/* padding: 1px 2px; */
font-size: 1.1em;
font-family: monospace;
}
.viewcode-back {
font-family: Arial, sans-serif;
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
p {
margin: 0;
}
ul li dd {
margin-top: 0;
}
ul li dl {
margin-bottom: 0;
}
li dl dd {
margin-bottom: 0;
}
dd ul {
padding-left: 0;
}
li dd ul {
margin-bottom: 0;
}

View File

@ -58,8 +58,8 @@ class EventFactory(object):
random_string(10), self.hs.hostname
)
if "ts" not in kwargs:
kwargs["ts"] = int(self.clock.time_msec())
if "origin_server_ts" not in kwargs:
kwargs["origin_server_ts"] = int(self.clock.time_msec())
# The "age" key is a delta timestamp that should be converted into an
# absolute timestamp the minute we see it.

View File

@ -95,8 +95,8 @@ class PduCodec(object):
if k not in ["event_id", "room_id", "type"]
})
if "ts" not in kwargs:
kwargs["ts"] = int(self.clock.time_msec())
if "origin_server_ts" not in kwargs:
kwargs["origin_server_ts"] = int(self.clock.time_msec())
pdu = Pdu(**kwargs)
pdu = add_event_pdu_content_hash(pdu)

View File

@ -157,7 +157,7 @@ class TransactionActions(object):
transaction.prev_ids = yield self.store.prep_send_transaction(
transaction.transaction_id,
transaction.destination,
transaction.ts,
transaction.origin_server_ts,
[(p["pdu_id"], p["origin"]) for p in transaction.pdus]
)

View File

@ -427,7 +427,7 @@ class ReplicationLayer(object):
return Transaction(
origin=self.server_name,
pdus=pdus,
ts=int(time_now),
origin_server_ts=int(time_now),
destination=None,
)
@ -595,7 +595,7 @@ class _TransactionQueue(object):
logger.debug("TX [%s] Persisting transaction...", destination)
transaction = Transaction.create_new(
ts=int(self._clock.time_msec()),
origin_server_ts=int(self._clock.time_msec()),
transaction_id=str(self._next_txn_id),
origin=self.server_name,
destination=destination,

View File

@ -41,7 +41,7 @@ class Pdu(JsonEncodedObject):
{
"pdu_id": "78c",
"ts": 1404835423000,
"origin_server_ts": 1404835423000,
"origin": "bar",
"prev_ids": [
["23b", "foo"],
@ -56,7 +56,7 @@ class Pdu(JsonEncodedObject):
"pdu_id",
"context",
"origin",
"ts",
"origin_server_ts",
"pdu_type",
"destinations",
"transaction_id",
@ -84,7 +84,7 @@ class Pdu(JsonEncodedObject):
"pdu_id",
"context",
"origin",
"ts",
"origin_server_ts",
"pdu_type",
"content",
]
@ -122,6 +122,7 @@ class Pdu(JsonEncodedObject):
"""
if pdu_tuple:
d = copy.copy(pdu_tuple.pdu_entry._asdict())
d["origin_server_ts"] = d.pop("ts")
for k in d.keys():
if d[k] is None:
@ -212,7 +213,7 @@ class Transaction(JsonEncodedObject):
"transaction_id",
"origin",
"destination",
"ts",
"origin_server_ts",
"previous_ids",
"pdus",
"edus",
@ -229,7 +230,7 @@ class Transaction(JsonEncodedObject):
"transaction_id",
"origin",
"destination",
"ts",
"origin_server_ts",
"pdus",
]
@ -251,10 +252,10 @@ class Transaction(JsonEncodedObject):
@staticmethod
def create_new(pdus, **kwargs):
""" Used to create a new transaction. Will auto fill out
transaction_id and ts keys.
transaction_id and origin_server_ts keys.
"""
if "ts" not in kwargs:
raise KeyError("Require 'ts' to construct a Transaction")
if "origin_server_ts" not in kwargs:
raise KeyError("Require 'origin_server_ts' to construct a Transaction")
if "transaction_id" not in kwargs:
raise KeyError(
"Require 'transaction_id' to construct a Transaction"

View File

@ -64,7 +64,7 @@ class MessageHandler(BaseHandler):
defer.returnValue(None)
@defer.inlineCallbacks
def send_message(self, event=None, suppress_auth=False, stamp_event=True):
def send_message(self, event=None, suppress_auth=False):
""" Send a message.
Args:
@ -72,7 +72,6 @@ class MessageHandler(BaseHandler):
suppress_auth (bool) : True to suppress auth for this message. This
is primarily so the home server can inject messages into rooms at
will.
stamp_event (bool) : True to stamp event content with server keys.
Raises:
SynapseError if something went wrong.
"""
@ -82,9 +81,6 @@ class MessageHandler(BaseHandler):
user = self.hs.parse_userid(event.user_id)
assert user.is_mine, "User must be our own: %s" % (user,)
if stamp_event:
event.content["hsob_ts"] = int(self.clock.time_msec())
snapshot = yield self.store.snapshot_room(event.room_id, event.user_id)
if not suppress_auth:
@ -132,7 +128,7 @@ class MessageHandler(BaseHandler):
defer.returnValue(chunk)
@defer.inlineCallbacks
def store_room_data(self, event=None, stamp_event=True):
def store_room_data(self, event=None):
""" Stores data for a room.
Args:
@ -151,9 +147,6 @@ class MessageHandler(BaseHandler):
yield self.auth.check(event, snapshot, raises=True)
if stamp_event:
event.content["hsob_ts"] = int(self.clock.time_msec())
yield self.state_handler.handle_new_event(event, snapshot)
yield self._on_new_room_event(event, snapshot)
@ -221,10 +214,7 @@ class MessageHandler(BaseHandler):
defer.returnValue(None)
@defer.inlineCallbacks
def send_feedback(self, event, stamp_event=True):
if stamp_event:
event.content["hsob_ts"] = int(self.clock.time_msec())
def send_feedback(self, event):
snapshot = yield self.store.snapshot_room(event.room_id, event.user_id)
yield self.auth.check(event, snapshot, raises=True)

View File

@ -68,7 +68,7 @@ class PresenceStatusRestServlet(RestServlet):
yield self.handlers.presence_handler.set_state(
target_user=user, auth_user=auth_user, state=state)
defer.returnValue((200, ""))
defer.returnValue((200, {}))
def on_OPTIONS(self, request):
return (200, {})
@ -141,7 +141,7 @@ class PresenceListRestServlet(RestServlet):
yield defer.DeferredList(deferreds)
defer.returnValue((200, ""))
defer.returnValue((200, {}))
def on_OPTIONS(self, request):
return (200, {})

View File

@ -163,6 +163,8 @@ class DataStore(RoomMemberStore, RoomStore,
cols["unrecognized_keys"] = json.dumps(unrec_keys)
cols["ts"] = cols.pop("origin_server_ts")
logger.debug("Persisting: %s", repr(cols))
for hash_alg, hash_base64 in pdu.hashes.items():

View File

@ -354,6 +354,7 @@ class SQLBaseStore(object):
d.pop("stream_ordering", None)
d.pop("topological_ordering", None)
d.pop("processed", None)
d["origin_server_ts"] = d.pop("ts", 0)
d.update(json.loads(row_dict["unrecognized_keys"]))
d["content"] = json.loads(d["content"])
@ -361,7 +362,7 @@ class SQLBaseStore(object):
if "age_ts" not in d:
# For compatibility
d["age_ts"] = d["ts"] if "ts" in d else 0
d["age_ts"] = d.get("origin_server_ts", 0)
return self.event_factory.create_event(
etype=d["type"],

View File

@ -87,7 +87,8 @@ class TransactionStore(SQLBaseStore):
txn.execute(query, (code, response_json, transaction_id, origin))
def prep_send_transaction(self, transaction_id, destination, ts, pdu_list):
def prep_send_transaction(self, transaction_id, destination,
origin_server_ts, pdu_list):
"""Persists an outgoing transaction and calculates the values for the
previous transaction id list.
@ -97,7 +98,7 @@ class TransactionStore(SQLBaseStore):
Args:
transaction_id (str)
destination (str)
ts (int)
origin_server_ts (int)
pdu_list (list)
Returns:
@ -106,11 +107,11 @@ class TransactionStore(SQLBaseStore):
return self.runInteraction(
self._prep_send_transaction,
transaction_id, destination, ts, pdu_list
transaction_id, destination, origin_server_ts, pdu_list
)
def _prep_send_transaction(self, txn, transaction_id, destination, ts,
pdu_list):
def _prep_send_transaction(self, txn, transaction_id, destination,
origin_server_ts, pdu_list):
# First we find out what the prev_txs should be.
# Since we know that we are only sending one transaction at a time,
@ -131,7 +132,7 @@ class TransactionStore(SQLBaseStore):
None,
transaction_id=transaction_id,
destination=destination,
ts=ts,
ts=origin_server_ts,
response_code=0,
response_json=None
))

View File

@ -158,7 +158,7 @@ class FederationTestCase(unittest.TestCase):
origin="red",
destinations=["remote"],
context="my-context",
ts=123456789002,
origin_server_ts=123456789002,
pdu_type="m.test",
content={"testing": "content here"},
depth=1,
@ -170,14 +170,14 @@ class FederationTestCase(unittest.TestCase):
"remote",
path="/_matrix/federation/v1/send/1000000/",
data={
"ts": 1000000,
"origin_server_ts": 1000000,
"origin": "test",
"pdus": [
{
"origin": "red",
"pdu_id": "abc123def456",
"prev_pdus": [],
"ts": 123456789002,
"origin_server_ts": 123456789002,
"context": "my-context",
"pdu_type": "m.test",
"is_state": False,
@ -209,7 +209,7 @@ class FederationTestCase(unittest.TestCase):
path="/_matrix/federation/v1/send/1000000/",
data={
"origin": "test",
"ts": 1000000,
"origin_server_ts": 1000000,
"pdus": [],
"edus": [
{
@ -236,7 +236,7 @@ class FederationTestCase(unittest.TestCase):
"/_matrix/federation/v1/send/1001000/",
"""{
"origin": "remote",
"ts": 1001000,
"origin_server_ts": 1001000,
"pdus": [],
"edus": [
{

View File

@ -75,7 +75,7 @@ class PduCodecTestCase(unittest.TestCase):
context="rooooom",
pdu_type="m.room.message",
origin="bar.com",
ts=12345,
origin_server_ts=12345,
depth=5,
prev_pdus=[("alice", "bob.com")],
is_state=False,
@ -130,7 +130,7 @@ class PduCodecTestCase(unittest.TestCase):
context="rooooom",
pdu_type="m.room.topic",
origin="bar.com",
ts=12345,
origin_server_ts=12345,
depth=5,
prev_pdus=[("alice", "bob.com")],
is_state=True,

View File

@ -68,7 +68,7 @@ class FederationTestCase(unittest.TestCase):
pdu_type=MessageEvent.TYPE,
context="foo",
content={"msgtype": u"fooo"},
ts=0,
origin_server_ts=0,
pdu_id="a",
origin="b",
)
@ -95,7 +95,7 @@ class FederationTestCase(unittest.TestCase):
target_host=self.hostname,
context=room_id,
content={},
ts=0,
origin_server_ts=0,
pdu_id="a",
origin="b",
)
@ -127,7 +127,7 @@ class FederationTestCase(unittest.TestCase):
state_key="@red:not%s" % self.hostname,
context=room_id,
content={},
ts=0,
origin_server_ts=0,
pdu_id="a",
origin="b",
)

View File

@ -39,7 +39,7 @@ ONLINE = PresenceState.ONLINE
def _expect_edu(destination, edu_type, content, origin="test"):
return {
"origin": origin,
"ts": 1000000,
"origin_server_ts": 1000000,
"pdus": [],
"edus": [
{

View File

@ -29,7 +29,7 @@ from synapse.handlers.typing import TypingNotificationHandler
def _expect_edu(destination, edu_type, content, origin="test"):
return {
"origin": origin,
"ts": 1000000,
"origin_server_ts": 1000000,
"pdus": [],
"edus": [
{

View File

@ -599,7 +599,7 @@ def new_fake_pdu(pdu_id, context, pdu_type, state_key, prev_state_id,
prev_state_id=prev_state_id,
origin="example.com",
context="context",
ts=1405353060021,
origin_server_ts=1405353060021,
depth=depth,
content_json="{}",
unrecognized_keys="{}",

View File

@ -80,4 +80,53 @@ angular.module('matrixWebClient')
return function(text) {
return $sce.trustAsHtml(text);
};
}])
// Exactly the same as ngSanitize's linky but instead of pushing sanitized
// text in the addText function, we just push the raw text.
.filter('unsanitizedLinky', ['$sanitize', function($sanitize) {
var LINKY_URL_REGEXP =
/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"]/,
MAILTO_REGEXP = /^mailto:/;
return function(text, target) {
if (!text) return text;
var match;
var raw = text;
var html = [];
var url;
var i;
while ((match = raw.match(LINKY_URL_REGEXP))) {
// We can not end in these as they are sometimes found at the end of the sentence
url = match[0];
// if we did not match ftp/http/mailto then assume mailto
if (match[2] == match[3]) url = 'mailto:' + url;
i = match.index;
addText(raw.substr(0, i));
addLink(url, match[0].replace(MAILTO_REGEXP, ''));
raw = raw.substring(i + match[0].length);
}
addText(raw);
return $sanitize(html.join(''));
function addText(text) {
if (!text) {
return;
}
html.push(text);
}
function addLink(url, text) {
html.push('<a ');
if (angular.isDefined(target)) {
html.push('target="');
html.push(target);
html.push('" ');
}
html.push('href="');
html.push(url);
html.push('">');
addText(text);
html.push('</a>');
}
};
}]);

View File

@ -121,7 +121,9 @@
<span ng-show='msg.content.msgtype === "m.text"'
class="message"
ng-class="containsBingWord(msg.content.body) && msg.user_id != state.user_id ? msg.echo_msg_state + ' messageBing' : msg.echo_msg_state"
ng-bind-html="((msg.content.msgtype === 'm.text') ? msg.content.body : '') | linky:'_blank'"/>
ng-bind-html="(msg.content.msgtype === 'm.text' && msg.type === 'm.room.message' && msg.content.format === 'org.matrix.custom.html') ?
(msg.content.formatted_body | unsanitizedLinky) :
(msg.content.msgtype === 'm.text' && msg.type === 'm.room.message') ? (msg.content.body | linky:'_blank') : '' "/>
<span ng-show='msg.type === "m.call.invite" && msg.user_id == state.user_id'>Outgoing Call{{ isWebRTCSupported ? '' : ' (But your browser does not support VoIP)' }}</span>
<span ng-show='msg.type === "m.call.invite" && msg.user_id != state.user_id'>Incoming Call{{ isWebRTCSupported ? '' : ' (But your browser does not support VoIP)' }}</span>