|
From: Elle S. <ell...@ni...> - 2014-02-20 13:35:18
|
Responsibility for complying with ICC profile licenses belongs to the individual. Policing for ICC profile license violations is not a proper role for imaging and file format software. Libpng contains code that checks for embedded ICC profiles that violate licenses with which the profiles were released. This code should be removed. Below are excerpts from an email exchange between John Bowler and myself, quoted with permission. The topic is also mentioned in comments in this gimp bug report: https://bugzilla.gnome.org/show_bug.cgi?id=721135 On 02/14/2014 11:42 PM, John Bowler wrote: > On Fri, Feb 14, 2014 at 1:54 PM, Elle Stone > <ell...@ni...>wrote: The sentence below refers to the color.org sRGB profiles: >> Fourth, the profiles can't be distributed with floss software. > !?! Glenn: I think I raised this before, in the context of embedding one > or other of the profiles into libpng at allow iCCP to be valid if sRGB is > encountered (but maybe I just thought about it). I think this > is acceptably compatible with the libpng license (it's from > http://www.color.org/srgbprofiles.xalter): > > "To anyone who acknowledges that the files > "sRGB_IEC61966-2-1_no_black_scaling.icc" and "sRGB_IEC61966-2-1_black > scaled.icc" are provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY, > permission to use, copy and distribute these file for any purpose is hereby > granted without fee, provided that the files are not changed including the > ICC copyright notice tag, and that the name of ICC shall not be used in > advertising or publicity pertaining to distribution of the software without > specific, written prior permission. ICC makes no representations about the > suitability of this software for any purpose." > Whether the color.org license is compatible with the libpng license is one question. Whether Debian, FSF, Fedora, etc would accept the color.org license as free is another question. There are better alternatives than including or recommending the use of proprietary color.org profiles with free software. > And I think libpng already attempts to validate the non-modification clause > in that license. > This libpng attempt to validate an ICC profile's license non-modification clause is not something *any* imaging or file format software should do. The user, not libpng, is responsible for making sure the user complies with ICC profile license requirements. >> Good sRGB profiles can be made with LCMS and ArgyllCMS, so there's no >> reason to use the color.org sRGB V2 profiles. > > > So? libpng doesn't object to those profiles, even though I might think > they are totally bogus. It only objects to the two that you *cannot* > distribute with floss software, indeed, so far as I can see, that you can > only *use* if you are also running one of Windows, Mac Office (not sure > about that) or certain HP (Dell?) hardware. > The only HP sRGB license I can find is this one: https://svn.apache.org/repos/asf/pdfbox/trunk/examples/src/main/resources/org/apache/pdfbox/resources/pdfa/sRGB%20Color%20Space%20Profile.icm.LICENSE.txt The license on the apache page says: ##begin quote## The file "sRGB Color Space Profile.icm" is: Copyright (c) 1998 Hewlett-Packard Company To anyone who acknowledges that the file "sRGB Color Space Profile.icm" is provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY: permission to use, copy and distribute this file for any purpose is hereby granted without fee, provided that the file is not changed including the HP copyright notice tag, and that the name of Hewlett-Packard Company not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Hewlett-Packard Company makes no representations about the suitability of this software for any purpose. ##end quote## I can't find a more onerous HP ICC profile license. But if such a license exists, libpng still should not be policing whether the user might be violating the terms of said license. That responsibility belongs to the user. In effect, libpng has turned itself into digital rights management software. To summarize, the current libpng code: 1. Checks for two old HP profiles that are claimed to have onerous licenses. 2. Attempts to validate the color.org profile license non-modification clause. These portions of the libpng code should be removed. Imaging software and file format libraries should not take on the role of policing which ICC profiles a user uses, how they choose to use them, or whether their use constitutes a violation of the ICC profile's license. Responsibility for making sure that the user complies with ICC profile license restrictions lies with the user, not the imaging software or the file format that the user chooses to use. The fact that libpng does check some profiles for license violations sets a bad precedent that could have unintended and onerous consequences. Imaging and file format software is not and should not also be Digital Rights Management software. Elle Stone |
|
From: Glenn Randers-P. <gl...@gm...> - 2014-02-20 14:51:33
|
On Thu, Feb 20, 2014 at 8:40 AM, Elle Stone
<ell...@ni...>wrote:
> Responsibility for complying with ICC profile licenses belongs to the
> individual. Policing for ICC profile license violations is not a proper
> role for imaging and file format software.
>
> Libpng contains code that checks for embedded ICC profiles that violate
> licenses with which the profiles were released. This code should be removed.
>
Libpng contains code that attempts to identify ICC profiles that contain
the sRGB profile.
In two cases it reports a possible copyright violation as the explanation
for rejecting the profile.
We do need to reject those for technical reasons (since they have been
modified in some
unknown way, we can't be sure they still are really sRGB).
So we could remove the check entirely as Elle suggests (thereby falling
through and
returning "0" to indicate no match), or we could replace the benign error
with
a warning that doesn't mention the copyright problem, i.e.,
replace
# if PNG_sRGB_PROFILE_CHECKS > 0
/* The signature matched, but the profile had been changed in
some
* way. This is an apparent violation of the ICC terms of use
and,
* anyway, probably indicates a data error or uninformed
hacking.
*/
if (png_sRGB_checks[i].have_md5)
png_benign_error(png_ptr,
"copyright violation: edited ICC profile ignored");
# endif
with
# if PNG_sRGB_PROFILE_CHECKS > 0
/* The signature matched, but the profile had been changed in
some
* way, which probably indicates a data error or uninformed
hacking.
*/
if (png_sRGB_checks[i].have_md5)
png_chunk_report(png_ptr,
"edited ICC profile not recognized as sRGB",
PNG_CHUNK_WARNING);
# endif
> The fact that libpng does check some profiles for license violations sets
> a bad precedent that could have unintended and onerous consequences.
> Imaging and file format software is not and should not also be Digital
> Rights Management software.
>
Right. I think we're OK so long as we don't distribute
copyright-infringing profiles with (or embedded in) libpng.
Glenn
|
|
From: John B. <joh...@gm...> - 2014-02-20 20:46:48
|
Notice there are off-list contributes, so please reply all. On Thu, Feb 20, 2014 at 6:51 AM, Glenn Randers-Pehrson <gl...@gm...>wrote: > >> Libpng contains code that attempts to identify ICC profiles that contain > the sRGB profile. > In two cases it reports a possible copyright violation as the explanation > for rejecting the profile. > We do need to reject those for technical reasons (since they have been > modified in some > unknown way, we can't be sure they still are really sRGB). > Glenn and I have disagreed about the latter statement before - what's in the code is a compromise. If the profile contains an MD5 signature (not all do) we check for it. For profiles that don't we check the adler32 and crc32 of the profile, calculating the crc32 requires work so can be disabled. Glenn feels that if the MD5 matches but the adler32/crc32 don't match we should not treat the profile as sRGB. Unfortunately the MD5 signature doesn't cover all the bytes of the profile, the ICC could, conceivably, release a version of the profile that changed the relevant fields. The fields don't change what the profile does, they just convey information to the user of the profile about how it was expected to be used, or how it was used. My viewpoint is that we should just check the MD5. As is normal, this led to a piece of build time configuration: PNG_sRGB_PROFILE_CHECKS == 0 The MD5 is used if available, nothing else is checked. No warning messages. PNG_sRGB_PROFILE_CHECKS == 1 The MD5 is checked and if it matches the adler32 (from the zlib stream) is also checked, the profile is regarded as not-sRGB if the check fails. PNG_SRGB_PROFILE_CHECKS == 2 In addition to the above a full crc32 is also calculated if everything passes. The profile is only regarded as sRGB if this passes too. Unfortunately after we reject the MD5 we are in an unusual situation. Firstly we must issue a warning message - I completely disagree with Glenn on silently assuming the profile is not sRGB because it *could* be a new valid ICC profile with different flags. We need to know PDQ that this has happened and that we are ignoring a new profile. At the point where we issue a warning we have a duty to inform the user because we know the license on the file with that MD5 signature and we know it prohibits modification, with the possible exception of the flag fields (which, it seems to me, the ICC actually expects to be modified.) Because the profile is embedded in an image the user can't be assumed to know this. My feeling is that we should default to PNG_sRGB_PROFILE_CHECKS == 0, and document that this may cause hacked profiles to be flagged as sRGB but that those profiles violate the ICC spec (because the MD5 was not recomputed). I'd prefer to remove the other checking options. In reality we know that system builders don't change these configurations, so whichever we choose as the *default* is the one that gets used. We could leave the other options in, and I guess then we could leave out the warning so long as we document this in scripts/pnglibconf.dfa We could also go down Glenn's route and, in that case, not check the MD5 at all. The problem is that we should be skipping the relevant profile fields in the checksum, but we can address that by computing the crc32 if the adler32 fails and computing it correctly - without the flag fields. Or we could simply use the crc32. I think the original choice to use both adler32 and crc32 was based on mistaking the scenario for the "birthdays" case. If you have 65536 profiles then it's pretty much certain that two of them will have the same adler32 or crc32 checksum, it is more than likely that there are 65536 profiles out there. However, in this case, we are only looking at 7 profiles and this number will not increase without a code change. Therefore our change of a false positive is 1 in 6x10^8 with a single checksum. I suggest we can fix that bug when it happens. Elle said: > > The fact that libpng does check some profiles for license violations sets >> a bad precedent that could have unintended and onerous consequences. >> Imaging and file format software is not and should not also be Digital >> Rights Management software. > > That's incorrect. We *know* that the profile is a modified version of the ICC one and we *known* the license on the ICC profile. We don't check for this, we know it a-priori as a result of the checks we perform. Hence: > The user, not libpng, is responsible for making sure the user complies with ICC profile license >requirements. So we should not *hide* information that will help the user in meeting that requirement. We maybe don't have a responsibility to go out of our way to *help*, but that's not the situation. The moral issue is; what do you do when you see something that you believe violates someone else's rights? So far as I know it is not a crime to violate someone's copyright, it's a civil issue. Nevertheless even accidental use of the profile might conceivably lead an innocent user of libpng to have to remove the profile from all the images that contain it. Given that we have stumbled over this fact and that we are already warning the user that something is odd it seems morally reprehensible to not point out that, likely as not, there is a copyright violation. John Bowler |
|
From: Elle S. <ell...@ni...> - 2014-02-20 23:05:35
|
On 02/20/2014 09:51 AM, Glenn Randers-Pehrson wrote: > Libpng contains code that attempts to identify ICC profiles that contain > the sRGB profile. Why? > In two cases it reports a possible copyright violation as the explanation > for rejecting the profile. > We do need to reject those for technical reasons(since they have been > modified in some > unknown way, we can't be sure they still are really sRGB). > 1. What is the libpng criteria for "really sRGB"? 2. What is the technical reason that makes it necessary that libpng must pass judgement on whether an embedded ICC profile is "really sRGB"? Elle |
|
From: Glenn Randers-P. <gl...@gm...> - 2014-02-21 00:07:36
|
On Thu, Feb 20, 2014 at 6:11 PM, Elle Stone <ell...@ni...>wrote: > On 02/20/2014 09:51 AM, Glenn Randers-Pehrson wrote: > >> Libpng contains code that attempts to identify ICC profiles that contain >> the sRGB profile. >> > > Why? > So we can, if possible, replace the iCCP chunk with the sRGB chunk. At least that was the theory. But that idea came about when we thought sRGB meant something unambiguous. Now we know, much thanks to your work, that there are what, fifteen or more different profiles now, all claiming to be sRGB. > > In two cases it reports a possible copyright violation as the explanation >> for rejecting the profile. >> We do need to reject those for technical reasons(since they have been >> >> modified in some >> unknown way, we can't be sure they still are really sRGB). >> >> > 1. What is the libpng criteria for "really sRGB"? > Libpng's is still evolving. Mine is that it can be swapped with another "really sRGB" profile and not have anything go wrong with the image. > > 2. What is the technical reason that makes it necessary that libpng must > pass judgement on whether an embedded ICC profile is "really sRGB"? > See above. It's been on our TODO for a long time to identify sRGB ICC profiles carried in the iCCP chunk and replace them with the 13-byte sRGB chunk. Also the reverse, if we are copying a PNG with the sRGB chunk to another image format, one that conveys ICC profiles but not the sRGB chunk, to have the "real sRGB" profile on hand, to insert in the new image. We'd probably need at least two, one for 16-bit images and another with 257 or fewer points for 8-bit images. Glenn |
|
From: Bob F. <bfr...@si...> - 2014-02-21 00:18:23
|
On Thu, 20 Feb 2014, Glenn Randers-Pehrson wrote: > > See above. It's been on our TODO for a long time to identify sRGB ICC > profiles carried in the iCCP chunk and replace them with the 13-byte sRGB chunk. While this is a nice optimization, it can surely cause harm to someone's workflow if they receive a PNG file which has the sRGB ICC profile unexpectedly stripped and they don't have the profile available locally, or the software they are using does not support finding a sRGB ICC profile. I am familiar with software which knows how to use ICC profiles but does not automatically provide them. The case where it causes harm is if the receiving software intended to actually use the profile. There is also harm if the using software does not properly bridge the attributes while performing operations (which do not modify color) on the image. > Also the reverse, if we are copying a PNG with the sRGB chunk to another > image format, one that conveys ICC profiles but not the sRGB chunk, to have > the "real sRGB" profile on hand, to insert in the new image. We'd probably need > at least two, one for 16-bit images and another with 257 or fewer points for > 8-bit images. Is there one "real sRGB" profile which is free to copy? Bob -- Bob Friesenhahn bfr...@si..., http://www.simplesystems.org/users/bfriesen/ GraphicsMagick Maintainer, http://www.GraphicsMagick.org/ |
|
From: John B. <joh...@gm...> - 2014-02-21 03:35:39
|
I copied back to Elle Stone and Graeme Gill, because I feel that if I don't we will achieve a false resolution simply by excluding the people who have suggested that the current implementation is wrong. Sorry Elle, Graeme; the original response from Bob is on the png-mng-implement archive on sourceforge. On Thu, Feb 20, 2014 at 4:18 PM, Bob Friesenhahn < bfr...@si...> wrote: > On Thu, 20 Feb 2014, Glenn Randers-Pehrson wrote: > >> >> See above. It's been on our TODO for a long time to identify sRGB ICC >> profiles carried in the iCCP chunk and replace them with the 13-byte sRGB >> chunk. >> > > While this is a nice optimization, Agreed, but that wasn't why I did it. It's a useful side effect - if you *know* that the image data is sRGB despite containing an iCCP chunk you can safely do processing assuming the data is sRGB ;-) > it can surely cause harm to someone's workflow if they receive a PNG file > which has the sRGB ICC profile unexpectedly stripped and they don't have > the profile available locally, That doesn't happen. The profile is still there. Perhaps the confusion arises because Glenn is considering whether pngcrush (an application) should remove iCCP chunks that definitely, 100%, are ICC distributed sRGB profiles. libpng does not do this; it, instead, informs the app that the PNG contains a profile that is definitely, 100% sure, an ICC sRGB profile. It's up to the app what to do next; both pieces of information are available. The case where it causes harm is if the receiving software intended to > actually use the profile. That doesn't happen. > There is also harm if the using software does not properly bridge the > attributes while performing operations (which do not modify color) on the > image. That does not happen unless the app chooses to do so (the default is to write the profile in preference to the sRGB tag). In fact an app cannot set both a-priori - it has to make a decision - but an app that takes a png_info from a read struct and uses it with a write struct should, invariably, copy the information that was in the original PNG (that was my intention.) > Is there one "real sRGB" profile which is free to copy? Yes, it is *sRGB_v4_ICC_preference.icc* on this web page: http://www.color.org/srgbprofiles.xalter The license is on that page too. The issue is that different CMS's have different levels of support. I believe LCMS2 should support that profile but certainly other CMSs don't. So a number of different ICC profiles exist to support different CMS capabilities, or omissions, or bugs, depending on your viewpoint. This is another reason why I believe it is important for libpng to reliably identify ICC sRGB profiles - because then if someone embeds a profile that a particular CMS cannot handle it is possible for the CMS to handle it. Indeed, if a CMS simply ignores profiles that are identified as ICC sRGB profiles and uses its own (assuming it conforms to the ICC spec) it has a much better chance of getting the right result than if it relies on the embedded profile. Contrariwise if a CMS author wants to create an sRGB profile that is *better* than the ICC ones then the CMS author can and libpng will ignore it - it is not treated as an sRGB profile. So I think the current behavior is both well defined and easy to understand. If we byte-match an ICC sRGB profile we say that so by means of saying that an sRGB tag was present. We also tell an app that uses the simplified API that the colorspace is definitely sRGB (as defined by the sRGB standard, not the ICC), just as we do if the gAMA and cHRM chunks match the sRGB values. -- John Bowler <joh...@gm...> +1 (541) 450-9885 PO BOX 3151 KERBY OR 97531-3151 USA |
|
From: Elle S. <ell...@ni...> - 2014-02-21 16:49:46
|
On 02/20/2014 10:35 PM, John Bowler wrote: > On Thu, Feb 20, 2014 at 7:18 PM, Bob Friesenhahn < > bfr...@si...> wrote: > >> While this is a nice optimization, > > > Agreed, but that wasn't why I did it. It's a useful side effect - if you > *know* that the image data is sRGB despite containing an iCCP chunk you can > safely do processing assuming the data is sRGB ;-) Please let the user decide if they are using the wrong ICC profile and if so, what to do about it. If this libpng profile screening behavior is in any way inspired by my article outlining the many variations of sRGB that have been distributed, then I heartily wish I hadn't ever written the article. The point of the article was to alert users to take care in what sRGB profile they choose to use. It wasn't to suggest that software try to make those decisions for the user. > >> Is there one "real sRGB" profile which is free to copy? > > > Yes, it is *sRGB_v4_ICC_preference.icc* on this web page: > > http://www.color.org/srgbprofiles.xalter That particular color.org sRGB profile is for use in a very specialized V4 sRGB print-oriented workflow. Also, the sRGB preference profile is a LUT profile, not a matrix profile. If you want a V2 matrix sRGB profile that is compatible with free and open source licenses, use Graeme's Gill's public domain sRGB.icm, downloadable with ArgyllCMS. If you want a V4 functional equivalent to Graeme's sRGB.icm, I can send you one that's licensed CC0. John might say these profiles are not really sRGB. If so, I think what he means is that libpng doesn't know they are sRGB because libpng hasn't added hard-coded checks for same. So the prior question would be how do the libpng programmers decide which profiles should be on the list of valid sRGB profiles and which ones should not be? The question of how sRGB profiles get "on the list" would be completely moot if libpng were to remove all profile checking code, as it should. So from a practical point of view, if libpng doesn't remove the profile checking code, at least please don't add new profiles to the list. > The license is on that page too. As the color.org license says the profile can't be modified, the license isn't free. > The issue is that different CMS's have different levels of support. I > believe LCMS2 should support that profile but certainly other CMSs don't. > So a number of different ICC profiles exist to support different CMS > capabilities, or omissions, or bugs, depending on your viewpoint. Another reason different sRGB ICC profiles exist is to support different user goals in a color-managed workflow: The proprietary color.org preferences profile is for use in a specialized color.org V4 print workflow. The proprietary color.org V2 "no black scaling" profile is for use as a substitute for a real monitor profile. The proprietary color.org V2 black scaled profile is a substitute for the old HP sRGB matrix profiles. It has an incorrect, non-zero black point tag that conflicts with the profile tone reproduction curves. The ArgyllCMS sRGB profile is a V2 public domain substitute for the old HP sRGB matrix profiles. My V4 functional equivalent of Graeme Gill's sRGB.icm profile is to take advantage of the LCMS unbounded mode profile conversions that can't be done using a profile with tone reproduction curves defined by points. A number of other sRGB profiles exist because someone made a peculiar choice for the source white point or the primaries or the tone reproduction curve. Yet others exist because there is a need for a linear gamma version of sRGB. Libpng shouldn't be second-guessing why any given profile - sRGB or otherwise - is embedded in an image. Even if a given sRGB ICC profile is completely bogus, as for example the sRGB profiles with the unadapted primaries, libpng can't know what the user has already done with the image or how the user would like to remedy whatever problems were caused by using this profile (as I believe Glenn was pointing out?). > This is another reason why I believe it is important for libpng to reliably > identify ICC sRGB profiles - because then if someone embeds a profile that > a particular CMS cannot handle it is possible for the CMS to handle it. Why does libpng try to detect that the CMM can't handle the embedded ICC profile? The user will discover the problem just as soon as they try to open the image with an image editing application that uses a CMM that can't handle the profile. It's up to the image editing application to issue an appropriate explanation. It's up to the user to decide what to do about it. > Indeed, if a CMS simply ignores profiles that are identified as ICC sRGB > profiles and uses its own (assuming it conforms to the ICC spec) it has a > much better chance of getting the right result than if it relies on the > embedded profile. Libpng can't know how much damage might be done to an image by substituting a different, libpng-approved sRGB profile for the one that is embedded in the image. Elle |
|
From: Glenn Randers-P. <gl...@gm...> - 2014-02-21 03:54:17
|
On Thu, Feb 20, 2014 at 7:18 PM, Bob Friesenhahn < bfr...@si...> wrote: > On Thu, 20 Feb 2014, Glenn Randers-Pehrson wrote: > >> >> See above. It's been on our TODO for a long time to identify sRGB ICC >> profiles carried in the iCCP chunk and replace them with the 13-byte sRGB >> chunk. >> > > While this is a nice optimization, it can surely cause harm to someone's > workflow if they receive a PNG file which has the sRGB ICC profile > unexpectedly stripped and they don't have the profile available locally, or > the software they are using does not support finding a sRGB ICC profile. I > am familiar with software which knows how to use ICC profiles but does not > automatically provide them. > It also harms them if they were using one of the profiles that gives a bluish cast with some image in which they've carefully compensated for that. > > The case where it causes harm is if the receiving software intended to > actually use the profile. There is also harm if the using software does > not properly bridge the attributes while performing operations (which do > not modify color) on the image. > > > Also the reverse, if we are copying a PNG with the sRGB chunk to another >> image format, one that conveys ICC profiles but not the sRGB chunk, to >> have >> the "real sRGB" profile on hand, to insert in the new image. We'd >> probably need >> at least two, one for 16-bit images and another with 257 or fewer points >> for >> 8-bit images. >> > > Is there one "real sRGB" profile which is free to copy? > argyll's srgb profile. John wrote: > Yes, it is *sRGB_v4_ICC_preference.icc* on this web page: > > http://www.color.org/srgbprofiles.xalter<http://www.color.org/srgbprofiles.xalter> > > The license is on that page too. The license says "provided that the file is not changed" which makes it non-free. It's free to copy and use but not free to modify. But now it seems we need to be able to provide many profiles (v2 and v4, bpc and not bpc, 16-bit,/8-bit/tiny, etc., etc.) so I'm thinking it's probably a lost cause (have been thinking that for a couple of years now since I ran across Elle's articles about sRGB). Glenn |
|
From: John B. <joh...@gm...> - 2014-02-21 00:17:32
|
On Thu, Feb 20, 2014 at 3:11 PM, Elle Stone
<ell...@ni...>wrote:
> On 02/20/2014 09:51 AM, Glenn Randers-Pehrson wrote:
> > Libpng contains code that attempts to identify ICC profiles that contain
> > the sRGB profile.
>
> Why?
>
Because in the libpng API we tell the application if there is some
possibility that we have just treated a non-sRGB image as though it were
sRGB. We could always set the flag for any image with an ICC profile, but
since there are a set of standard profiles approved by the ICC it seems
much more helpful to the app to check for them.
I couldn't solve the more general case of extracting a cHRM and gAMA chunk
from the profile and it is not soluble for a minimal ICC v2 profile. If it
were soluble I thought I could always do the right thing; say whether or
not the data does use the sRGB end-points and decode to linear correctly.
The other thread Elle posted will show why, in practice, we don't want to
do this anyway (we would be getting ourselves into a dispute between ICC
profile makers that we don't want to be involved in.)
>
> > In two cases it reports a possible copyright violation as the explanation
> > for rejecting the profile.
> > We do need to reject those for technical reasons(since they have been
> > modified in some
> > unknown way, we can't be sure they still are really sRGB).
> >
>
> 1. What is the libpng criteria for "really sRGB"?
>
That's a fragment of what Glenn said: "we can't be sure they still are
really sRGB." If we recognize the profile and the various checksums
indicate that it hasn't been changed then *we can be sure* it is an sRGB
profile.
>
> 2. What is the technical reason that makes it necessary that libpng must
> pass judgement on whether an embedded ICC profile is "really sRGB"?
>
I interpreted your first question ('Why?') as asking for a technical
justification, so the answer is the same.
John Bowler
|