From 40ae44b2fd091c2475e6cd1f7c12c78658303d4d Mon Sep 17 00:00:00 2001 From: wgroeneveld Date: Mon, 26 Apr 2021 11:15:11 +0200 Subject: [PATCH] sanitize receiving publication dates, this caused yet another crash... --- README.md | 3 + app/mf/microformats.go | 39 +++- app/mf/microformats_test.go | 100 +++++++++ app/webmention/recv/receive.go | 4 +- app/webmention/recv/receive_test.go | 12 +- common/config.go | 5 + mentions.db | 336 ++++++++++++++++++++++++++++ 7 files changed, 484 insertions(+), 15 deletions(-) create mode 100644 app/mf/microformats_test.go diff --git a/README.md b/README.md index e5b1367..efa837c 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,9 @@ Will result in a `202 Accepted` - it handles things async. Stores in `.json` fil This also saves the author picture/avatar locally - if present in the microformat. It does _not_ resize images, however, if it's bigger than 5 MB, it falls back to a default one. +Publication dates are sanitized and stored in `published`. They should be formatted in ISO8601. See [RFC3339](https://www.ietf.org/rfc/rfc3339.txt). +If that is not the case, go-jamming falls back to the moment the mention was received. + #### 1.2 `GET /webmention/:domain/:token` Retrieves a JSON array with relevant webmentions stored for that domain. The token should match. See configuration to fiddle with it yourself. diff --git a/app/mf/microformats.go b/app/mf/microformats.go index fdef9e6..94343a0 100644 --- a/app/mf/microformats.go +++ b/app/mf/microformats.go @@ -9,8 +9,24 @@ import ( ) const ( - DateFormat = "2006-01-02T15:04:05" - Anonymous = "anonymous" + dateFormatWithTimeZone = "2006-01-02T15:04:05-07:00" + dateFormatWithAbsoluteTimeZone = "2006-01-02T15:04:05-0700" + dateFormatWithTimeZoneSuffixed = "2006-01-02T15:04:05.000Z" + dateFormatWithoutTimeZone = "2006-01-02T15:04:05" + dateFormatWithSecondsWithoutTimeZone = "2006-01-02T15:04:05.00Z" + dateFormatWithoutTime = "2006-01-02" + Anonymous = "anonymous" +) + +var ( + supportedFormats = []string{ + dateFormatWithTimeZone, + dateFormatWithAbsoluteTimeZone, + dateFormatWithTimeZoneSuffixed, + dateFormatWithSecondsWithoutTimeZone, + dateFormatWithoutTimeZone, + dateFormatWithoutTime, + } ) type IndiewebAuthor struct { @@ -63,8 +79,8 @@ func (id *IndiewebData) IsEmpty() bool { return id.Url == "" } -func PublishedNow(utcOffset int) string { - return common.Now().UTC().Add(time.Duration(utcOffset) * time.Minute).Format("2006-01-02T15:04:05") +func PublishedNow(zone *time.Location) string { + return common.Now().UTC().In(zone).Format(dateFormatWithTimeZone) } func shorten(txt string) string { @@ -145,12 +161,21 @@ func Prop(mf *microformats.Microformat, key string) *microformats.Microformat { return mfEmpty() } -func Published(hEntry *microformats.Microformat, utcOffset int) string { +func Published(hEntry *microformats.Microformat, zone *time.Location) string { publishedDate := Str(hEntry, "published") if publishedDate == "" { - return PublishedNow(utcOffset) + return PublishedNow(zone) } - return publishedDate + + for _, format := range supportedFormats { + formatted, err := time.Parse(format, publishedDate) + if err != nil { + continue + } + return formatted.Format(dateFormatWithTimeZone) + } + + return PublishedNow(zone) } func NewAuthor(hEntry *microformats.Microformat, hCard *microformats.Microformat) IndiewebAuthor { diff --git a/app/mf/microformats_test.go b/app/mf/microformats_test.go new file mode 100644 index 0000000..b2cc509 --- /dev/null +++ b/app/mf/microformats_test.go @@ -0,0 +1,100 @@ +package mf + +import ( + "brainbaking.com/go-jamming/common" + "github.com/stretchr/testify/assert" + "testing" + "time" + "willnorris.com/go/microformats" +) + +func TestPublished(t *testing.T) { + cases := []struct { + label string + raw string + expectedTime string + }{ + { + "Converts published date in RFC3339 ISO8601 indieweb datetime format with timezone", + "2021-04-25T11:24:48+02:00", + "2021-04-25T11:24:48+02:00", + }, + { + "Converts published date in RFC3339 ISO8601 indieweb datetime format with absolute timezone", + "2021-04-25T11:24:48+0200", + "2021-04-25T11:24:48+02:00", + }, + { + "Converts published date in RFC3339 ISO8601 indieweb datetime format with timezone suffixed with Z", + "2021-03-02T16:17:18.000Z", + "2021-03-02T16:17:18+00:00", + }, + { + "Converts published date in RFC3339 ISO8601 indieweb datetime format without timezone", + "2021-04-25T11:24:48", + "2021-04-25T11:24:48+00:00", + }, + { + "Converts published date in RFC3339 ISO8601 indieweb datetime format without time", + "2021-04-25", + "2021-04-25T00:00:00+00:00", + }, + { + "Returns current date if property with correct timezone not found", + "", + "2020-01-01T13:30:00+01:00", + }, + { + "Reverts to current date if not in correct ISO8601 datetime format", + "26 April 2021", + "2020-01-01T13:30:00+01:00", + }, + { + "https://www.ietf.org/rfc/rfc3339.txt example 1", + "1985-04-12T23:20:50.52Z", + "1985-04-12T23:20:50+00:00", + }, + { + "https://www.ietf.org/rfc/rfc3339.txt example 2", + "1996-12-19T16:39:57-08:00", + "1996-12-19T16:39:57-08:00", + }, + { + "https://www.ietf.org/rfc/rfc3339.txt example 3 explicitly not implemented", + "1990-12-31T23:59:60Z", + "2020-01-01T13:30:00+01:00", + }, + { + "https://www.ietf.org/rfc/rfc3339.txt example 4 explicitly not implemented", + "1990-12-31T15:59:60-08:00", + "2020-01-01T13:30:00+01:00", + }, + { + "https://www.ietf.org/rfc/rfc3339.txt example 5 with seconds ignored", + "1937-01-01T12:00:27.87+00:20", + "1937-01-01T12:00:27+00:20", + }, + } + common.Now = func() time.Time { + return time.Date(2020, time.January, 1, 12, 30, 0, 0, time.UTC) + } + utcPlusOne := time.FixedZone("UTC+1", 60*60) + defer func() { + common.Now = time.Now + }() + + for _, tc := range cases { + t.Run(tc.label, func(t *testing.T) { + props := map[string][]interface{}{} + props["published"] = []interface{}{ + tc.raw, + } + theTime := Published(µformats.Microformat{ + Properties: props, + }, utcPlusOne) + + assert.Equal(t, tc.expectedTime, theTime) + }) + + } +} diff --git a/app/webmention/recv/receive.go b/app/webmention/recv/receive.go index 1ab6e7a..f70cd6a 100644 --- a/app/webmention/recv/receive.go +++ b/app/webmention/recv/receive.go @@ -85,7 +85,7 @@ func (recv *Receiver) parseBodyAsIndiewebSite(hEntry *microformats.Microformat, Author: mf.NewAuthor(hEntry, hCard), Content: mf.Content(hEntry), Url: mf.Url(hEntry, wm.Source), - Published: mf.Published(hEntry, recv.Conf.UtcOffset), + Published: mf.Published(hEntry, recv.Conf.Zone()), Source: wm.Source, Target: wm.Target, IndiewebType: mf.Type(hEntry), @@ -100,7 +100,7 @@ func (recv *Receiver) parseBodyAsNonIndiewebSite(body string, wm mf.Mention) *mf }, Name: title, Content: title, - Published: mf.PublishedNow(recv.Conf.UtcOffset), + Published: mf.PublishedNow(recv.Conf.Zone()), Url: wm.Source, IndiewebType: mf.TypeMention, Source: wm.Source, diff --git a/app/webmention/recv/receive_test.go b/app/webmention/recv/receive_test.go index 86d3d53..d97c3e6 100644 --- a/app/webmention/recv/receive_test.go +++ b/app/webmention/recv/receive_test.go @@ -126,7 +126,7 @@ func TestReceive(t *testing.T) { Source: "https://brainbaking.com/valid-bridgy-twitter-source.html", Target: "https://brainbaking.com/post/2021/03/the-indieweb-mixed-bag", }, - json: `{"author":{"name":"Jamie Tanna","picture":"/pictures/brainbaking.com"},"name":"","content":"Recommended read:\nThe IndieWeb Mixed Bag - Thoughts about the (d)evolution of blog interactions\nhttps://brainbaking.com/post/2021/03/the-indieweb-mixed-bag/","published":"2021-03-15T12:42:00+0000","url":"https://brainbaking.com/mf2/2021/03/1bkre/","type":"bookmark","source":"https://brainbaking.com/valid-bridgy-twitter-source.html","target":"https://brainbaking.com/post/2021/03/the-indieweb-mixed-bag"}`, + json: `{"author":{"name":"Jamie Tanna","picture":"/pictures/brainbaking.com"},"name":"","content":"Recommended read:\nThe IndieWeb Mixed Bag - Thoughts about the (d)evolution of blog interactions\nhttps://brainbaking.com/post/2021/03/the-indieweb-mixed-bag/","published":"2021-03-15T12:42:00+00:00","url":"https://brainbaking.com/mf2/2021/03/1bkre/","type":"bookmark","source":"https://brainbaking.com/valid-bridgy-twitter-source.html","target":"https://brainbaking.com/post/2021/03/the-indieweb-mixed-bag"}`, }, { label: "receive a brid.gy Webmention like", @@ -136,7 +136,7 @@ func TestReceive(t *testing.T) { Target: "https://brainbaking.com/valid-indieweb-target.html", }, // no dates in bridgy-to-mastodon likes... - json: `{"author":{"name":"Stampeding Longhorn","picture":"/pictures/brainbaking.com"},"name":"","content":"","published":"2020-01-01T12:30:00","url":"https://chat.brainbaking.com/notice/A4nx1rFwKUJYSe4TqK#favorited-by-A4nwg4LYyh4WgrJOXg","type":"like","source":"https://brainbaking.com/valid-bridgy-like.html","target":"https://brainbaking.com/valid-indieweb-target.html"}`, + json: `{"author":{"name":"Stampeding Longhorn","picture":"/pictures/brainbaking.com"},"name":"","content":"","published":"2020-01-01T12:30:00+00:00","url":"https://chat.brainbaking.com/notice/A4nx1rFwKUJYSe4TqK#favorited-by-A4nwg4LYyh4WgrJOXg","type":"like","source":"https://brainbaking.com/valid-bridgy-like.html","target":"https://brainbaking.com/valid-indieweb-target.html"}`, }, { label: "receive a brid.gy Webmention that has a url and photo without value", @@ -144,7 +144,7 @@ func TestReceive(t *testing.T) { Source: "https://brainbaking.com/valid-bridgy-source.html", Target: "https://brainbaking.com/valid-indieweb-target.html", }, - json: `{"author":{"name":"Stampeding Longhorn", "picture":"/pictures/brainbaking.com"}, "content":"@wouter The cat pictures are awesome. for jest tests!", "name":"@wouter The cat pictures are awesome. for jest tests!", "published":"2021-03-02T16:17:18.000Z", "source":"https://brainbaking.com/valid-bridgy-source.html", "target":"https://brainbaking.com/valid-indieweb-target.html", "type":"mention", "url":"https://social.linux.pizza/@StampedingLonghorn/105821099684887793"}`, + json: `{"author":{"name":"Stampeding Longhorn", "picture":"/pictures/brainbaking.com"}, "content":"@wouter The cat pictures are awesome. for jest tests!", "name":"@wouter The cat pictures are awesome. for jest tests!", "published":"2021-03-02T16:17:18+00:00", "source":"https://brainbaking.com/valid-bridgy-source.html", "target":"https://brainbaking.com/valid-indieweb-target.html", "type":"mention", "url":"https://social.linux.pizza/@StampedingLonghorn/105821099684887793"}`, }, { label: "receive saves a JSON file of indieweb-metadata if all is valid", @@ -152,7 +152,7 @@ func TestReceive(t *testing.T) { Source: "https://brainbaking.com/valid-indieweb-source.html", Target: "https://jefklakscodex.com/articles", }, - json: `{"author":{"name":"Wouter Groeneveld","picture":"/pictures/brainbaking.com"},"name":"I just learned about https://www.inklestudios.com/...","content":"This is cool, I just found out about valid indieweb target - so cool","published":"2021-03-06T12:41:00","url":"https://brainbaking.com/notes/2021/03/06h12m41s48/","type":"mention","source":"https://brainbaking.com/valid-indieweb-source.html","target":"https://jefklakscodex.com/articles"}`, + json: `{"author":{"name":"Wouter Groeneveld","picture":"/pictures/brainbaking.com"},"name":"I just learned about https://www.inklestudios.com/...","content":"This is cool, I just found out about valid indieweb target - so cool","published":"2021-03-06T12:41:00+00:00","url":"https://brainbaking.com/notes/2021/03/06h12m41s48/","type":"mention","source":"https://brainbaking.com/valid-indieweb-source.html","target":"https://jefklakscodex.com/articles"}`, }, { label: "receive saves a JSON file of indieweb-metadata with summary as content if present", @@ -160,7 +160,7 @@ func TestReceive(t *testing.T) { Source: "https://brainbaking.com/valid-indieweb-source-with-summary.html", Target: "https://brainbaking.com/valid-indieweb-target.html", }, - json: `{"author":{"name":"Wouter Groeneveld", "picture":"/pictures/brainbaking.com"}, "content":"This is cool, this is a summary!", "name":"I just learned about https://www.inklestudios.com/...", "published":"2021-03-06T12:41:00", "source":"https://brainbaking.com/valid-indieweb-source-with-summary.html", "target":"https://brainbaking.com/valid-indieweb-target.html", "type":"mention", "url":"https://brainbaking.com/notes/2021/03/06h12m41s48/"}`, + json: `{"author":{"name":"Wouter Groeneveld", "picture":"/pictures/brainbaking.com"}, "content":"This is cool, this is a summary!", "name":"I just learned about https://www.inklestudios.com/...", "published":"2021-03-06T12:41:00+00:00", "source":"https://brainbaking.com/valid-indieweb-source-with-summary.html", "target":"https://brainbaking.com/valid-indieweb-target.html", "type":"mention", "url":"https://brainbaking.com/notes/2021/03/06h12m41s48/"}`, }, { label: "receive saves a JSON file of non-indieweb-data such as title if all is valid", @@ -168,7 +168,7 @@ func TestReceive(t *testing.T) { Source: "https://brainbaking.com/valid-nonindieweb-source.html", Target: "https://brainbaking.com/valid-indieweb-target.html", }, - json: `{"author":{"name":"https://brainbaking.com/valid-nonindieweb-source.html", "picture":""}, "content":"Diablo 2 Twenty Years Later: A Retrospective | Jefklaks Codex", "name":"Diablo 2 Twenty Years Later: A Retrospective | Jefklaks Codex", "published":"2020-01-01T12:30:00", "source":"https://brainbaking.com/valid-nonindieweb-source.html", "target":"https://brainbaking.com/valid-indieweb-target.html", "type":"mention", "url":"https://brainbaking.com/valid-nonindieweb-source.html"}`, + json: `{"author":{"name":"https://brainbaking.com/valid-nonindieweb-source.html", "picture":""}, "content":"Diablo 2 Twenty Years Later: A Retrospective | Jefklaks Codex", "name":"Diablo 2 Twenty Years Later: A Retrospective | Jefklaks Codex", "published":"2020-01-01T12:30:00+00:00", "source":"https://brainbaking.com/valid-nonindieweb-source.html", "target":"https://brainbaking.com/valid-indieweb-target.html", "type":"mention", "url":"https://brainbaking.com/valid-nonindieweb-source.html"}`, }, } diff --git a/common/config.go b/common/config.go index f44a233..d862e14 100644 --- a/common/config.go +++ b/common/config.go @@ -6,6 +6,7 @@ import ( "github.com/rs/zerolog/log" "io/ioutil" "strings" + "time" ) type Config struct { @@ -18,6 +19,10 @@ type Config struct { DisallowedWebmentionDomains []string `json:"disallowedWebmentionDomains"` } +func (c *Config) Zone() *time.Location { + return time.FixedZone("local", c.UtcOffset*60) +} + func (c *Config) missingKeys() []string { keys := []string{} if c.Port == 0 { diff --git a/mentions.db b/mentions.db index 544219c..07db498 100644 --- a/mentions.db +++ b/mentions.db @@ -376,3 +376,339 @@ $21 brainbaking.com:since $24 2021-04-19T15:51:50.183Z +*3 +$3 +set +$21 +brainbaking.com:since +$24 +2021-04-19T17:02:07.277Z +*3 +$3 +set +$21 +brainbaking.com:since +$24 +2021-04-19T17:55:47.794Z +*3 +$3 +set +$23 +brainbaking.com:picture +$4861 +JFIFC  + +  +  +    + C dd A!1AQa"q2BR#$c 3STr5CDb1!1QA"aс2q#B ?7js7d;zczğюüzʔÃa6c4}'.Ǽw=COwb]yV^NG~ssI/N_/HLsTAU`lm._ԘuJ\@Y'`{e{EMfۧ<^46/43۷q:r6LfD(XnGǠR !5H[^?,\}R4qЄ幱t߹WミE[F5en}qns?QOͳ^1`>}\NO +DTGͭCDS|seavԴnN z>A({FAEbYMf[67<#`DD]k)xߤF}H%uXQ]ntRm1"A?"\ ,}i.s_a&A-BF0KYWJ>\ gaAiz Chn (9tڙ~Dy 徳U>HCOeۈ}kؕ +@mu :y"EPm/Sihuj.´Æ\b)Pd-U.cWVu՝AX՚t'&}EMq9,|Uy6etePlm+$P!˝RRdRRL86*Z@Iv]FZTP&.'O\ziovʬD亣2f58"oxB_u + ;;Uu0(76 3*>$9͵ˢz40_+=t$zHA +Jnv1(F:D[[MKJRPt5dD=Z](xqlT Ru/1`}cĎ09u:bUES- j&Ц>@ǿG&eW?]*r;K,?ᷗ;,ks=ʎѲHa&S*D*o`}W/Y?YK3MΐjK.*-r6``vT763"WиAA WđJSmln iPI +m4!Yyi"J:vM"HIX@l\JFP +[dJf2`i1K56.V]i,)vmߩC-F.'*"`;w?ɕN%XŸ$wJr-h)G*AkT]t'Z%g_'N+5R*z.ʪuEm#?KXs[;\6N_$ 1t +J߬zx/[alUoUo510([G_O93 +nRVolMlSc/kF5CLi{Z-ƝݲMMk tƤURe +Ո\*yN6I#ف{ ;ΙT[(nkJ|>]u)]DG*>nr#hLց;tQ& Qȇ6jRS.: +W) q犕U]',ЉHjfbd:i.JrlʭI1]l?Wբ[1 $6J&KH{bi17&pOa_Z cZO)Y3ayivpaD>M0󓦚#8eYPQ-QI7z]ʵ?X?T4Ӿ-NY5Lj]9.Ř؆i) +`{d(m}t3iJ}#_x-L/2U[m- *\npjUYE 43>$Nޝr'Q8ƧJ:q'e!>e@}[K`5\AJqb:ٳÔ,i>ι5>TO_4t:8.,ARY%B;}M֗_Ra4O&RpqTjg֫SJMI.`MAjPe^B7J%#Dz\bKUj X9(^21z̳f@ֵSvF->Җ4VMo-v,$=: ,-/^ +qQͫSZiYt^ǯ3q]1ލ) B.=ŷs: !].ujY)3*BͅGk gQбr[vL_Y9t"=A2g)0xQkeIW%?HUpOG,૗o{)| l0t,j\L !'DFɱ C`c׶*3x7ȄQ_:lZw+YnIi`8Nف6Bmiߐ0Âc`mE7G$ykX ED8H6:8xI;dFzB$rd%-@6>V%%&t;ۧ(m)Xhxv殶<3UuɅLr3Xw2lOvnB-Itڏ/dGɄR3npwviՋ%j \)^$@/!@P%!&y/PlfM.ؖl[Ζ)wfWJbVS9s#$Dz/)VDsf)O9{BMDAt֖V8z(%\&Fk[ D/h\5|if/_RI:)dѢIMX +}[[h)t}q\KL3ń6ͿWURhn[K&r$JG? |C +0c*E?E61RK.yK9~?)6B%X~OeBǰx@<@ej臟:ƨ;Bqf \s{*)O7YXKېHJr/)%0b 42=!Vs M]?ӊ㣉@%&U !@s>&KO7d%.oH +ͯ=Yr #7G\R@c\f +*>m44$ wi7=~NߗiB(I0#QQBJ1wմn}} +8fDǓ(htqS~?egsQWBܽ<8k(ʷHgo'K?ț[d!5̋F"=ҼF C\o +hx +`߼P5gL6\>% ɳNƧ]B`*dAo"_$c yBe9{f}% "wCBK$c>%h) D Tx°mt€=ϼ>)h ]v1@NR"MW$qx{Jrk!=؉ e\U3m8D?/;%$\ Jѥ@ݑ5s w2 bVDB('bv9"dֺgo Bݼ=V˫;$ Ͽ'=&M4 +Sٛ`CAY_1y͟ޣ^ׯJMҊiW0I*=(΂M=lTPG|]k9hn_s5'~'0^HꄜE`7\mVr~gwU|u `4l#1‰@eDOb+Oo;:+_ H"x'ϊazjTd-$B , + #-ㇿ*I`?lC +N4Z(e?\̛ +܇Noy`|ҎA*f*i{LKg'+)( Nc_WHS($!GIjNrDJ &9RS|-jG$қ Zq">*FƬi_Eț_>%W6gqRJ\eo[r9^vnI A*3]"HIX"h<b 4(X.JHʻylPz{RkWhTػ{/}K +9="$[ <H +S Dq7Է(pNu@ 3µtxŽJx^#WU3i0 +xuKmyf\]_*W? +臀j mj 5ǟ|ƽx*a_Ds7)RJфPx,ƪ:cHzxW^fV`EdK +pJ$@b!=nӒBYxqʂ="Nx +ubO}uw-W@S̀N7,0tW~%pDspe-sE (_gɩ9ЋUPX.zN722_ yT]{iڸf=?m!@sO&_׊_8b׫6^=]|wwPxFx**bg]a')fTɷyxuGjI D/}i1@PڏƉ( +m᳘($&R _N]Ěc9%CaEО.dpsL*+xq +j>914"X$b&rw{Z=gE lk`lC>V9P<%*XL/#2KB/'hӘVu$ݟvNHPX5Z%t |z>78V䠰 +^'9ָd!3 Ӓp)c|oW #'o˧CA􋗑q{;pLv>H:oZf+ ?aG߼/oCHnOBBqo0@X=/}qKiIdls.'M"J"S5)4)Npl.@B? 0aWROQe\2'R~7oyʓ:{vZ~"+#4,NN_*T319'F)B4ȄQG;d;tDfIlGh?r0\A)!o\`{> cwvJz +=xD?us1 }Qf wO]CѱijnyLR+grRx>%jTX"E:shu7o{ۻGо_O B>}r AKhTlˈ &*?FeS_4?ȪM>2r;#b;g*{ɉy?uuFFcZDвMmVI5{CL $*Yb-7G]`a#|%ɿcϽ1E F-8Ƽ0L+f &_^W:Y*40 +?X8^<;INB柗m>s~!N08M J%-p% N$@ ^xW? _\6L?|v0FOگP4tJflَT#8 ~rY.HrC_T=6 pA/5V4!5Ks =nƯ=6<>>.˥~(YM;P@"`fAj˽wh2~V1$'s1TIki J(G _icH}L>Qx +N/2,=8D ^?\5t#1G[3o_91hy'"?NYlUz>r,goHLt!8,ѻ[*7RE_eW.H +%fbȟD/^X]Φ?õh#*| 31+Z Nr_JGI[ssrk:59:Y=IlL=X˿x9SY5t|1kJʙA@_v>PɀkedUd=5ĝcVpD2;5ewk'HV)/y +[Hf3'N#ѯؐA*`Wh5nWz* 'O+6>HJ'WᓮGp7|η6n|oE减 扠(uH7bKCjmg+xNMgAyԊݸ,i)wK|,TS>)-i%ls~c DJgd[3ú$ShaA4 +6 +- T}"$vu凯j [ʵ f4ЊK9M%A^dtu@AHl Cf*yehs4ڏOp-dr10o!Τ +px Tg+)5j& +0a~BLIzv{$fps/Y)IeGI?(-#eX^T!A%h &Iegvi30f>۾lwY\Es8̒{c/DH$rgPxe1ȉ==Du~j7,ΘfH~g"8 Bń8 +=jmIzG\fp)?4C'g-)rի! 臢bXGP!Ϳk!#/Un"c(=^6Z8,]@~4pGdPFKJl=|b]q73 +L2vnc݌#.[oax\>wnqTp'ꆐ&;ϲ +ź:gJͨu'jdadƄW1K|2#.*~}#ʢ,N#SKJK~lʊ +t̿( ]a' # Nŧ ++B`iȗl~ }$&?Q'.J'=$ 2 J?Ȕb oO#ԁ~{Gj͂v|Am9%]S'3 2<  )mU?$3IN {A~Pg 0^)-I+σrrr C$|6-Q 86QطUTo}kol?>;FP3ZqptMǩ&o(w׶hrNsR*C0cx??HzIxt΁&٦NaL`¢Fw gIaB `PFyXG76~K/3΄o &ҹW{?xG%/xM-yTa@j4Uq5Awvv$4 ͪxkOD/JE;gY G0H"=N2w <"kLr+ +8;O~(3 Z*.B)+x>҂.GĴҝc&OQ'֓l`/֛;~ (?|DZUq!Cw.r4 +0a^q4_|ݞcڅ eB$0qۉʱǠ*"CaGcwF(}x_@둺^foM!h0 >"ϿV_1a: /ȧ},6kxqyOA(|efZ)Kz:W$I_pYkz<\43 `>\#fckۉuI1#'z{xJmMuOOBgeg_So?쯿x;<]3r7^j# Ȃ1mѴ\ dQ<{*Qf$fBLgkHk(G,#\E0/Ym5W_0͠2I2V̋av~'|g}ּD&[& )^%}ʄ4+zrn XRfX02A ]vid1INf WriJS5=H& R@NA׎3π$XyۆbxN@6]qS(WE,鶛4A'iգI72΂d;RbJ\r`0{;@D5p>wfG&RAP)T+xYLDA ssO-\ū9Qsg`.Y&ƫx&PijQqrmu#p3=ѭ"DV?Ė\fIN"9*_B{5nE,y/T_͇?j9!h'w˧k=صL&^hYd W0(oee|=D#pEvЂ,AXC5L M/ \DG?i$X؊y0ɢ\i2D+j߉(RMhWJ^_?ޭυljljT%Iann|P~%/?mjn[€C-TϾZ cO OM3$O*PKp=>A1z1tPҫ+#( +qJ%gh b` +I|J?ڎK@\KЈPۜ;ۤs(W3#@ ~0G~32ͻxuy̅cVC~a G +`-ijt fx ʆ[14oU62RD$ +>W髰3;yw4$XV+fT5I$ԑvFL]`aQgV2~@Z̅ J`GJvy'w>ڧF?YJ PBxsx'T3ZuMdLbjpiW]n%{x'" D: @xVfV:ҋ8Y&j5ɏfD|g"57ܜOf JOd.^7`Oxz85  l!]!-uIx!76JV@Ow1M(;De3>5B$B:y% :  abc;ɐ˩ + kw8iH~$P)0ɻ;%<@0M>EW) +Q+Fv4O{) +Ln(Y^ nh zz_D'%VـI2SVbҵoH[ `L ()Y_9O$Pl:%x"j7(gXŮ(Rj*t/[)hEǘ ޞQqu> 鯾5_*FjvŭM-٣LuSuwHV],Kt`>e^z5W91 + IQHO\EN[(5VbFaOxJjvP"aQ~Nӧ:^6аca+/Jz˃ + M*nɲ7Sރ|qdX8 kCp>=|^Mq3PCpfovJӣ#aXlclgDdΣ[ed-oČt;̸4YyOȮKNtt]cu2T  O#},ҥ \rHn,A_ҋ1 d]YR )jS&Pd< CLCG,g*?hN!&N~&rH٤MKRAN>d<0QPlj&[]>u0 #[\@(oViၭxꩋu/n'oj@]v/F IR`L|D9Ub2,H)7ZOb6C fa$c߅[<-4rtǔ?ᏱE=ޏ@5ko"[D\\w:@Q'mG2OMtEnt>ѰrJU(>} U/9\.Ͽ4W*v0upkDwLa7aIÀXk%lbqeUuUu d}A4A#Ot8s4nLѐ: >_%q`&4Z,w?uy}ݧ|nI=QN'X1yR޲,#>깽 wE>B‡~}aM7/[|yn ۸Z}lXQBR?Pazcd._+=T-:jVc%A!9WvJ9^j + ~-nc$!RINJ +h:. . e*! DMW%o\okf2g 3i-9"sFi`6pyG_*Z=wܭ,q&(ӾV)ᗷ"*)'[ 4ԐXCM&Z:'q]XQ&Vp~5) e>kN?ԡ=X?37(z0Vj vCddh,"kރ.:HTӧ# pPO.%ap1e6-~W,:f3~=?]WHG@"r!1X^ L]g*Yx3Țہ|, vD|> Oj:h2QtfK/0ϟz>qjOJCY ,s4<焉`cDI%-^dC%ГV +1|IPH0(^ + bbΏ>Ә7t`I*cUxO~@h7rM!;х|f۾? l%= ?yrWx[]YV ->txǧ"!Wߋ!y(~zxOSV"ɻJPвK_ gDF|ţ rwrwb%%qe8v<-^ 3GD@L.4+PHRD~]ՉLYMV=3 й9JCßB~ן_>/QͿ/w/|>3<f1 +pԠخׅҬI@\[Gۄ4,2w\}穀'z0, B :'x2CE'#nHY +0p^LD1/|[w>D>[>wWo7?ќ@榦Ңp4`H ϽH⪷K^1Y^q_xF<%ߺ݂A0p=3<~/ĺkdbX iΧ644UW B]QeNS|-q0XXik^L s5E@B,}!G_~_Ƚ}'1&?bsԽ-~&(u62LZ}Wц_ǤF6wA%0$H_-300Q0Q.L~H;$4@~c!c)Bg?])"NcI +A (4[f74j:%D;P/%l8d 0K!ZVOLyȟ_>`ffi^'! r1XаbǓ}V= +uTfiFZpªC~~GDf0<ہ2,s~2LVT^Xo:вimw+ Z(i1Gz6?G6vTk[ 6m4;10-BKkDYgdեţ=ޏͿg:?x-_0 \أ\I@S֓oaZ IxcȆbY\_(Yk+Gs31ׇD?yunqjU|O}8}/ +a+!%V? +Bf!Wc/cKak_s '$Ȟ_Ryo- H9gxw덌~=_WW9ƼlzR&AS#)@h^1/Ǐ{u гTͪ1B~D#K`* p_Kq$9³=1a4 RL)?b?h0{U# 1Q727T8]]qqߡ=o-䠓.Ei޳؜hȼ{bRF{d'"7#ޠj Vjj%\;z / +ȁS0/ j2gq'E6E96=i1Ec;  75UarP@h_>zuxKe0H- +KD@JT8`wU(P1t{*NXU*^xqV9n ȏ$aQ0€Q1/rg:hxlZche쿞X | >><Ɠ ُx|;G<|T @?^˜XcG8wCDO~e.+RxY凅~#; fx +pT@!4bJzF) @ch~mS4m%SU>gܽ."j>ZHdegGrBeNz Ok]Z@5`4*º'^~*"ɩ)S|XT<KNtnEwz۶ -qe 5LQ?l s fڔӡ}e +Fà@JGR?ep*T@qMꨣ?NU/HT Ș!aaMz7I^Q>ÌALi03gHm$ SrȪ:ooD~wWwcO̸k]tvdzn_( ;yi?2[zևJ+Qz{Vʰ(2X +0_[c𵀈З y|Q?$7ll?ztC8[p\ ԩJ-QeXkky@L̚FP``DDtFݕ՗wO4!Lvt{4>x ÷.f(t?~zt| 7b96N0߯bE0vqclcji_c1>\P "_:\{Mɭ\8U=@J +-7b[ZRfW}|GD?̳L^T*ipiƆb$A 8>zML=O`L mBUAf0;ݿ&-Geh=ZvO^/Jvo0F6Jת}*D3X+/pw38 ;Y@sE`}> +z.Sm<P\jUB +@}jUHb8^:h*QJ\?7 4Sx zPA3[|VVP B^*TYƹ=\0{\ 5(Dfg3 +և / GvW qǯ׃f>d#4U7JCM[BV/H1$Td؇p~?4e +p|Voנ<-̘JNZ/-^Ǐd W6?:t.Fm.t̿R%P8V +oWp/GQĦ\.L@ Ƞ }02B_A|)߅#&3#$M'N!)؁)z obMoy/-9 <ӋTn۱;iWU ,xa*@ r2x(C`3)Y4@ 2hR\OX5R48ԄU{3@_ke~/P'ȞĘnD18|$UpV_д{OFtiފd04aza.O2aͿolz| FWZ[۞|A;yWQ!:;,0@>mW\̿^.H肗*A \͎ i\SvA%.0 K6 hB +b8մ걻޸p_Pw zM̞ yH\kY(epW5\2#͝C+䠀;ay#ՠso~G|όÓx_>rp5 P߽}/VsS;~*[^aADz`pa|U<Sst`h T,8) $kDҷ\/<k*_q^"dԁwH/hI@\ছnl|󍸶^&S]\O/;bfS4 .uy0{XY-8S 7H@rÂ-W ƭD0&٢<=l5to3&x7s.g)R|[5Q"$D<8Y?XVu_+lV @ $HĄ)j|̿蜣0 zݸQ_8h~?֟A;bً*ww>z@Xw&}wV  +kd`UMVZ1Wskk⛁A"Q$ɒ\@'Azc뱊/ vUy8: +{X^ZhJ2L/Pse HlO`z +oD"/Es5jZ>nDBD(`[OwmΌK.3+lC>/W: &\zX^ XPO#3 Y@ϏE њw`Eċybec3W6=5?4sz)=ݜ!,.&-6 46.W"`]/)7w rsň#,[|l* +_RD u'a}41?tZĉɓ\"zH=ÍZ~PC,,M ++9]7.XΒDX:vW_Ja6 ܲΙ}=x)?n/vԏk&N(uܹc!/4͢bϸQ(@Ѻ-cZ p)#o +Z|¾1΂cje?s]l2I3}3|i.0`&{޳9(C-0r,H)R!I 'M8Z{8rWw08Mnj%GdNieAZ +UPd?i2a@SvJEhs3k g6̀{ܳm̲ |˻6AF!"LǍhL1;Ǭ {pa¥#|14̱߹#H4׻fOw7S# N#¸_Ԇ(dz,4ql~%<l +3([ 4^8BdmBv)#g;T=dن9BSQ?f&frZM Zp_ś$`J$Ys̃yx+#l |[qzlIEtUUciGaЄP@b M@Ig!p\-2lx7".$ ź |&aUƸԫsDp^0=;M|V +5ٍ.my#?ɠB[l h`J"``z EԴuWUKO +mwmk'9_KwXd@?~ 2a xA8i6vXoYy.*T "Iy#ڏ +prcT q6 +cq;,*}QO` +BSXos*k>w֏tZ4uX +5Tudq~9EV5٦chU>{ Wz됙 kԑO,(35ʟ):7-qZ35rcgA#WH๨п؊B<*ך;92x# 5S4,)}{zHkL@ ̷n9eR5ܧij+DWl9~Z ~4nh͉ъg); ~\-.hZ,(FlA_xSf[čkXiػsgC?KC(zux?5lciM:Dž XTO4Y(ͼwPy,TxЬ)K>d0;Yܰ0Oy*R\U"pZBNi)e#QQIԚ%B1A|W;m{NpEޒK2aFH1'hX啉UB_Wy/p$=g, yxr"}9DV0hƴ4쮈/R^b&2ckBg 0)Mu`N'tkƾ28yw" l|{:ɋ9wYy9;bnZ؏u`4Ji +OjZKxU~GV[q[8MԻMMx5V7o[|N 7ɲ{*1G&{CFq1x_2$ZȌ3{dU.f_Q0 Ӥ2QyU?2)d2I#%2x[~U5 ꜑n_ |I/2R?&%N3#\߁'3XRfq +PstX$gO)Kt:O~ t$fZ4䩈P4,ѿ{_0Ѽf9l%D1M48F}i +dWvśSRŸ os= +B--G[ oT&xG@Jr',}vsWM=+7_9 ȹFjAxV6HJК2۔!t i3 +36y㾺[.7{P{񔿯-H,\cۀc|dӰЃ$BS +QĐl<`>*xh@d2Þzv8 ԀRwν〳ϧ'mؐom4~)"IF +?V$^hyc=/\rh(JT3;Ea($M<~@6^3[6|̾Ã)gO +9w t\+,ܵ;Iз% ub$&͡hqz +UӲM(xdN2!GȎZB"2!Ʉj̮O^BBo_ at=z˦EBqkoBOi+Ӻ(>-_7#Tv|X:ټyeLs/!O9&4 ¨=<ЪI11#_%"+J;eSyOKѿ稫"L<C2NqZ޵e|pN9ώbCh) `$o*-$Kpwgܝ_h0 ~,^l&sÖz;NiD'N"¦ >y9 +! c,9U~J"<5C2Bo?-df{zʝgX-2q$L^,>ANo4?k,x NGkMKПIPWGy}gW, \|]oh 6)_aԄ?q0(=,-4 +.! +] MhC.,$tcXQeE,:8XnR>F~!Y +9FjF@VFLkC?@.B<Z#AݟgDjJúi}!5<!aY; } ϩ$*T`HB iŤBEU3 \~/i6IF0~:`Um=C=~J:#&L/0@τH +6A$VbN8ѳonxO݀?.C¿zvDž/˻뀳= R:4ޗkHHJ["?:ƐQlJ ۓ@!v@V0g='ׁvܡagr{FC񥷷RH?@y}U澀 j/?X?C7_oP{*^#m ] +JF +PHvC`gK",:8EĆ2ڭuK(LbI_a}N_3t iTҔq?uiA+7rM#BgբFji[ MO8X~S}5: ڴ -wu"qaA0`h}, pof+hBEgaV{enu{+'IZ0X +Yj13׽YО}rY:ښ<ގOBK'#Гtڻ6]A8J``Tc0 @,_~5 +73i$JzGb:YԵO>^zVewv-'>kyO}vGjcrZ1ev<a1 mvCRc(v)Ѹ,u`3o+WDD۾}3d(_\Q, S(R,_ػ(+=4с@B 0 %01v`skHMlx_/Ĺ>{7zĉ7Il-B\n[#Q[}3: 1O4z_{Ck]GD d;Z#n"ITo7߲A> ]:h7u2u Z.KޚWUHW* K 7޸e۶I@vcAE?(/H Շ b-u#l>Koa{6?OqziRi#N$$)XPHpC 6gn×y gٔ8Yfa57? iʅU,]}0\2 7P1wpH40[N>w$-idK# ( @$,vDc`_uewI5׏Xk}PXj>'?k?==.baZTӎ +A~CpH! "TrI=r=OTq)>ch!a O߭ ѺJ@+ŷ+&w_*{v,'wݦ_AJKV)^{8J`a~dW`t4U skV]*~_KM&8Ms`0Xzo^-.€!tt L$''3ghzmvBMAPEFf[h4$GÂ{2t=s)p?I( +[:LjsH5 NFK32a^AyA)_ \ ?{0eT!6D]Mcur낃Q3'9o[[+5~~N[V$iH.vNee Pa[uHr:PuUON`804-TOV+P$p w߂`pş"` 24QX }BBh;pׯp.r:`yW#_~~ {á@hw(G |cN_%I_^n*ΏE FF~.ksțD@60 +ׅt/@"ʀ0G P}9tl0OmU_?f7Ӗt~ "G_)׮f5^bY( ASUg"gS,i,ǽ/՘㗾5x]{ј^V=C*r, C [lh#a |W?AtW6k :K`Q33ݦQcΕQ^=AEAlKRaI wOW|Տ 8p-m  ?|{t_D-RNHQEư s5ǃox8g2vG͛u~!b11B8a8@k?Ũ X8?'q~2S"f_wu3Ž4,\,BajQ8 eM(}N϶nשׁ%CR5c~h~]M@!#nq&FAYȊ53Z^AHzݷc\ҏZfia +f+,t(޼.p"*AָdԽgg\ϱU+g.@ ]UVK[dx[/lG [!gñ8IE5,RmH{YV>➞̴m.N]0Jl^C 0L.K¢/~s %`$CÃCmI!gM 曪j.1 +B"luMHg q2!^L{~6FJФ柛/ŷ@]>S![>%Ic}W{O; v:QO r{AL[xG߷eןCU_XJԟ$A2a2|kn0\vmy+Ud=߲^s}ۻ48ܭXiϹ2I?@HumϮdzZ< goi hfmʭ>'1E_<<ؾ17?Q]S>Ehuht"\ * GGB%I +: 7.hoV>1gz max>Rmݜ ;)* n +U5S& +kF Qa= #MS,B䅤5 ;@vިjY/".+Dh5*}%]@&_? FTiz*%jײv<6`ڣз`nƒ_܎4PSi9+ʴchxS +AHq@gylF TJvO΍$8X3IvbK݄UOĪK:G"Ry,t!իf:i뷇,xQH[j 7|U^(wڗ~7tJ$qCU@7sDEJdI︒,-gk1u1J\?l!ScGc#R},ܙĂB3XD(a6º|`F]nٶV܏5c#6|m1 +`/ȧ+ja LT}buq1 B.39Y߰$B)6!=l'38HCs'(PyWs7 u%ThqWֲ110poҒ{wCB@fqP\rQ}fP} +ΣMF> jN)#^ U>dǺF Q tuE4'yk 0KvG5 icmnQ?yIƀV3J} ,ODoahh4WWh5%v2@z$i3Q4!|艂ӡ3'p]!a@ +D(!w]+ b6Emð\H60k;<6Of : ybWCPNڂ@ +q5 G?b;>]-鐢 +:#SH!^^┢B4rh"B .H Cg!-g.cObx$.ru\Jj 3͟S9sz"mAQU0bP#5]VOgACaJ/ +<y )Z()RZӒ2*c*%3CWC!^*g:IN S}%DU@EP # .@EPOSR!?VvZ*)zӺAt( :Bƣ?ibZQ1-=lO& RN\O[gV̛:#YY-8$ ^Abb|ݷh 6g_@bTCD}4'XX1x~D@gmᕌt?b'CfIjAaJ q\_=]A~`wE @CXADV-wK) &4$d84R[im-xI5s +`*L {h="&H+Ry9,~(G^yLfe!ҕ)XzɮiWcw柛㟛G< 2VOHA`RF"ipfd,B-m>,;5׾D/YJ>n.{|w ?>: OhxdƓ:D@0vAdES(M 0&T"* &$o@Ms0A`60q;IDxbDeʮ0Mth3Ȕ( 3^z+wHH^ yOHR OMQۂ[@@ZH}º>XzPKLE:nw2guٜ5h@8 IRv 1 $?>{Jwqt\@pՔBJqmk`D 5apmn-oג{wNWb3Mz:h |^G57P#| r+D~ͮZ=\e]@PӳlHO޴"?J˽L[:@@xrΓH]C3V(^kR&RS? Iu6}YRuzAnPFz+OJ@oc ꠜnfBzdZ- RR: b?6L*ǀͻq$4\m?(Qk<RH8ɏR 8L΋qi յPXX{{_]_IENDB` +*3 +$3 +set +$48 +2e0e5a9b6e609f71e02273e5de434e14:brainbaking.com +$622 +{"author":{"name":"Webmention Rocks!","picture":"/pictures/webmention.rocks"},"name":"Receiver Test #1","content":"This test verifies that you accept a Webmention request that contains a valid source and target URL. To pass this test, your Webmention endpoint must return either HTTP 200, 201 or 202 along with the appropriate headers.\n If your endpoint retu...","published":"2021-04-25T03:49:45-07:00","url":"https://webmention.rocks/receive/1","type":"mention","source":"https://webmention.rocks/receive/1/0ae8c8642f0e3bbc75ff2b6147b3a06f","target":"https://brainbaking.com/post/2021/03/the-indieweb-mixed-bag/"} +*3 +$3 +set +$19 +zylstra.org:picture +$16040 +JFIF,,ExifII*} R(1 2(i8$CanonCanon EOS-1Ds Mark II-'-'Adobe Photoshop CS6 (Macintosh)2014:11:25 16:14:10Sonja de Ridder"'0230 + +  +124d +2014:10:24 14:55:322014:10:24 14:55:32`e@B@Bq2jLp23399282250.0 mmrz(HH Adobe_CMAdobed    +         " +? +  +  3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?LCk4A=nHnMH{x,X?xhIILK7Kl +bD"OtTo8IӲ-aҠkIk>˂fXX4w!4;AJOaIK W}Nu&{ BLܔߡ{+Hg6[c 7yW1Ë^%g:^%?Yss8h[F\pO`"6=JSGxq"yN2T)v\O`˄?#ʺe;D03G]ާߢeM>~fWg0\ (0sL%}K'1nꅄ4n@LE"2r׋ϸ@>{7" VAuڽ64J_A˺>].-V6j:eX ]9HsL~}hVSsO R@͎j;$m#<"=)9'-H> +$KJ +,C-is]@V٘t%?K70'~@!Z}msY=EL]mUU46u:"f8AMH)}Fe6;q͟[VCnnNq*9~LůCO kb߉qC+h䆍/C\(H W?d$:LQ;: + J~7@ndƪ7%bd&O߁kHdhwSkgG1ncv~z~6eghFWj`y*95u&*u֔w[1ۏ*$y(ӽۍ-3$aO l-8'cKyAn* XLIIL.d!'L'ok{ϒJYg縺܇s`iu<j^ P#BP)OLDB5)6ꂛ;vYnʀs.UҵWٹCv\hmwOW*똵Wuю%>1nS BukmuYU ;3۹]e]_\ۈAD^wFmsS*y6kcn9D[ZAE]p DZS׌ 2V<Ӓמ+,}]zٴ怜au_cn%$co?K.e~ʨȱtcn,]wȹٳ6Z{(ySF%4*"΋ՙ,ۋoCiϊx~Yqݒ,=T& 0 *n :!8QZvpa6C-Z5S2}GAh>)umK״e//n HADB<O⚕hTE~js&`hO s*Tuz/54}OhhG'%miGݝ fM-fMcdsoRȣeܜ][O=mJtUվ׏V@ЇXk LFk;,g>WHA[}mʹs6Ё*P5S'u)G;VX+h,0Ii.CyT-9bcm'SidjIB{h@k5JهV# wry\OHws2 -.3t7]>c3/v\" \òڬeOnǵWkpk 6+=@Aoqt<V2}l۰] +^~i>2$I oD.. :$q {q@(1/ 1N; +9:|xV}k1)s2ͱR_H?D,d|ܺ鱣XY:MoSm?<VV]aq&I'IR/G/VEY_]]{$t]R~XBǴx6۲և{u#Ғ;#!ޮedLlVF3ip%X_.z=p_U]im}7: \5mcEQms}2Z\oI ;Oqi ųKSIvNm/#;x]^W xzpq-h`"#:U `F+npMVVm%i=\^ӨR9F^`R%ۉ6ӺM`}*6Z?nQBVݤ;+*OΜ!\4BJ>0mT>M{`#w.cuF۝i^#y?p6 A>edDiwQdNwacIIL C<tpa%#'A+M_:%8=:.ln啐eNv=! cl82;7 h?kGcs!bďwի4d^E qZZuΔ D!yLO>l?u.'zAŌnN5_Yp8=)k;?:YY^|;j٬5Sx -n#*ɉ.mZ(b}gk'P;!OJL@ !2M= +J@lt4ZNWQĬ +"ZXLh\%o>β {}/{`wR0Nk\ƴ9eʕc9ֵCVAi5R%/qvtKkG\w1}d\V?Ŏvݻ(}Rܡ:E7DYPev0H`kw=c UYs^5y@շ< =Hk:}AmM +1`rCGхƒΛqwߗa:uLʾTY<FֺܹόirRR{-fi4Ρ'UVhd0KL*>f)k9L^HnI d蒙:p徏'#qc}v.~o|mcwSt>?XQuՎ@;g^BsdtS 6awFޒ`"9j(٥1:H?k IM΋ktK\A1z^["DϫX4fc).kZaov3 IJGܖԶXe6S 7*"CudY:KoY(_Y[NKEh (+wTu:3w` F4߿?576 $0ꬂOM8~qokniGցz3 +qfz%݅敏U iOsWG,OeǸz{Z+i;\܁|S"|˷2iЏ08Qq )*9vd \T/[20141024tSonja de RidderShttp://ns.adobe.com/xap/1.0/ C    +!'"#%%%),($+!$%$C   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$9!1AQ"a2q#bB$%4Rr"!1AQ"aq ?IQ}OƑ5 qVLV\^Fj¤\ڈk;J9ā ۀ_WFʹCvS@dB4o=HAeSiC8~y=r+1҆WX^(ȥhU iؠ%jO͚ G0|" Qm |* լ+)F +Nqh9 pFK`Tyк*hWid.{HW1&lCgaQ*7K'9wvoU$)'kp5wL-#GR3l&BɂjԁerzߧdT&'A9hI4iuC!-ob> +=޳T|wQv3O(s%:~T`|\y==^#wjPt`\ Qv4m}kvnVӖlaވO 9^nYd8h5ՍݸivX)w\;RŁDG+4hĠARQ>E%!1 +*xMW.uIzT&r=:_*^J[e$x𐑐{Pa=6Cg\|+dÒ#& jAꡩp(("AҢK+Bs[TD@u9vsMYs 2V hb5 +²v6{(V 6m@Դ yqYM4C~Vmmc7dc=is%ָoVs.N㹮]|%6%fe7N}q+lt yŪ,˵A$.=Ld]8.;I:52L"wXM+OUm' jԷ9xﴴneKK8e^l +X6zQΫ{pʶ<#xZL݋D^fm5K +:{{q]0#ᶆdʅ&&f-4bPb'\%1;Tan0x"tUM=Z=2` @{4QCBɪ\ R*_Kj&rP#;ۺ;[Mnv>չvxw +Mn+'&5\{3Rhvs1 ٻ?nͳ5{|@.V,KȒgEdkkج\dsY&]JyѰREGwkś@[#,܀Ip+N[jiju߀DcnjJ0B ]k;Tͤߦ0GpFF~ޥ:=N hJ͹S ~c.[oM- ĈU>X-nR qK?oL1'$n#޻I,ʾ{;}[pj bBEf CF\o^ME2H9l#(rvH6|`[:=]ʂ "Pj3̃Z81bSH ڈu&zHfn]V[ڲK0%Xֱy{oh;\} 6/6 ]mM`k_@Of8Eɚj́Iȣ;_>Z8Tq#ⷄntr.;y³VU/f.BI +6ތaڋRJgnyO&WwkG(vO/ӕ.!PZviXƻW5BHZPTڛ] +O[GҹӾFK`ePqiL,PX‚exy +,{v(.q9W-K7[bl9TMi|U*eA UDzcKj05&,ؒ5jYrjZni=ejӨ-e,5a2BF-tEUrq [{p?3j~!N p3[Up+^&ٖo.Y4vܶ*]{$heuS xE9 Vc![uhFPH#^|;t&LvդyZ4z3Q(iY6-|nVӮkmJ$ݵdbፚ̵v nnةb5.HmJ[?YIb>Qv]=tiofCy0$aɨ+mG1 +b!2RgK>ⳤXdsM/P=PzŞnY8'o5%1<*issި[NV03[ *7PvYPѬaGcV TtuZGS|үH]K{ejdxw ׿#Sn,=Otq~*Vi[ +Vg? -:YL*O5y-Sm5[~B||./a-aմ5HR8*G f⯖uU]g$Ԭn"%~lA-nJ*&Qu,[<ߥ~9]2Qimh0 rMX5k?GV2Di *+=HY5+Gi0[x^9$ϿvYG|qAy[\̲]"2gj_Ļ0 Au=k&p(s]o&rKptI'FvFH>;ֿqkzeȈlןmuFPn7p*laWlb +]g); >ۮlj2Pvac4+4rmSXu6y"%泗kQ1i #}(% ((H%rs惓IQ CN&IEyq+^66Ե٣K+#TgV*/TQ, ]k?VM1^Kc<}cG#׮݆8XҁM^t !1Ʊ;ǜqSC]s19i vyhSޠ_JA@&+ɠ:Gh-Ѳ + i; ,b#L ~\Ɓr6ns‘@ҍ:etƙ$#.첃ܓVegKމS"ۈPxR5]kص\p3N9O4ƽKߺĿaF6<} 7*;=QI+-1YCjXaѼǐNXTld(#;6! +&۟s@̃ԣhdX Tr(#lYiP +*3 +$3 +set +$48 +a789ec1fde13d44f0f03cdce05eaa353:brainbaking.com +$705 +{"author":{"name":"Ton Zijlstra","picture":"/pictures/zylstra.org"},"name":"Nabeschouwing: de eerste Nederlandstalige Obsidian meet-up","content":"De allereerste Nederlandstalige meet-up van Obsidian.md gebruikers was interessant en leuk! We waren met z’n vieren, Sebastiaan, Wouter, Frank en ik, en spraken bijna 2 uur met elkaar. Leuk om te vergelijken waarom en hoe we notities maken in Obsid...","published":"2021-04-25T11:24:48+02:00","url":"https://www.zylstra.org/blog/2021/04/nabeschouwing-de-eerste-nederlandstalige-obsidian-meet-up/","type":"mention","source":"https://www.zylstra.org/blog/2021/04/nabeschouwing-de-eerste-nederlandstalige-obsidian-meet-up/","target":"https://brainbaking.com"} +*3 +$3 +set +$19 +zylstra.org:picture +$16040 +JFIF,,ExifII*} R(1 2(i8$CanonCanon EOS-1Ds Mark II-'-'Adobe Photoshop CS6 (Macintosh)2014:11:25 16:14:10Sonja de Ridder"'0230 + +  +124d +2014:10:24 14:55:322014:10:24 14:55:32`e@B@Bq2jLp23399282250.0 mmrz(HH Adobe_CMAdobed    +         " +? +  +  3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?LCk4A=nHnMH{x,X?xhIILK7Kl +bD"OtTo8IӲ-aҠkIk>˂fXX4w!4;AJOaIK W}Nu&{ BLܔߡ{+Hg6[c 7yW1Ë^%g:^%?Yss8h[F\pO`"6=JSGxq"yN2T)v\O`˄?#ʺe;D03G]ާߢeM>~fWg0\ (0sL%}K'1nꅄ4n@LE"2r׋ϸ@>{7" VAuڽ64J_A˺>].-V6j:eX ]9HsL~}hVSsO R@͎j;$m#<"=)9'-H> +$KJ +,C-is]@V٘t%?K70'~@!Z}msY=EL]mUU46u:"f8AMH)}Fe6;q͟[VCnnNq*9~LůCO kb߉qC+h䆍/C\(H W?d$:LQ;: + J~7@ndƪ7%bd&O߁kHdhwSkgG1ncv~z~6eghFWj`y*95u&*u֔w[1ۏ*$y(ӽۍ-3$aO l-8'cKyAn* XLIIL.d!'L'ok{ϒJYg縺܇s`iu<j^ P#BP)OLDB5)6ꂛ;vYnʀs.UҵWٹCv\hmwOW*똵Wuю%>1nS BukmuYU ;3۹]e]_\ۈAD^wFmsS*y6kcn9D[ZAE]p DZS׌ 2V<Ӓמ+,}]zٴ怜au_cn%$co?K.e~ʨȱtcn,]wȹٳ6Z{(ySF%4*"΋ՙ,ۋoCiϊx~Yqݒ,=T& 0 *n :!8QZvpa6C-Z5S2}GAh>)umK״e//n HADB<O⚕hTE~js&`hO s*Tuz/54}OhhG'%miGݝ fM-fMcdsoRȣeܜ][O=mJtUվ׏V@ЇXk LFk;,g>WHA[}mʹs6Ё*P5S'u)G;VX+h,0Ii.CyT-9bcm'SidjIB{h@k5JهV# wry\OHws2 -.3t7]>c3/v\" \òڬeOnǵWkpk 6+=@Aoqt<V2}l۰] +^~i>2$I oD.. :$q {q@(1/ 1N; +9:|xV}k1)s2ͱR_H?D,d|ܺ鱣XY:MoSm?<VV]aq&I'IR/G/VEY_]]{$t]R~XBǴx6۲և{u#Ғ;#!ޮedLlVF3ip%X_.z=p_U]im}7: \5mcEQms}2Z\oI ;Oqi ųKSIvNm/#;x]^W xzpq-h`"#:U `F+npMVVm%i=\^ӨR9F^`R%ۉ6ӺM`}*6Z?nQBVݤ;+*OΜ!\4BJ>0mT>M{`#w.cuF۝i^#y?p6 A>edDiwQdNwacIIL C<tpa%#'A+M_:%8=:.ln啐eNv=! cl82;7 h?kGcs!bďwի4d^E qZZuΔ D!yLO>l?u.'zAŌnN5_Yp8=)k;?:YY^|;j٬5Sx -n#*ɉ.mZ(b}gk'P;!OJL@ !2M= +J@lt4ZNWQĬ +"ZXLh\%o>β {}/{`wR0Nk\ƴ9eʕc9ֵCVAi5R%/qvtKkG\w1}d\V?Ŏvݻ(}Rܡ:E7DYPev0H`kw=c UYs^5y@շ< =Hk:}AmM +1`rCGхƒΛqwߗa:uLʾTY<FֺܹόirRR{-fi4Ρ'UVhd0KL*>f)k9L^HnI d蒙:p徏'#qc}v.~o|mcwSt>?XQuՎ@;g^BsdtS 6awFޒ`"9j(٥1:H?k IM΋ktK\A1z^["DϫX4fc).kZaov3 IJGܖԶXe6S 7*"CudY:KoY(_Y[NKEh (+wTu:3w` F4߿?576 $0ꬂOM8~qokniGցz3 +qfz%݅敏U iOsWG,OeǸz{Z+i;\܁|S"|˷2iЏ08Qq )*9vd \T/[20141024tSonja de RidderShttp://ns.adobe.com/xap/1.0/ C    +!'"#%%%),($+!$%$C   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$9!1AQ"a2q#bB$%4Rr"!1AQ"aq ?IQ}OƑ5 qVLV\^Fj¤\ڈk;J9ā ۀ_WFʹCvS@dB4o=HAeSiC8~y=r+1҆WX^(ȥhU iؠ%jO͚ G0|" Qm |* լ+)F +Nqh9 pFK`Tyк*hWid.{HW1&lCgaQ*7K'9wvoU$)'kp5wL-#GR3l&BɂjԁerzߧdT&'A9hI4iuC!-ob> +=޳T|wQv3O(s%:~T`|\y==^#wjPt`\ Qv4m}kvnVӖlaވO 9^nYd8h5ՍݸivX)w\;RŁDG+4hĠARQ>E%!1 +*xMW.uIzT&r=:_*^J[e$x𐑐{Pa=6Cg\|+dÒ#& jAꡩp(("AҢK+Bs[TD@u9vsMYs 2V hb5 +²v6{(V 6m@Դ yqYM4C~Vmmc7dc=is%ָoVs.N㹮]|%6%fe7N}q+lt yŪ,˵A$.=Ld]8.;I:52L"wXM+OUm' jԷ9xﴴneKK8e^l +X6zQΫ{pʶ<#xZL݋D^fm5K +:{{q]0#ᶆdʅ&&f-4bPb'\%1;Tan0x"tUM=Z=2` @{4QCBɪ\ R*_Kj&rP#;ۺ;[Mnv>չvxw +Mn+'&5\{3Rhvs1 ٻ?nͳ5{|@.V,KȒgEdkkج\dsY&]JyѰREGwkś@[#,܀Ip+N[jiju߀DcnjJ0B ]k;Tͤߦ0GpFF~ޥ:=N hJ͹S ~c.[oM- ĈU>X-nR qK?oL1'$n#޻I,ʾ{;}[pj bBEf CF\o^ME2H9l#(rvH6|`[:=]ʂ "Pj3̃Z81bSH ڈu&zHfn]V[ڲK0%Xֱy{oh;\} 6/6 ]mM`k_@Of8Eɚj́Iȣ;_>Z8Tq#ⷄntr.;y³VU/f.BI +6ތaڋRJgnyO&WwkG(vO/ӕ.!PZviXƻW5BHZPTڛ] +O[GҹӾFK`ePqiL,PX‚exy +,{v(.q9W-K7[bl9TMi|U*eA UDzcKj05&,ؒ5jYrjZni=ejӨ-e,5a2BF-tEUrq [{p?3j~!N p3[Up+^&ٖo.Y4vܶ*]{$heuS xE9 Vc![uhFPH#^|;t&LvդyZ4z3Q(iY6-|nVӮkmJ$ݵdbፚ̵v nnةb5.HmJ[?YIb>Qv]=tiofCy0$aɨ+mG1 +b!2RgK>ⳤXdsM/P=PzŞnY8'o5%1<*issި[NV03[ *7PvYPѬaGcV TtuZGS|үH]K{ejdxw ׿#Sn,=Otq~*Vi[ +Vg? -:YL*O5y-Sm5[~B||./a-aմ5HR8*G f⯖uU]g$Ԭn"%~lA-nJ*&Qu,[<ߥ~9]2Qimh0 rMX5k?GV2Di *+=HY5+Gi0[x^9$ϿvYG|qAy[\̲]"2gj_Ļ0 Au=k&p(s]o&rKptI'FvFH>;ֿqkzeȈlןmuFPn7p*laWlb +]g); >ۮlj2Pvac4+4rmSXu6y"%泗kQ1i #}(% ((H%rs惓IQ CN&IEyq+^66Ե٣K+#TgV*/TQ, ]k?VM1^Kc<}cG#׮݆8XҁM^t !1Ʊ;ǜqSC]s19i vyhSޠ_JA@&+ɠ:Gh-Ѳ + i; ,b#L ~\Ɓr6ns‘@ҍ:etƙ$#.첃ܓVegKމS"ۈPxR5]kص\p3N9O4ƽKߺĿaF6<} 7*;=QI+-1YCjXaѼǐNXTld(#;6! +&۟s@̃ԣhdX Tr(#lYiP +*3 +$3 +set +$48 +31d75d84838a97f1c4de550ba91b6fff:brainbaking.com +$589 +{"author":{"name":"Ton Zijlstra","picture":"/pictures/zylstra.org"},"name":"","content":"Don’t worry, I mostly blog in English, sometimes in Dutch and seldomly in German. My notes reflect much the same thing, they’re a mix of those languages, plus source material in a few languages more. How to deal with multilingual blogging has bee...","published":"2021-04-25T20:31:11+02:00","url":"https://www.zylstra.org/blog/2021/04/16112/","type":"mention","source":"https://www.zylstra.org/blog/2021/04/16112/","target":"https://brainbaking.com/post/2021/04/the-first-dutch-obsidian-meetup/"} +*3 +$3 +set +$21 +brainbaking.com:since +$24 +2021-04-26T08:47:41.873Z +*3 +$3 +set +$21 +brainbaking.com:since +$24 +2021-04-26T08:52:19.857Z