Giter Site home page Giter Site logo

apple / ccs-caldavclientlibrary Goto Github PK

View Code? Open in Web Editor NEW
42.0 42.0 26.0 1.7 MB

CalDAV/CardDAV Testing Tool Used by CalendarServer

Home Page: https://www.calendarserver.org

License: Apache License 2.0

Python 4.05% HTML 95.74% CSS 0.13% JavaScript 0.08%

ccs-caldavclientlibrary's People

Contributors

bgaya avatar cyrusdaboo avatar dreness avatar exarkun avatar glyph avatar m0rgen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ccs-caldavclientlibrary's Issues

Better input testing in URL:compEqual

karra.etc@… originally submitted this as ticket:808


Check of None input and do something meaningful

From b53421747d150556a9bf6a6243bb015a1bfbde1d Mon Sep 17 00:00:00 2001
From: Sriram Karra <[email protected]>
Date: Wed, 10 Apr 2013 07:16:00 +0530
Subject: [PATCH] Better input testing in URL:compEqual

---
 caldavclientlibrary/protocol/url.py | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/caldavclientlibrary/protocol/url.py b/caldavclientlibrary/protocol/url.py
index c8e65fe..817466b 100644
--- a/caldavclientlibrary/protocol/url.py
+++ b/caldavclientlibrary/protocol/url.py
@@ -173,6 +173,12 @@ def equalRelative(self, comp):
         if comp.server:
             return False

+        if not self.path and not comp.path:
+            return True
+
+        if not self.path or not comp.path:
+            return False
+
         # Just compare paths, ignore trailing slash
         return self.path.rstrip("/") == comp.path.rstrip("/")

-- 
1.8.1.6

multiGet() support for carddav Part 1/2

karra.etc@… originally submitted this as ticket:810


This is the first part of the code to add carddav multiGet() support to the client library.

From 72ac60dc32c22b83af6ad57820af960e061cf692 Mon Sep 17 00:00:00 2001
From: Sriram Karra <[email protected]>
Date: Mon, 8 Apr 2013 11:18:24 +0530
Subject: [PATCH] Support for addressbook_multiget

Replicate the caldav/multiget.py functionality for carddav as well. Also
replicate the unit test caldav/tests/test_multiget.py

---
 caldavclientlibrary/protocol/carddav/multiget.py   |  76 ++++++++++++
 .../protocol/carddav/tests/test_multiget.py        | 134 +++++++++++++++++++++
 2 files changed, 210 insertions(+)
 create mode 100644 caldavclientlibrary/protocol/carddav/multiget.py
 create mode 100644 caldavclientlibrary/protocol/carddav/tests/test_multiget.py

