From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id E5B2D1F9F3 for ; Sat, 24 Apr 2021 09:28:46 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 3/7] URIimap: support ->uidvalidity and ->iuid Date: Sat, 24 Apr 2021 09:28:42 +0000 Message-Id: <20210424092846.726-4-e@80x24.org> In-Reply-To: <20210424092846.726-1-e@80x24.org> References: <20210424092846.726-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: These will be useful for keyword synchronization, and perhaps importing a single IMAP message with ->iuid. --- lib/PublicInbox/URIimap.pm | 38 ++++++++++++++++++++++++++++++++++---- t/uri_imap.t | 32 +++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/lib/PublicInbox/URIimap.pm b/lib/PublicInbox/URIimap.pm index db84ee5e..dc193468 100644 --- a/lib/PublicInbox/URIimap.pm +++ b/lib/PublicInbox/URIimap.pm @@ -5,8 +5,9 @@ # This depends only on the documented public API of the `URI' dist, # not on internal `_'-prefixed subclasses such as `URI::_server' # -# exists, but it's not in -# common distros. +# exists, but it appears +# unmaintained, isn't in common distros, nor does it support +# ';FOO=BAR' parameters such as UIDVALIDITY # # RFC 2192 also describes ";TYPE=" package PublicInbox::URIimap; @@ -56,7 +57,7 @@ sub path { my ($self) = @_; my (undef, undef, $path) = uri_split($$self); $path =~ s!\A/+!!; - $path =~ s/;.*\z//; # ;UIDVALIDITY=nz-number + $path =~ s![/;].*\z!!; # [;UIDVALIDITY=nz-number]/;UID=nz-number $path eq '' ? undef : $path; } @@ -66,7 +67,36 @@ sub mailbox { defined($path) ? uri_unescape($path) : undef; } -# TODO: UIDVALIDITY, search, and other params +sub uidvalidity { # read/write + my ($self, $val) = @_; + my ($scheme, $auth, $path, $query, $frag) = uri_split($$self); + if (defined $val) { + if ($path =~ s!;UIDVALIDITY=[^;/]*\b!;UIDVALIDITY=$val!i or + $path =~ s!/;!;UIDVALIDITY=$val/;!i) { + # s// already changed it + } else { # both s// failed, so just append + $path .= ";UIDVALIDITY=$val"; + } + $$self = uri_join($scheme, $auth, $path, $query, $frag); + } + $path =~ s!\A/+!!; + $path =~ m!\A[^;/]+;UIDVALIDITY=([1-9][0-9]*)\b!i ? ($1 + 0) : undef; +} + +sub iuid { + my ($self, $val) = @_; + my ($scheme, $auth, $path, $query, $frag) = uri_split($$self); + if (defined $val) { + if ($path =~ s!/;UID=[^;/]*\b!/;UID=$val!i) { + # s// already changed it + } else { # both s// failed, so just append + $path .= ";UID=$val"; + } + $$self = uri_join($scheme, $auth, $path, $query); + } + $path =~ m!\A/[^/;]+(?:;UIDVALIDITY=[^;/]+)?/;UID=([1-9][0-9]*)\b!i ? + ($1 + 0) : undef; +} sub port { my ($self) = @_; diff --git a/t/uri_imap.t b/t/uri_imap.t index f7c78665..e2aadf84 100644 --- a/t/uri_imap.t +++ b/t/uri_imap.t @@ -54,6 +54,7 @@ is(PublicInbox::URIimap->new('imaps://0:993/')->canonical->as_string, $uri = PublicInbox::URIimap->new('imap://NSA:Hunter2@0/INBOX'); is($uri->user, 'NSA'); is($uri->password, 'Hunter2'); +is($uri->uidvalidity, undef, 'no UIDVALIDITY'); $uri = PublicInbox::URIimap->new('imap://0/%'); is($uri->mailbox, '%', "RFC 2192 '%' supported"); @@ -61,6 +62,35 @@ $uri = PublicInbox::URIimap->new('imap://0/%25'); $uri = PublicInbox::URIimap->new('imap://0/*'); is($uri->mailbox, '*', "RFC 2192 '*' supported"); -# TODO: support UIDVALIDITY and other params +$uri = PublicInbox::URIimap->new('imap://0/mmm;UIDVALIDITY=1'); +is($uri->mailbox, 'mmm', 'mailbox works with UIDVALIDITY'); +is($uri->uidvalidity, 1, 'single-digit UIDVALIDITY'); +$uri = PublicInbox::URIimap->new('imap://0/mmm;UIDVALIDITY=21'); +is($uri->uidvalidity, 21, 'multi-digit UIDVALIDITY'); +$uri = PublicInbox::URIimap->new('imap://0/mmm;UIDVALIDITY=bogus'); +is($uri->uidvalidity, undef, 'bogus UIDVALIDITY'); +is($uri->uidvalidity(2), 2, 'iuid set'); +is($$uri, 'imap://0/mmm;UIDVALIDITY=2', 'bogus uidvalidity replaced'); +is($uri->uidvalidity(13), 13, 'iuid set'); +is($$uri, 'imap://0/mmm;UIDVALIDITY=13', 'valid uidvalidity replaced'); + +$uri = PublicInbox::URIimap->new('imap://0/mmm'); +is($uri->uidvalidity(2), 2, 'iuid set'); +is($$uri, 'imap://0/mmm;UIDVALIDITY=2', 'uidvalidity appended'); +is($uri->iuid, undef, 'no iuid'); + +$uri = PublicInbox::URIimap->new('imap://0/mmm/;uid=8'); +is($uri->mailbox, 'mmm', 'mailbox works with iuid'); +is($uri->iuid, 8, 'iuid extracted'); +is($uri->iuid(9), 9, 'iuid set'); +is($$uri, 'imap://0/mmm/;UID=9', 'correct iuid when stringified'); +is($uri->uidvalidity(1), 1, 'set uidvalidity with iuid'); +is($$uri, 'imap://0/mmm;UIDVALIDITY=1/;UID=9', + 'uidvalidity added with iuid'); +is($uri->uidvalidity(4), 4, 'set uidvalidity with iuid'); +is($$uri, 'imap://0/mmm;UIDVALIDITY=4/;UID=9', + 'uidvalidity replaced with iuid'); +is($uri->iuid(3), 3, 'iuid set with uidvalidity'); +is($$uri, 'imap://0/mmm;UIDVALIDITY=4/;UID=3', 'iuid replaced properly'); done_testing;