zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: Modifiers that implement realpath-like feature
@ 2009-03-12 22:42 Michael Hwang
  2009-03-14 18:14 ` Peter Stephenson
  0 siblings, 1 reply; 5+ messages in thread
From: Michael Hwang @ 2009-03-12 22:42 UTC (permalink / raw)
  To: zsh-workers


Hey zshers,

I'm particularly proud of this patch, as it's my first time contributing to an open source project. (I'm sure the novelty will wear off in a while.) It implements two history-style realpath-like modifiers for getting the absolute path of a file. I chose the letter 'a' for 'absolute' (r was already taken). Both 'a' and 'A' have different meanings. The uppercase A will resolve symbolic links.

There are a couple of caveats. Firstly, blank variables don't expand to anything. Secondly, the modifier does NOT care if the file exists. So:

% FILE='dne.txt'  # dne.txt does not exist.
%print ${FILE:a}
/home/joe/dne.txt

That example used the lower case 'a', which only resolves './' and '../'. However, with the upper case 'A' modifier, any of the previous will do :a and symlink resolution. Again, it doesn't matter if the file doesn't exist.

% ln -s /media/cdrom0 a_link
% FILE='./a_link/dne.txt'
% print ${FILE:A}
/media/cdrom0/dne.txt

Third, trying to climb above root is allowed, but ignored. Consider:

% FILE='/../../../dne.txt'
% print ${FILE:a}
/dne.txt

The only time there will ever be '..'s in the expansion is if RFS_SUPERROOT is enabled. I've never heard of it, but since fixdir() in builtin.c (upon which my functions are based) has it, I added it in.

That's the new modifiers in a nutshell. The diff is pasted below. I'm curious about the difference between bicat() and dyncat(), tricat() and zhtricat(). I wasn't sure if one was more appropriate to use than the other, or if it didn't matter. In any case, enjoy!

Michael "Nomexous" Hwang
-----------------

diff --git a/Src/hist.c b/Src/hist.c                                                                                                                                                                      
index 38ceac3..0dd8c21 100644                                                                                                                                                                             
--- a/Src/hist.c                                                                                                                                                                                          
+++ b/Src/hist.c                                                                                                                                                                                          
@@ -623,6 +623,21 @@ histsubchar(int c)                                                                                                                                                                   
            case 'p':                                                                                                                                                                                     
                histdone = HISTFLAG_DONE | HISTFLAG_NOEXEC;                                                                                                                                               
                break;                                                                                                                                                                                    
+           case 'a':                                                                                                                                                                                     
+               if (!chabspath(&sline)) {                                                                                                                                                                 
+                   herrflush();                                                                                                                                                                          
+                   zerr("modifier failed: a");                                                                                                                                                           
+                   return -1;                                                                                                                                                                            
+               }                                                                                                                                                                                         
+               break;                                                                                                                                                                                    
+                                                                                                                                                                                                         
+           case 'A':                                                                                                                                                                                     
+               if (!chrealpath(&sline)) {                                                                                                                                                                
+                   herrflush();                                                                                                                                                                          
+                   zerr("modifier failed: A");                                                                                                                                                           
+                   return -1;                                                                                                                                                                            
+               }                                                                                                                                                                                         
+               break;                                                                                                                                                                                    
            case 'h':                                                                                                                                                                                     
                if (!remtpath(&sline)) {                                                                                                                                                                  
                    herrflush();                                                                                                                                                                          
@@ -1484,6 +1499,119 @@ hcomsearch(char *str)                                                                                                                                                             
                                                                                                                                                                                                          
 /**/                                                                                                                                                                                                     
 int                                                                                                                                                                                                      
+chabspath(char **junkptr)                                                                                                                                                                                
+{                                                                                                                                                                                                        
+    if (!**junkptr)                                                                                                                                                                                      
+       return 1;                                                                                                                                                                                         
+                                                                                                                                                                                                         
+    if (**junkptr != '/') {                                                                                                                                                                              
+       *junkptr = zhtricat(zgetcwd(), "/", *junkptr);                                                                                                                                                    
+    }                                                                                                                                                                                                    
+                                                                                                                                                                                                         
+    char *current = *junkptr;                                                                                                                                                                            
+    char *dest = *junkptr;                                                                                                                                                                               
+                                                                                                                                                                                                         
+#ifdef HAVE_SUPERROOT                                                                                                                                                                                    
+    while (*current == '/' && current[1] == '.' && current[2] == '.' && (!current[3] || current[3] == '/')) {                                                                                            
+       *dest++ = '/';                                                                                                                                                                                    
+       *dest++ = '.';                                                                                                                                                                                    
+       *dest++ = '.';                                                                                                                                                                                    
+       current += 3;                                                                                                                                                                                     
+    }                                                                                                                                                                                                    
+#endif                                                                                                                                                                                                   
+                                                                                                                                                                                                         
+    for (;;) {                                                                                                                                                                                           
+       if (*current == '/') {                                                                                                                                                                            
+#ifdef __CYGWIN__                                                                                                                                                                                        
+           if (current == *junkptr && current[1] == '/')                                                                                                                                                 
+               *dest++ = *current++;                                                                                                                                                                     
+#endif                                                                                                                                                                                                   
+           *dest++ = *current++;                                                                                                                                                                         
+           while (*current == '/')                                                                                                                                                                       
+               current++;                                                                                                                                                                                
+       } else if (!*current) {                                                                                                                                                                           
+           while (dest > *junkptr + 1 && dest[-1] == '/')                                                                                                                                                
+               dest--;                                                                                                                                                                                   
+           *dest = '\0';                                                                                                                                                                                 
+           break;                                                                                                                                                                                        
+       } else if (current[0] == '.' && current[1] == '.' && (!current[2] || current[2] == '/')) {                                                                                                        
+               if (current == *junkptr || dest == *junkptr) {                                                                                                                                            
+                   *dest++ = '.';                                                                                                                                                                        
+                   *dest++ = '.';                                                                                                                                                                        
+                   current += 2;                                                                                                                                                                         
+               } else if (dest > *junkptr + 2 && !strncmp(dest - 3, "../", 3)) {                                                                                                                         
+                   *dest++ = '.';                                                                                                                                                                        
+                   *dest++ = '.';                                                                                                                                                                        
+                   current += 2;                                                                                                                                                                         
+               } else if (dest > *junkptr + 1) {                                                                                                                                                         
+                   *dest = '\0';                                                                                                                                                                         
+                   for (dest--; dest > *junkptr + 1 && dest[-1] != '/'; dest--);                                                                                                                         
+                   if (dest[-1] != '/')                                                                                                                                                                  
+                       dest--;                                                                                                                                                                           
+                   current += 2;                                                                                                                                                                         
+               } else if (dest == *junkptr + 1) { /* This might break with Cygwin's leading double slashes? */                                                                                           
+                   current += 2;                                                                                                                                                                         
+               } else {                                                                                                                                                                                  
+                   return 0;                                                                                                                                                                             
+               }                                                                                                                                                                                         
+       } else if (current[0] == '.' && (current[1] == '/' || !current[1])) {                                                                                                                             
+            while (*++current == '/');                                                                                                                                                                   
+       } else {                                                                                                                                                                                          
+           while (*current != '/' && *current != '\0')                                                                                                                                                   
+               if ((*dest++ = *current++) == Meta)                                                                                                                                                       
+                   dest[-1] = *current++ ^ 32;                                                                                                                                                           
+       }                                                                                                                                                                                                 
+    }                                                                                                                                                                                                    
+    return 1;                                                                                                                                                                                            
+}                                                                                                                                                                                                        
+                                                                                                                                                                                                         
+/**/                                                                                                                                                                                                     
+int                                                                                                                                                                                                      
+chrealpath(char **junkptr)                                                                                                                                                                               
+{                                                                                                                                                                                                        
+    if (!**junkptr)                                                                                                                                                                                      
+       return 1;                                                                                                                                                                                         
+                                                                                                                                                                                                         
+    /* Notice that this means ..'s are applied before symlinks are resolved! */                                                                                                                          
+    if (!chabspath(junkptr))                                                                                                                                                                             
+       return 0;                                                                                                                                                                                         
+                                                                                                                                                                                                         
+    /* Notice that this means you cannot pass relative paths into this function! */                                                                                                                      
+    if (**junkptr != '/')                                                                                                                                                                                
+       return 0;                                                                                                                                                                                         
+                                                                                                                                                                                                         
+    char *lastpos = strend(*junkptr);                                                                                                                                                                    
+    char *nonreal = lastpos + 1;                                                                                                                                                                         
+    char real[PATH_MAX];                                                                                                                                                                                 
+                                                                                                                                                                                                         
+    while (!realpath(*junkptr, real)) {                                                                                                                                                                  
+       if (errno == EINVAL || errno == ELOOP || errno == ENAMETOOLONG || errno == ENOMEM)                                                                                                                
+           return 0;                                                                                                                                                                                     
+                                                                                                                                                                                                         
+       if (nonreal == *junkptr) {                                                                                                                                                                        
+           *real = '\0';                                                                                                                                                                                 
+           break;                                                                                                                                                                                        
+       }                                                                                                                                                                                                 
+                                                                                                                                                                                                         
+       while (*nonreal != '/' && nonreal >= *junkptr)                                                                                                                                                    
+           nonreal--;                                                                                                                                                                                    
+       *nonreal = '\0';                                                                                                                                                                                  
+    }                                                                                                                                                                                                    
+                                                                                                                                                                                                         
+    char *str = nonreal;                                                                                                                                                                                 
+    while (str <= lastpos) {                                                                                                                                                                             
+       if (*str == '\0')                                                                                                                                                                                 
+           *str = '/';                                                                                                                                                                                   
+       str++;                                                                                                                                                                                            
+    }                                                                                                                                                                                                    
+                                                                                                                                                                                                         
+    *junkptr = bicat(real, nonreal);                                                                                                                                                                     
+                                                                                                                                                                                                         
+    return 1;
+}
+
+/**/
+int
 remtpath(char **junkptr)
 {
     char *str = strend(*junkptr);
diff --git a/Src/subst.c b/Src/subst.c
index 9e3f06f..5033dd4 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3199,6 +3199,8 @@ modify(char **str, char **ptr)

        for (; !c && **ptr;) {
            switch (**ptr) {
+            case 'a':
+            case 'A':
            case 'h':
            case 'r':
            case 'e':
@@ -3337,6 +3339,12 @@ modify(char **str, char **ptr)
                        copy = dupstring(tt);
                    *e = tc;
                    switch (c) {
+                    case 'a':
+                       chabspath(&copy);
+                       break;
+                   case 'A':
+                       chrealpath(&copy);
+                       break;
                    case 'h':
                        remtpath(&copy);
                        break;
@@ -3396,6 +3404,12 @@ modify(char **str, char **ptr)

            } else {
                switch (c) {
+               case 'a':
+                   chabspath(str);
+                   break;
+               case 'A':
+                   chrealpath(str);
+                   break;
                case 'h':
                    remtpath(str);
                    break;



      


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Modifiers that implement realpath-like feature
  2009-03-12 22:42 PATCH: Modifiers that implement realpath-like feature Michael Hwang
@ 2009-03-14 18:14 ` Peter Stephenson
  2009-03-14 21:27   ` Michael Hwang
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Stephenson @ 2009-03-14 18:14 UTC (permalink / raw)
  To: Michael Hwang; +Cc: zsh-workers

On Thu, 12 Mar 2009 15:42:25 -0700 (PDT)
Michael Hwang <nomex45@yahoo.com> wrote:
> I'm particularly proud of this patch, as it's my first time
> contributing to an open source project. (I'm sure the novelty will wear
> off in a while.) It implements two history-style realpath-like modifiers
> for getting the absolute path of a file. I chose the letter 'a' for
> 'absolute' (r was already taken). Both 'a' and 'A' have different
> meanings. The uppercase A will resolve symbolic links. 

This looks useful but your mailer's screwed it up.  Could you send it as
an attachment?

Thanks

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Modifiers that implement realpath-like feature
  2009-03-14 18:14 ` Peter Stephenson