diff --git a/caldavclientlibrary/protocol/carddav/multiget.py b/caldavclientlibrary/protocol/carddav/multiget.py
new file mode 100644
index 0000000..ddd0170
--- /dev/null
+++ b/caldavclientlibrary/protocol/carddav/multiget.py
@@ -0,0 +1,76 @@
+##
+# Copyright (c) 2007-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013 Sriram Karra <[email protected]>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from StringIO import StringIO
+from caldavclientlibrary.protocol.carddav.definitions import carddavxml
+from caldavclientlibrary.protocol.http.data.string import RequestDataString
+from caldavclientlibrary.protocol.utils.xmlhelpers import BetterElementTree
+from caldavclientlibrary.protocol.webdav.definitions import davxml
+from caldavclientlibrary.protocol.webdav.report import Report
+from xml.etree.ElementTree import Element
+from xml.etree.ElementTree import SubElement
+
+class Multiget(Report):
+
+    def __init__(self, session, url, hrefs, props=()):
+        super(Multiget, self).__init__(session, url)
+        self.props = props
+        self.hrefs = hrefs
+
+        self.initRequestData()
+
+
+    def initRequestData(self):
+        # Write XML info to a string
+        os = StringIO()
+        self.generateXML(os)
+        self.request_data = RequestDataString(os.getvalue(),
+                                              "text/xml charset=utf-8")
+
+
+    def generateXML(self, os):
+        ## FIXME: Needs to be replace.
+        # Structure of document is:
+        #
+        # <CardDAV:addressbook-multiget>
+        #   <DAV:prop>
+        #     <<names of each property as elements>>
+        #   </DAV:prop>
+        #   <DAV:href>...</DAV:href>
+        #   ...
+        # </CardDAV:addresbook-multiget>
+
+        # <CardDAV:addressbook-multiget> element
+        multiget = Element(carddavxml.addressbook_multiget)
+
+        if self.props:
+            # <DAV:prop> element
+            prop = SubElement(multiget, davxml.prop)
+
+            # Now add each property
+            for propname in self.props:
+                # Add property element taking namespace into account
+                SubElement(prop, propname)
+
+        # Now add each href
+        for href in self.hrefs:
+            # Add href elements
+            SubElement(multiget, davxml.href).text = href
+
+        # Now we have the complete document, so write it out (no indentation)
+        xmldoc = BetterElementTree(multiget)
+        xmldoc.writeUTF8(os)
diff --git a/caldavclientlibrary/protocol/carddav/tests/test_multiget.py b/caldavclientlibrary/protocol/carddav/tests/test_multiget.py
new file mode 100644
index 0000000..d575a8e
--- /dev/null
+++ b/caldavclientlibrary/protocol/carddav/tests/test_multiget.py
@@ -0,0 +1,134 @@
+##
+# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013 Sriram Karra <[email protected]>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.protocol.webdav.session import Session
+from caldavclientlibrary.protocol.carddav.multiget import Multiget
+from StringIO import StringIO
+from caldavclientlibrary.protocol.webdav.definitions import davxml
+import unittest
+
+host = 'www.example.com'
+
+class TestRequest(unittest.TestCase):
+
+
+    def test_Method(self):
+
+        server = Session(host)
+        request = Multiget(server, "/", ())
+        self.assertEqual(request.getMethod(), "REPORT")
+
+
+
+class TestRequestHeaders(unittest.TestCase):
+    pass
+
+
+
+class TestRequestBody(unittest.TestCase):
+
+    def test_GenerateXMLOneHrefOnly(self):
+
+        server = Session(host)
+        request = Multiget(server, "/", ("/a",))
+        os = StringIO()
+        request.generateXML(os)
+        self.assertEqual(os.getvalue(), """<?xml version='1.0' encoding='utf-8'?>
+<ns0:addressbook-multiget xmlns:ns0="urn:ietf:params:xml:ns:carddav">
+  <ns1:href xmlns:ns1="DAV:">/a</ns1:href>
+</ns0:addressbook-multiget>
+""".replace("\n", "\r\n")
+)
+
+
+    def test_GenerateXMLMultipleHrefsOnly(self):
+
+        server = Session(host)
+        request = Multiget(server, "/", ("/a", "/b",))
+        os = StringIO()
+        request.generateXML(os)
+        self.assertEqual(os.getvalue(), """<?xml version='1.0' encoding='utf-8'?>
+<ns0:addressbook-multiget xmlns:ns0="urn:ietf:params:xml:ns:carddav">
+  <ns1:href xmlns:ns1="DAV:">/a</ns1:href>
+  <ns1:href xmlns:ns1="DAV:">/b</ns1:href>
+</ns0:addressbook-multiget>
+""".replace("\n", "\r\n")
+)
+
+
+    def test_GenerateXMLMultipleHrefsOneProperty(self):
+
+        server = Session(host)
+        request = Multiget(server, "/", ("/a", "/b",), (davxml.getetag,))
+        os = StringIO()
+        request.generateXML(os)
+        self.assertEqual(os.getvalue(), """<?xml version='1.0' encoding='utf-8'?>
+<ns0:addressbook-multiget xmlns:ns0="urn:ietf:params:xml:ns:carddav">
+  <ns1:prop xmlns:ns1="DAV:">
+    <ns1:getetag />
+  </ns1:prop>
+  <ns1:href xmlns:ns1="DAV:">/a</ns1:href>
+  <ns1:href xmlns:ns1="DAV:">/b</ns1:href>
+</ns0:addressbook-multiget>
+""".replace("\n", "\r\n")
+)
+
+
+    def test_GenerateXMLMultipleHrefsMultipleProperties(self):
+
+        server = Session(host)
+        request = Multiget(server, "/", ("/a", "/b",), (davxml.getetag, davxml.displayname,))
+        os = StringIO()
+        request.generateXML(os)
+        self.assertEqual(os.getvalue(), """<?xml version='1.0' encoding='utf-8'?>
+<ns0:addressbook-multiget xmlns:ns0="urn:ietf:params:xml:ns:carddav">
+  <ns1:prop xmlns:ns1="DAV:">
+    <ns1:getetag />
+    <ns1:displayname />
+  </ns1:prop>
+  <ns1:href xmlns:ns1="DAV:">/a</ns1:href>
+  <ns1:href xmlns:ns1="DAV:">/b</ns1:href>
+</ns0:addressbook-multiget>
+""".replace("\n", "\r\n")
+)
+
+
+
+class TestResponse(unittest.TestCase):
+    pass
+
+
+
+class TestResponseHeaders(unittest.TestCase):
+    pass
+
+
+
+class TestResponseBody(unittest.TestCase):
+    pass
+
+
+def main (argv=None):
+    suite = unittest.TestLoader().loadTestsFromTestCase(TestRequest)
+    unittest.TextTestRunner(verbosity=2).run(suite)
+
+    suite = unittest.TestLoader().loadTestsFromTestCase(TestRequestBody)
+    unittest.TextTestRunner(verbosity=2).run(suite)
+
+
+if __name__ == '__main__':
+    main()
-- 
1.8.1.6

