From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: "J.P." Newsgroups: gmane.emacs.bugs Subject: bug#74516: 31.0.50; ERC 5.6.1-git: [PATCH] allow port as string in auth-source params Date: Mon, 25 Nov 2024 19:36:00 -0800 Message-ID: <87bjy2ekf3.fsf__3893.48551850475$1732592246$gmane$org@neverwas.me> References: <87r070gw2k.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="16036"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: 74516@debbugs.gnu.org, emacs-erc@gnu.org To: Trevor Arjeski Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Nov 26 04:37:18 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1tFmO6-0003zx-4C for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 26 Nov 2024 04:37:18 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tFmNu-0007On-W6; Mon, 25 Nov 2024 22:37:07 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tFmNt-0007OQ-HX for bug-gnu-emacs@gnu.org; Mon, 25 Nov 2024 22:37:05 -0500 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tFmNr-0004MX-71 for bug-gnu-emacs@gnu.org; Mon, 25 Nov 2024 22:37:05 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:References:In-Reply-To:From:To:Subject; bh=939HqOnkLJMJjTif1Ed+PNjXyvLdVLTl9dVK/7hkoM8=; b=rEe2IdQ8sOQScuMkhwHRXzEvo+d8EmaXN4uT3jjdg1XqqJwIU5+6B6fAf3AtsqahRVvPELIDS705+MVTMmF5hX8Df21Ts0nLONccXmDfg9vF2H50w/2wybnyozX4BmvUHl0da0ipG22kcE4b7mr6ae/KABNwCTcIx43psWjPeRCEFIFuDppfkt3EbrPXFOrH1vYMY8q7+hywfEYZ3s8+fRXJqEayAjtgiyIcmVbgcVs5OSXYo1T6GGlgfp9ZXkI1DUFqU200q2wYr5icm10GzTWoqQGAX7uzOotIQWVEkgh9iFOtRsxl9mqry9tCiYc3IcjLsaTvryiZydmgKM15mw==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1tFmNq-0007cy-I5 for bug-gnu-emacs@gnu.org; Mon, 25 Nov 2024 22:37:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: "J.P." Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 26 Nov 2024 03:37:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 74516 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 74516-submit@debbugs.gnu.org id=B74516.173259217129241 (code B ref 74516); Tue, 26 Nov 2024 03:37:02 +0000 Original-Received: (at 74516) by debbugs.gnu.org; 26 Nov 2024 03:36:11 +0000 Original-Received: from localhost ([127.0.0.1]:43744 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tFmN0-0007bV-6b for submit@debbugs.gnu.org; Mon, 25 Nov 2024 22:36:11 -0500 Original-Received: from mail-108-mta191.mxroute.com ([136.175.108.191]:33101) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tFmMw-0007bH-Hk for 74516@debbugs.gnu.org; Mon, 25 Nov 2024 22:36:08 -0500 Original-Received: from filter006.mxroute.com ([136.175.111.3] filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta191.mxroute.com (ZoneMTA) with ESMTPSA id 193668a59890003e01.001 for <74516@debbugs.gnu.org> (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384); Tue, 26 Nov 2024 03:36:03 +0000 X-Zone-Loop: 54aabf4ae2fdc08879a4107ecf07534c75f07817d4af X-Originating-IP: [136.175.111.3] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=939HqOnkLJMJjTif1Ed+PNjXyvLdVLTl9dVK/7hkoM8=; b=PDB7cQInuNkByZuayu1Z197hu1 i8Z7yk/MD3AHhVObMo4RM8IrOq3O2iIG7lcKcQwItwcYvV9dDDOLaUoAuGBlLXBbg3/ROBaGRHxvO RnZuvtYwq0yzJDRq/6R2TFFaI7VZRWmNutsEG60CMWl/ypYoEolVLnWuiTlBlfE3+kI6Lj/gdOPJa 3pLOp0HRrEowYWDtJccMt/hvv+BVbI7dikSlYP15j8jL+y9G9Xu/+SA/X+sybjuTTJu18CDQlr3sK 6+eu5LAj9GrQicyvAn/cr1NbQ8vx/UGzyM+tevHGOehg8Ly+pCe18efZgKX9qHFD5aHJDtq8Awtgd WptzIkCQ==; In-Reply-To: <87r070gw2k.fsf@gmail.com> (Trevor Arjeski's message of "Mon, 25 Nov 2024 00:29:07 +0300") X-Authenticated-Id: masked@neverwas.me X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:295973 Archived-At: --=-=-= Content-Type: text/plain Trevor Arjeski writes: > Reproduction steps: > > 1. Have an entry in .authinfo, such as > machine yourbouncer login nick password hunter2 port 7777 > > 2. Using the following code in init.el, open emacs > 3. M-x erc-connect > 4. Notice ERC tries connecting without password > 5. Change erc-port to be an integer (commented out below) > 6. Retry steps 2 - 4 > > [3. text/x-org] > #+BEGIN_SRC emacs-lisp > (use-package erc > :ensure nil > :preface > (defun erc-connect () > (interactive) > (erc :server erc-server > :port erc-port > :user erc-nick)) > :custom > (erc-server "yourbouncer") > (erc-port "7777") ;; (erc-port 7777) is working > (erc-nick "nick")) > #+END_SRC Thanks. I can reproduce this. > From 9468a786fb8c0ef950117e78395592f2e11613c2 Mon Sep 17 00:00:00 2001 > From: Trevor Arjeski > Date: Sun, 24 Nov 2024 23:35:41 +0300 > Subject: [PATCH] erc: allow port as string in auth-source params > > Checking the equality of the given `erc-session-port' with "irc" is > unnecessary since: > > 1. "irc" is already added to the list of ports > 2. /etc/services may contain "ircs-u" (or other) as the desired port I think it makes sense to allow entries to specify well known service names. And I suppose it couldn't hurt to also at least implicitly support numeric strings, although that sounds like bad UX if anyone should need to resort to that just to differentiate between entries. > If the correct port/service is missing then the auth-source query will > fail for a seemingly unknown reason. IIRC, all params appearing in an auth-source entry are basically required, and a successful query must therefore supply all of them. However, such a query may specify additional, unmatched or partially matched parameters. > This also allows a user to `(setopt erc-port "1234")', intentionally or > accidentally, and still be able to use .authinfo for password > management. > --- > lisp/erc/erc.el | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el > index 7028d0a68cc..81818a7227e 100644 > --- a/lisp/erc/erc.el > +++ b/lisp/erc/erc.el > @@ -4675,8 +4675,7 @@ erc--auth-source-determine-params-defaults > (list net erc-server-announced-name erc-session-server))) > (ports (list (cl-typecase erc-session-port > (integer (number-to-string erc-session-port)) > - (string (and (string= erc-session-port "irc") > - erc-session-port)) ; or nil > + (string erc-session-port) ; or nil I've changed this slightly to become nil if `erc-session-port' is the empty string or "irc". > (t erc-session-port)) > "irc"))) > (list (cons :host (delq nil hosts)) I've also added a companion patch that changes some foundational behavior so that `erc-session-port' can more easily be set to a string to accommodate service names. With your example of machine mybouncer port ircs-u login mynick password hunter2 if someone tries to connect with (setopt auth-source-do-cache nil auth-source-debug t) (erc-tls :server "mybouncer" :nick "mynick") they should still be denied. But adding :port "ircs-u" to the invocation or doing something like (setopt erc-port "ircs-u") beforehand should see them succeed, assuming ircs-u appears in their /etc/services as a port listened on by their bouncer. Please try these out when you get a chance and give feedback if possible. Thanks. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-5.6.1-Allow-querying-auth-source-with-port-as-string.patch >From 0b82f7665c81008a0a3683c459c492f454c1a2af Mon Sep 17 00:00:00 2001 From: Trevor Arjeski Date: Sun, 24 Nov 2024 23:35:41 +0300 Subject: [PATCH 1/2] [5.6.1] Allow querying auth-source with port as string in ERC * lisp/erc/erc.el (erc--auth-source-determine-params-defaults): Allow arbitrary strings for `ers-session-port'. Previously, if a port/service was any string other than "irc", the auth-source query would fail for a seemingly unknown reason. Restricting the value to "irc" is unnecessary since "irc" is already added to the list of ports, and `make-network-process' already consults /etc/services for well-known service names, like "ircs-u", etc. This change allows a user to (setopt erc-port "1234"), intentionally or accidentally, while still being able to use .authinfo for password management. (Bug#74516) Copyright-paperwork-exempt: yes --- lisp/erc/erc.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 7028d0a68cc..60d84b2b20c 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -4675,8 +4675,9 @@ erc--auth-source-determine-params-defaults (list net erc-server-announced-name erc-session-server))) (ports (list (cl-typecase erc-session-port (integer (number-to-string erc-session-port)) - (string (and (string= erc-session-port "irc") - erc-session-port)) ; or nil + (string (and (not (member erc-session-port + '("" "irc"))) + erc-session-port)) (t erc-session-port)) "irc"))) (list (cons :host (delq nil hosts)) -- 2.47.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-5.6.1-Only-normalize-ports-for-equality-comparisons-.patch >From 420463c7f89a708ab0cc80e5bb2f6715fc48a03c Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 25 Nov 2024 04:21:36 -0800 Subject: [PATCH 2/2] [5.6.1] Only normalize ports for equality comparisons in ERC * etc/ERC-NEWS: Add entry explaining changes to entry point 'erc-tls' and library functions, like `erc-normalize-port' and `erc-compute-port'. * lisp/erc/erc.el (erc-normalize-port): Map "ircu" to 6665 instead of 6667. Add other IANA mappings. Return 0 for unknown nonempty strings. (erc-open): Pass `erc-session-port' through `erc-string-to-port' before handing it to `erc-server-connect'. This prevents the network-connection machinery from seeing a numeric string, like "6667". (erc-select-read-args): Use `erc-port-equal' instead of `eql'. (erc-tls): Respect a configured non-nil `erc-port' option when the user does not provide a :port argument. (erc-determine-parameters): Use `erc-compute-port' for `erc-session-port'. (erc-compute-port): Don't pass the result through `erc-normalize-port', which can convert it to an unintuitive form. (erc-handle-irc-url): Use `erc-port-equal' for comparison. (Bug#74516) * test/lisp/erc/erc-scenarios-auth-source.el (erc-scenarios-common--auth-source) (erc-scenarios-base-auth-source-server--dialed): Use `erc-port' option instead of passing a :port parameter to entry-point command. * test/lisp/erc/erc-tests.el (erc-normalize-port): New test. --- etc/ERC-NEWS | 25 +++++++++++ lisp/erc/erc.el | 52 +++++++++++++--------- test/lisp/erc/erc-scenarios-auth-source.el | 29 +++++++----- test/lisp/erc/erc-tests.el | 16 +++++++ 4 files changed, 88 insertions(+), 34 deletions(-) diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 3970f67d725..1c7c278338f 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -62,6 +62,31 @@ of concerns and the newer module's "experimental" status, the migration was deemed worth any potential disruption, despite this being a point release. ERC appreciates your understanding in this matter. +** Entry-point command 'erc-tls' now considers option 'erc-port'. +When called in Lisp code, this command now respects a non-nil 'erc-port' +if the ':port' keyword is absent. This also means users with this +option set to a non-TLS port should make sure to specify a ':port' from +now on. + +** Changes in the library API. + +*** Function 'erc-normalize-port' may return 0 instead of nil. +When given a nonempty, non-numeric string, this function now returns 0. +ERC now officially requests that users not use its output for anything +but comparing port equality, which was always its intended purpose. + +*** Function 'erc-compute-port' no longer uses 'erc-normalize-port'. +An uninformed change in ERC 5.5 led to 'erc-compute-port' filtering its +result through 'erc-normalize-port', which brought unwelcome type +coercion and possible null return values. This defied its purpose of +ensuring a usable port. Users reliant on the aberrant 5.5 behavior +should wrap its return value in 'erc-normalize-port'. + +*** Local variable 'erc-session-port' may be a string. +Although this has always been the case, string values are now more +likely to be seen because ERC no longer coerces service names to port +numbers. + * Changes in ERC 5.6 diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 60d84b2b20c..46f096142d6 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1987,13 +1987,11 @@ erc-reuse-buffers "old behavior when t now permanent" "29.1") (defun erc-normalize-port (port) - "Normalize the port specification PORT to integer form. -PORT may be an integer, a string or a symbol. If it is a string or a -symbol, it may have these values: -* irc -> 194 -* ircs -> 994 -* ircd -> 6667 -* ircd-dalnet -> 7000" + "Normalize known PORT specifications to an integer. +Expect PORT to be an integer, a string, or a symbol to coerce into a +standardized form for the express purpose of equality comparisons. If +PORT is an IANA recognized service, return its numeric mapping. Do the +same for a few traditional but nonstandard names." ;; These were updated somewhat in 2022 to reflect modern standards ;; and practices. See also: ;; @@ -2001,7 +1999,7 @@ erc-normalize-port ;; https://www.iana.org/assignments/service-names-port-numbers (cond ((symbolp port) - (erc-normalize-port (symbol-name port))) + (and port (erc-normalize-port (symbol-name port)))) ((stringp port) (let ((port-nr (string-to-number port))) (cond @@ -2011,14 +2009,19 @@ erc-normalize-port 194) ((string-equal port "ircs") 994) - ((string-equal port "ircu") 6667) ; 6665-6669 + ((string-equal port "ircu") 6665) + ((string-equal port "ircu-2") 6666) + ((string-equal port "ircu-3") 6667) + ((string-equal port "ircu-4") 6668) + ((string-equal port "ircu-5") 6669) ((string-equal port "ircd") ; nonstandard (irc-serv is 529) 6667) ((string-equal port "ircs-u") 6697) ((string-equal port "ircd-dalnet") 7000) + ((string-empty-p port) nil) (t - nil)))) + 0)))) ((numberp port) port) (t @@ -2665,7 +2668,7 @@ erc-open (if connect (erc-server-connect erc-session-server - erc-session-port + (erc-string-to-port erc-session-port) buffer erc-session-client-certificate) (erc-update-mode-line)) @@ -2769,8 +2772,8 @@ erc-select-read-args (port (or (url-portspec url) (erc-compute-port (let ((d (erc-compute-port sp))) ; may be a string - (read-string (format-prompt "Port" d) - nil nil d))))) + (erc-string-to-port + (read-string (format-prompt "Port" d) nil nil d)))))) ;; Trust the user not to connect twice accidentally. We ;; can't use `erc-already-logged-in' to check for an existing ;; connection without modifying it to consider USER and PASS. @@ -2792,10 +2795,10 @@ erc-select-read-args (format-prompt "Server password" p) "Server password (optional): "))) (if erc-prompt-for-password (read-passwd m nil p) p))) - (opener (and (or sp (eql port erc-default-port-tls) + (opener (and (or sp (erc-port-equal port erc-default-port-tls) (and (equal server erc-default-server) (not (string-prefix-p "irc://" input)) - (eql port erc-default-port) + (erc-port-equal port erc-default-port) (y-or-n-p "Connect using TLS instead? ") (setq port erc-default-port-tls))) #'erc-open-tls-stream)) @@ -2891,7 +2894,8 @@ 'erc-ssl ;;;###autoload (cl-defun erc-tls (&key (server (erc-compute-server)) - (port (erc-compute-port 'ircs-u)) + (port (let ((erc-default-port erc-default-port-tls)) + (erc-compute-port))) (nick (erc-compute-nick)) (user (erc-compute-user)) password @@ -8841,7 +8845,7 @@ erc-determine-parameters - `erc-server-current-nick'" (setq erc-session-connector erc-server-connect-function erc-session-server (erc-compute-server server) - erc-session-port (or port erc-default-port) + erc-session-port (erc-compute-port port) erc-session-user-full-name (erc-compute-full-name name) erc-session-username (erc-compute-user user) erc-session-password (erc--compute-server-password passwd nick)) @@ -8914,8 +8918,12 @@ erc-compute-port - PORT (the argument passed to this function) - The `erc-port' option -- The `erc-default-port' variable" - (erc-normalize-port (or port erc-port erc-default-port))) +- The `erc-default-port' variable + +Note that between ERC 5.5 and 5.6.1, this function filtered its result +through `erc-normalize-port', which introduced regrettable surprises, +such as unwelcome, possibly null, type conversions." + (or (and port (not (equal "" port)) port) erc-port erc-default-port)) ;; time routines @@ -9909,9 +9917,9 @@ erc-handle-irc-url (and (string-equal erc-session-server host) ;; Ports only matter when dialed hosts ;; match and we have sufficient info. - (or (not port) - (= (erc-normalize-port erc-session-port) - port))))))))) + (or (null port) + (erc-port-equal erc-session-port + port))))))))) key deferred) (unless server-buffer (setq deferred t diff --git a/test/lisp/erc/erc-scenarios-auth-source.el b/test/lisp/erc/erc-scenarios-auth-source.el index f0a7a4cbaca..7e1e7c2f3ab 100644 --- a/test/lisp/erc/erc-scenarios-auth-source.el +++ b/test/lisp/erc/erc-scenarios-auth-source.el @@ -44,15 +44,19 @@ erc-scenarios-common--auth-source (string-join ents "\n"))) (auth-sources (list netrc-file)) (auth-source-do-cache nil) + (erc-port (and (eq erc-port 'test) (number-to-string port))) (erc-scenarios-common-extra-teardown (lambda () - (delete-file netrc-file)))) + (delete-file netrc-file))) + ;; With a `cl-defun', a keyword's presence prevents the default + ;; init form from being evaluated, even if its value is nil. + (args `( :server "127.0.0.1" + ,@(and (null erc-port) (list :port port)) + :nick "tester" + :full-name "tester" + :id ,id))) (ert-info ("Connect") - (with-current-buffer (erc :server "127.0.0.1" - :port port - :nick "tester" - :full-name "tester" - :id id) + (with-current-buffer (apply #'erc args) (should (string= (buffer-name) (if id (symbol-name id) (format "127.0.0.1:%d" port)))) @@ -60,12 +64,13 @@ erc-scenarios-common--auth-source (ert-deftest erc-scenarios-base-auth-source-server--dialed () :tags '(:expensive-test) - (erc-scenarios-common--auth-source - nil 'foonet - "machine GNU.chat port %d user tester password fake" - "machine FooNet port %d user tester password fake" - "machine 127.0.0.1 port %d user tester password changeme" - "machine 127.0.0.1 port %d user imposter password fake")) + (let ((erc-port 'test)) + (erc-scenarios-common--auth-source + nil 'foonet + "machine GNU.chat port %d user tester password fake" + "machine FooNet port %d user tester password fake" + "machine 127.0.0.1 port \"%s\" user tester password changeme" ; correct + "machine 127.0.0.1 port %d user imposter password fake"))) (ert-deftest erc-scenarios-base-auth-source-server--netid () :tags '(:expensive-test) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 4c5521721f0..c6936ba8dc0 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -2978,6 +2978,22 @@ erc--route-insertion (should-not (buffer-live-p spam-buffer)) (kill-buffer chan-buffer))) +(ert-deftest erc-normalize-port () + ;; The empty string, nil, and unsupported types become nil. + (should-not (erc-normalize-port "")) + (should-not (erc-normalize-port nil)) + (should-not (erc-normalize-port (current-buffer))) + + ;; Unrecognized names are coerced to 0. + (should (equal 0 (erc-normalize-port "fake"))) + + ;; Numbers pass through, but numeric strings are coerced. + (should (equal 6667 (erc-normalize-port 6667))) + (should (equal 6697 (erc-normalize-port "6697"))) + + ;; Strange IANA mappings recognized. + (should (equal 6665 (erc-normalize-port "ircu")))) + (defvar erc-tests--ipv6-examples '("1:2:3:4:5:6:7:8" "::ffff:10.0.0.1" "::ffff:1.2.3.4" "::ffff:0.0.0.0" -- 2.47.0 --=-=-=--