@ 2009-03-14 21:27   ` Michael Hwang
  2009-03-15  1:05     ` Peter Stephenson
  0 siblings, 1 reply; 5+ messages in thread
From: Michael Hwang @ 2009-03-14 21:27 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 980 bytes --]

Sorry, here.



----- Original Message ----
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: Michael Hwang <nomex45@yahoo.com>
Cc: zsh-workers@sunsite.dk
Sent: Saturday, March 14, 2009 2:14:58 PM
Subject: Re: PATCH: Modifiers that implement realpath-like feature

On Thu, 12 Mar 2009 15:42:25 -0700 (PDT)
Michael Hwang <nomex45@yahoo.com> wrote:
> I'm particularly proud of this patch, as it's my first time
> contributing to an open source project. (I'm sure the novelty will wear
> off in a while.) It implements two history-style realpath-like modifiers
> for getting the absolute path of a file. I chose the letter 'a' for
> 'absolute' (r was already taken). Both 'a' and 'A' have different
> meanings. The uppercase A will resolve symbolic links. 

This looks useful but your mailer's screwed it up.  Could you send it as
an attachment?

Thanks

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



      

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: a_modifiers.patch --]
[-- Type: text/x-diff; name="a_modifiers.patch", Size: 4135 bytes --]

diff --git a/Src/hist.c b/Src/hist.c
index 38ceac3..0dd8c21 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -623,6 +623,21 @@ histsubchar(int c)
 	    case 'p':
 		histdone = HISTFLAG_DONE | HISTFLAG_NOEXEC;
 		break;