kerberos-1.1.1.tar.gz install failure

mrcastle@… originally submitted this as ticket:828


Hello, I am trying to install the kerberos module on my Windows 7 machine with Python 2.6. I downloaded the install file from pypi and used "gunzip -c kerberos-1.1.1.tar.gz | tar xf - " to extract it. When I run setup.py I get the attached error. I should say that I also tried this on a different Windows 7 machine with minGW and got the same error. I've found examples of people using the kerberos module in Windows so I think it should work. What am I missing? Thanks,

Mike

New QName for default_addressbook_url

karra.etc@… originally submitted this as ticket:807


As stated in the summary the patch below defines a new QName. Note that the patch is in the format of a git patch.

From e4ff6916fadcee62c074e0b009ada894576f03c1 Mon Sep 17 00:00:00 2001
From: Sriram Karra <[email protected]>
Date: Sat, 6 Apr 2013 17:37:15 +0530
Subject: [PATCH] New QName for default-addressbook-URL

---
 caldavclientlibrary/protocol/carddav/definitions/carddavxml.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/caldavclientlibrary/protocol/carddav/definitions/carddavxml.py b/caldavclientlibrary/protocol/carddav/definitions/carddavxml.py
index 3fd1453..ce255da 100644
--- a/caldavclientlibrary/protocol/carddav/definitions/carddavxml.py
+++ b/caldavclientlibrary/protocol/carddav/definitions/carddavxml.py
@@ -43,3 +43,5 @@
 text_match = QName(CardDAVNamespace, "text-match")

 addressbook_multiget = QName(CardDAVNamespace, "addressbook-multiget")
+
+def_adbk_url = QName(CardDAVNamespace, "default-addressbook-URL")
-- 
1.8.1.6

multiGet() support for carddav

karra.etc@… originally submitted this as ticket:806


caldavclient library has a multiGet() method for calldav, but not for carddav. The patch below implements this method. Note that this patch is in the git patch format:

From c98176a63e86f2fe6003f1580802404358a209a8 Mon Sep 17 00:00:00 2001
From: Sriram Karra <[email protected]>
Date: Fri, 12 Apr 2013 20:14:37 +0530
Subject: [PATCH] New multiGet() method to fetch multiple carddav documents in
 one shot