+	    case 'a':
+		if (!chabspath(&sline)) {
+		    herrflush();
+		    zerr("modifier failed: a");
+		    return -1;
+		}
+		break;
+
+	    case 'A':
+		if (!chrealpath(&sline)) {
+		    herrflush();
+		    zerr("modifier failed: A");
+		    return -1;
+		}
+		break;
 	    case 'h':
 		if (!remtpath(&sline)) {
 		    herrflush();
@@ -1484,6 +1499,119 @@ hcomsearch(char *str)
 
 /**/
 int
+chabspath(char **junkptr)
+{
+    if (!**junkptr)
+	return 1;
+
+    if (**junkptr != '/') {
+	*junkptr = zhtricat(zgetcwd(), "/", *junkptr);
+    }
+
+    char *current = *junkptr;
+    char *dest = *junkptr;
+
+#ifdef HAVE_SUPERROOT
+    while (*current == '/' && current[1] == '.' && current[2] == '.' && (!current[3] || current[3] == '/')) {
+	*dest++ = '/';
+	*dest++ = '.';
+	*dest++ = '.';
+	current += 3;
+    }
+#endif
+	
+    for (;;) {
+	if (*current == '/') {
+#ifdef __CYGWIN__
+	    if (current == *junkptr && current[1] == '/')
+		*dest++ = *current++;
+#endif
+	    *dest++ = *current++;
+	    while (*current == '/')
+		current++;
+	} else if (!*current) {
+	    while (dest > *junkptr + 1 && dest[-1] == '/')
+		dest--;
+	    *dest = '\0';
+	    break;
+	} else if (current[0] == '.' && current[1] == '.' && (!current[2] || current[2] == '/')) {
+		if (current == *junkptr || dest == *junkptr) {
+		    *dest++ = '.';
+		    *dest++ = '.';
+		    current += 2;
+		} else if (dest > *junkptr + 2 && !strncmp(dest - 3, "../", 3)) {
+		    *dest++ = '.';
+		    *dest++ = '.';
+		    current += 2;
+		} else if (dest > *junkptr + 1) {
+		    *dest = '\0';
+		    for (dest--; dest > *junkptr + 1 && dest[-1] != '/'; dest--);
+		    if (dest[-1] != '/')
+			dest--;
+		    current += 2;
+		} else if (dest == *junkptr + 1) { /* This might break with Cygwin's leading double slashes? */
+		    current += 2;
+		} else {
+		    return 0;
+		}
+	} else if (current[0] == '.' && (current[1] == '/' || !current[1])) {
+	     while (*++current == '/');
+	} else {
+	    while (*current != '/' && *current != '\0')
+		if ((*dest++ = *current++) == Meta)
+		    dest[-1] = *current++ ^ 32;
+	}
+    }
+    return 1;
+}
+
+/**/
+int
+chrealpath(char **junkptr)
+{
+    if (!**junkptr)
+	return 1;
+
+    /* Notice that this means ..'s are applied before symlinks are resolved! */
+    if (!chabspath(junkptr))
+	return 0;
+
+    /* Notice that this means you cannot pass relative paths into this function! */
+    if (**junkptr != '/')
+	return 0;
+
+    char *lastpos = strend(*junkptr);
+    char *nonreal = lastpos + 1;
+    char real[PATH_MAX];
+
+    while (!realpath(*junkptr, real)) {
+	if (errno == EINVAL || errno == ELOOP || errno == ENAMETOOLONG || errno == ENOMEM)
+	    return 0;
+
+	if (nonreal == *junkptr) {
+	    *real = '\0';
+	    break;
+	}
+
+	while (*nonreal != '/' && nonreal >= *junkptr)
+	    nonreal--;
+	*nonreal = '\0';
+    }
+
+    char *str = nonreal;
+    while (str <= lastpos) {
+	if (*str == '\0')
+	    *str = '/';
+	str++;
+    }
+
+    *junkptr = bicat(real, nonreal);
+
+    return 1;
+}
+
+/**/
+int
 remtpath(char **junkptr)
 {
     char *str = strend(*junkptr);
diff --git a/Src/subst.c b/Src/subst.c
index 9e3f06f..5033dd4 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3199,6 +3199,8 @@ modify(char **str, char **ptr)
 
 	for (; !c && **ptr;) {
 	    switch (**ptr) {
+            case 'a':
+            case 'A':
 	    case 'h':
 	    case 'r':
 	    case 'e':
@@ -3337,6 +3339,12 @@ modify(char **str, char **ptr)
 			copy = dupstring(tt);
 		    *e = tc;
 		    switch (c) {
+                    case 'a':
+			chabspath(&copy);
+			break;
+		    case 'A':
+			chrealpath(&copy);
+			break;
 		    case 'h':
 			remtpath(&copy);
 			break;
@@ -3396,6 +3404,12 @@ modify(char **str, char **ptr)
 
 	    } else {
 		switch (c) {
+		case 'a':
+		    chabspath(str);
+		    break;
+		case 'A':
+		    chrealpath(str);
+		    break;
 		case 'h':
 		    remtpath(str);
 		    break;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Modifiers that implement realpath-like feature
  2009-03-14 21:27   ` Michael Hwang
@ 2009-03-15  1:05     ` Peter Stephenson
  2009-03-15  1:20       ` Peter Stephenson
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Stephenson @ 2009-03-15  1:05 UTC (permalink / raw)
  To: Michael Hwang; +Cc: zsh-workers

On Sat, 14 Mar 2009 14:27:09 -0700 (PDT)
Michael Hwang <nomex45@yahoo.com> wrote:
> Sorry, here.

Thanks, that seems to work well.  I'll commit it with the following
documentation.  (Larger than necessary since I've taken the opportunity
to reorder modifiers to alphabetical order since no other is particular
obvious---with the exception that `&' follows `s' since ASCII order for
that isn't particularly obvious either.)

Index: Doc/Zsh/expn.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v
retrieving revision 1.102
diff -u -r1.102 expn.yo
--- Doc/Zsh/expn.yo	6 Feb 2009 09:59:38 -0000	1.102
+++ Doc/Zsh/expn.yo	15 Mar 2009 01:03:57 -0000
@@ -216,20 +216,24 @@
 noted.
 
 startitem()
-item(tt(h))(
-Remove a trailing pathname component, leaving the head.  This works
-like `tt(dirname)'.
+item(tt(a))(
+Turn a file name into an absolute path:  prepends the current directory,
+if necessary, and resolves any use of `tt(..)' and `tt(.)' in the path.
 )
-item(tt(r))(
-Remove a filename extension of the form `tt(.)var(xxx)', leaving
-the root name.
+item(tt(A))(
+As `tt(a)', but also resolve use of symbolic links where possible.
+Note that resolution of `tt(..)' occurs em(before) resolution of symbolic
+links.
 )
 item(tt(e))(
 Remove all but the extension.
 )
-item(tt(t))(
-Remove all leading pathname components, leaving the tail.  This works
-like `tt(basename)'.
+item(tt(h))(
+Remove a trailing pathname component, leaving the head.  This works
+like `tt(dirname)'.
+)
+item(tt(l))(
+Convert the words to all lowercase.
 )
 item(tt(p))(
 Print the new command but do not execute it.  Only works with history
@@ -244,15 +248,9 @@
 item(tt(Q))(
 Remove one level of quotes from the substituted words.
 )
-item(tt(x))(
-Like tt(q), but break into words at whitespace.  Does not work with
-parameter expansion.
-)
-item(tt(l))(
-Convert the words to all lowercase.
-)
-item(tt(u))(
-Convert the words to all uppercase.
+item(tt(r))(
+Remove a filename extension of the form `tt(.)var(xxx)', leaving
+the root name.
 )
 item(tt(s/)var(l)tt(/)var(r)[tt(/)])(
 Substitute var(r) for var(l) as described below.
@@ -272,6 +270,17 @@
 inside braces, and in filename generation it must be quoted with a
 backslash.
 )
+item(tt(t))(
+Remove all leading pathname components, leaving the tail.  This works
+like `tt(basename)'.
+)
+item(tt(u))(
+Convert the words to all uppercase.
+)
+item(tt(x))(
+Like tt(q), but break into words at whitespace.  Does not work with
+parameter expansion.
+)
 enditem()
 
 The tt(s/l/r/) substitution works as follows.  By default the left-hand


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Modifiers that implement realpath-like feature
  2009-03-15  1:05     ` Peter Stephenson
@ 2009-03-15  1:20       ` Peter Stephenson
  0 siblings, 0 replies; 5+ messages in thread
From: Peter Stephenson @ 2009-03-15  1:20 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Michael Hwang, zsh-workers

On Sun, 15 Mar 2009 01:05:43 +0000
Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> On Sat, 14 Mar 2009 14:27:09 -0700 (PDT)
> Michael Hwang <nomex45@yahoo.com> wrote:
> > Sorry, here.
> 
> Thanks, that seems to work well.  I'll commit it with the following
> documentation.

... now done, with some largely cosmetic changes

- lines wrapped to 80 columns
- don't use variable declarations within blocks since we don't rely on C99.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-03-15  1:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-12 22:42 PATCH: Modifiers that implement realpath-like feature Michael Hwang
2009-03-14 18:14 ` Peter Stephenson
2009-03-14 21:27   ` Michael Hwang
2009-03-15  1:05     ` Peter Stephenson
2009-03-15  1:20       ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).