---
 caldavclientlibrary/client/clientsession.py | 31 +++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/caldavclientlibrary/client/clientsession.py b/caldavclientlibrary/client/clientsession.py
index e4c888d..e0b8599 100644
--- a/caldavclientlibrary/client/clientsession.py
+++ b/caldavclientlibrary/client/clientsession.py
@@ -18,6 +18,7 @@
 from caldavclientlibrary.protocol.caldav.definitions import headers
 from caldavclientlibrary.protocol.caldav.makecalendar import MakeCalendar
 from caldavclientlibrary.protocol.carddav.makeaddressbook import MakeAddressBook
+from caldavclientlibrary.protocol.carddav.multiget import Multiget
 from caldavclientlibrary.protocol.http.authentication.basic import Basic
 from caldavclientlibrary.protocol.http.authentication.digest import Digest
 from caldavclientlibrary.protocol.http.util import parseStatusLine
@@ -31,6 +32,7 @@
 from caldavclientlibrary.protocol.url import URL
 from caldavclientlibrary.protocol.webdav.acl import ACL
 from caldavclientlibrary.protocol.webdav.definitions import davxml
+from caldavclientlibrary.protocol.carddav.definitions import carddavxml
 from caldavclientlibrary.protocol.webdav.definitions import statuscodes
 from caldavclientlibrary.protocol.webdav.delete import Delete
 from caldavclientlibrary.protocol.webdav.get import Get
@@ -599,6 +601,35 @@ def queryCollection(self, rurl, timerange, start, end, expand, props=()):
         return hrefs


+    ## This works only for carddav multiget at the moment; but there is no
+    ## reason why this cannot be made more generic
+    def multiGet(self, rurl, hrefs, props):
+        """Fetches the specified props for the specified hrefs using a single
+        multoget call. The return value is a dictionary where the keys are the
+        hrefs and the values are PropFindResult objects containign results for
+        the requested props."""
+
+        assert(isinstance(rurl, URL))
+
+        request = Multiget(self, rurl.relativeURL(), hrefs=hrefs, props=props)
+        result = ResponseDataString()
+        request.setOutput(result)
+
+        # Process it
+        self.runSession(request)
+
+        # If it's a 207 we want to parse the XML
+        if request.getStatusCode() == statuscodes.MultiStatus:
+
+            parser = PropFindParser()
+            parser.parseData(result.getData())
+            return parser.getResults()
+
+        else:
+            self.handleHTTPError(request)
+            return None
+
+
     def deleteResource(self, rurl):

         assert(isinstance(rurl, URL))
-- 
1.8.1.6

Configure ssl through httpshandler

damien@… originally submitted this as ticket:907

  • Keywords: ssl, https, tls
  • Cc: damien@…

Hi,

the implementation of httpshandler.py is very basic: either the default python SSL options are suitable for the connection or the connection fails. For example, there is no way to specify where certificates can be found or that a particular certificate is white-listed (e.g., when self-signed).

cat command on a directory returns HTML page

mail@… originally submitted this as ticket:323


Since Linux upgrade to Lenny, the command 'cat' of 'CalDAVClientLibrary/runshell.py' returns HTML instead of an ics text if the argument is a directory.

E.g. calling 'cat calendars/users/me/calendar/f0e947e9.ics' works fine, but 'cat calendars/users/me/calendar' returns the same HTML page, as if you use a web browser (<html><head><title>Collection listing for /calendars/users...).

Test

gsnowkibo@… originally submitted this as ticket:378


First time here

CalDAVClientLibrary Kerberos authentication

rziai@… originally submitted this as ticket:334


CalDAVClientLibrary is the way to go for setting ACLs and various other things but it does not support Kerberos authentication. On the other hand, using Kerberos is the recommended authentication method of CalendarServer. The attached patch adds Kerberos support to the library, using the PyKerberos binding.

Sunbird fails to populate calendars

naoh123@… originally submitted this as ticket:348

  • Keywords: sunbird

First off, excellent project. It's been exciting following along the past year. I have been running the server on an Ubuntu 8.04 server for sometime, and can connect and manipulate fine using iCal clients; however, I have been unable to get Sunbird clients to cooperate. A little backgound: my setup is stock with the exception of the documentroot directive in caldavd.plist, and my pool of users (accounts.xml). When I add an account (any account) in sunbird I use the prescribed path, http://example.com:8008/calendars/user/jdoe/calendar, after which I am met with the user/pass prompt, credentials are accepted, but no calendars populate. The logs report the following ad nauseum:

2009-09-17 21:47:23-0500 [-] [caldav-8009] [PooledMemCacheProtocol,client] [twistedcaldav.extensions#info] PROPFIND /calendars/users/jdoe/calendar/ HTTP/1.1

2009-09-17 21:47:23-0500 [-] [caldav-8009] [AMP,client] [twistedcaldav.extensions#info] OPTIONS /calendars/users/jdoe/ HTTP/1.1

2009-09-17 21:47:23-0500 [-] [caldav-8009] [AMP,client] [twistedcaldav.extensions#info] HEAD /calendars/users/jdoe/calendar/ HTTP/1.1

2009-09-17 21:47:23-0500 [-] [caldav-8009] [PooledMemCacheProtocol,client] [twistedcaldav.directory.principal#error] No principal found for UID: admin

Any ideas what is going on here? Thanks!

'b' key issue in CalDAVClient

vivien@… originally submitted this as ticket:301

  • Version: trunk

Hi,

Trying to use CalDAVClientLibrary on a Debian Lenny server, I noticed that the CalDAVClient shell did not allow to enter the 'b' letter.

This issue is quite annoying especially when your user id contains a 'b' :)

I found that this issue was reported on the CalendarServer-users mailing list in April 2008 [1]. Unfortunately this bug does not seem to have been fixed as I am running a fresh SVN checkout [2]

A patch [3] was proposed in reply to this email fixing this issue. Applying it solved this 'b' key issue problem.

Thanks, Vivien

clientsession:syncCollection does not parse HTTP response properly

karra.etc@… originally submitted this as ticket:809


The code seems to assume that the status returned is an integer when in fact it is a String. We just need to use the appropriate parsing routines to fetch the status code as integer. The attached patch (in git patch format) does that:

From b64512376539c80be67b364bd671e83b9f0af4e1 Mon Sep 17 00:00:00 2001
From: Sriram Karra <[email protected]>
Date: Sat, 6 Apr 2013 17:38:20 +0530
Subject: [PATCH] PropFindResult.status obtained from server is not an integer;
 it is a status string that needs parsing.

---
 caldavclientlibrary/client/clientsession.py           | 7 +++++--
 caldavclientlibrary/protocol/webdav/propfindparser.py | 2 +-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/caldavclientlibrary/client/clientsession.py b/caldavclientlibrary/client/clientsession.py
index bc30e5b..e4c888d 100644
--- a/caldavclientlibrary/client/clientsession.py
+++ b/caldavclientlibrary/client/clientsession.py
@@ -20,6 +20,7 @@
 from caldavclientlibrary.protocol.carddav.makeaddressbook import MakeAddressBook
 from caldavclientlibrary.protocol.http.authentication.basic import Basic
 from caldavclientlibrary.protocol.http.authentication.digest import Digest
+from caldavclientlibrary.protocol.http.util import parseStatusLine
 from caldavclientlibrary.protocol.webdav.synccollection import SyncCollection
 from caldavclientlibrary.protocol.caldav.query import QueryVEVENTTimeRange
 try:
@@ -538,12 +539,14 @@ def syncCollection(self, rurl, synctoken, props=()):

             # Look at each propfind result
             for item in parser.getResults().itervalues():
+                # item is of type webdav.propfindparser.PropFindResult

                 # Get child element name (decode URL)
                 name = URL(url=item.getResource(), decode=True)
-                if item.status == 404:
+                status = parseStatusLine(item.status)
+                if status == 404:
                     removed.add(name)
-                elif item.status / 100 != 2:
+                elif status / 100 != 2:
                     other.add(name)
                 else:
                     changed.add(name)
diff --git a/caldavclientlibrary/protocol/webdav/propfindparser.py b/caldavclientlibrary/protocol/webdav/propfindparser.py
index d523997..ef5fe4a 100644
--- a/caldavclientlibrary/protocol/webdav/propfindparser.py
+++ b/caldavclientlibrary/protocol/webdav/propfindparser.py
@@ -29,7 +29,7 @@ class PropFindParser(MultiResponseParser):
     class PropFindResult(object):

         def __init__(self):
-            self.status = 200
+            self.status = "HTTP/1.1 200 OK"
             self.textProperties = {}
             self.hrefProperties = {}
             self.nodeProperties = {}
-- 
1.8.1.6

"./run -i" issue

rootsphere@… originally submitted this as ticket:485

  • Keywords: WebDAVBrowser.nib

I found caldavclientlibrary/ui/WebDAVBrowser.nib is not installed by ./run -i. Attached log file ends with

warning: install_data: setup script did not provide a directory for 'caldavclientlibrary/ui/WebDAVBrowser.nib' -- installing right in '../package/System/Library/Frameworks/Python.framework/Versions/2.6' error: can't copy 'caldavclientlibrary/ui/WebDAVBrowser.nib': doesn't exist or not a regular file

I don't know what script warns this line. Please fix this problem. I had compiled calendarserver on my MacPRO: MacOSX 10.6.8 with Xcode.

server is unusable if memcached goes down

rhodey@… originally submitted this as ticket:826


Darwin Calendar Server (release tag 5.2) becomes unusable when connection to the memcached server is lost. Darwin Calendar Server should simply query the datastore and directory services without relying on cache while attempting to reconnect with memcached.

can't create a collection with curl

antpaz@… originally submitted this as ticket:541


Curl can be used to create a calendar using curl -k -X MKCALENDAR -u usr1 https://localhost:8443/calendars/users/usr1/newcal/

However this is a VEVENT calendar.

To create a VTODO calendar I used curl -k -X MKCALENDAR --data "<C:supported-calendar-component-set xmlns:C='urn:ietf:params:xml:ns:caldav'><C:comp name='VTODO'/></C:supported-calendar-component-set>" -u usr1 https://localhost:8443/calendars/users/usr1/newcal2/

which fails with

<html><head><title>Unsupported Media Type</title></head><body><h1>Unsupported Media Type</h1><p>Non-mkcalendar element in MKCALENDAR request body: {urn:ietf:params:xml:ns:caldav}supported-calendar-component-sets</p></body></html>

I am newbie with DCS then I may be missing something on the above command.

Make updates to documents possible using clientsession writeData()

karra.etc@… originally submitted this as ticket:805

  • Keywords: if-match, update

To update an existing document on the server an If-Match header needs to be included in the request. There is no way to do this with the existing writeData() method.

The patch below does this:

@@ -692,14 +692,14 @@ def readData(self, rurl):
         return dout.getData(), etag


-    def writeData(self, rurl, data, contentType):
+    def writeData(self, rurl, data, contentType, etag=None):

         assert(isinstance(rurl, URL))

         # Create WebDAV PUT
         request = Put(self, rurl.relativeURL())
         dout = RequestDataString(data, contentType)
-        request.setData(dout, None)
+        request.setData(dout, None, etag=etag)

         # Process it
         self.runSession(request)

Proxy list not updating when read/write proxy added

mail@… originally submitted this as ticket:268


When using the command line shell to add a read/write proxy the list of proxies isn't updated correctly. Reproduce as follows...

(assuming logged in)
proxies -i
list
add -w
<add a proxy>
list
[ proxy will not be shown in list]
add -w
[ proxy will now be shown ]
q <don't add a proxy, just quit>
list
[ proxy will now be shown in list ]

This works OK when adding a read-only proxy.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.