Repository: astropy/astroquery

Issue:
SDSS.query_crossid doesn't work for DR<10
Run into this with the test suite, didn't investigate in detail. It likely just needs the URLs fixed. Could you maybe have a look @weaverba137? 

```
In [1]: from astroquery import sdss

In [2]: from astropy.coordinates import SkyCoord
   ...: from astropy.table import Table

In [3]: coords = SkyCoord('0h8m05.63s +14d50m23.3s')

In [4]: sdss.SDSS.query_crossid(coords,data_release=9)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-6418e02a3b0b> in <module>
----> 1 sdss.SDSS.query_crossid(coords,data_release=9)

~/munka/devel/worktrees/astroquery/testings/astroquery/utils/class_or_instance.py in f(*args, **kwds)
     23         def f(*args, **kwds):
     24             if obj is not None:
---> 25                 return self.fn(obj, *args, **kwds)
     26             else:
     27                 return self.fn(cls, *args, **kwds)

~/munka/devel/worktrees/astroquery/testings/astroquery/utils/process_asyncs.py in newmethod(self, *args, **kwargs)
     27             if kwargs.get('get_query_payload') or kwargs.get('field_help'):
     28                 return response
---> 29             result = self._parse_result(response, verbose=verbose)
     30             self.table = result
     31             return result

~/munka/devel/worktrees/astroquery/testings/astroquery/sdss/core.py in _parse_result(self, response, verbose)
    871                                           names=True, dtype=None,
    872                                           delimiter=',', skip_header=skip_header,
--> 873                                           comments='#'))
    874 
    875         if len(arr) == 0:

~/.pyenv/versions/3.7.9/lib/python3.7/site-packages/numpy/lib/npyio.py in genfromtxt(fname, dtype, comments, delimiter, skip_header, skip_footer, converters, missing_values, filling_values, usecols, names, excludelist, deletechars, replace_space, autostrip, case_sensitive, defaultfmt, unpack, usemask, loose, invalid_raise, max_rows, encoding)
   2078             # Raise an exception ?
   2079             if invalid_raise:
-> 2080                 raise ValueError(errmsg)
   2081             # Issue a warning ?
   2082             else:

ValueError: Some errors were detected !
    Line #12 (got 3 columns instead of 1)
    Line #32 (got 5 columns instead of 1)
    Line #34 (got 3 columns instead of 1)
```

Response: 

```
<!DOCTYPE html>
<html>
    <head>
        <title>The resource cannot be found.</title>
        <meta name="viewport" content="width=device-width" />
        <style>
         body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;} 
         p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
         b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
         H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
         H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
         pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
         .marker {font-weight: bold; color: black;text-decoration: none;}
         .version {color: gray;}
         .error {margin-bottom: 10px;}
         .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:pointer; }
         @media screen and (max-width: 639px) {
          pre { width: 440px; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
         }
         @media screen and (max-width: 479px) {
          pre { width: 280px; }
         }
        </style>
    </head>

    <body bgcolor="white">

            <span><H1>Server Error in '/dr9' Application.<hr width=100% size=1 color=silver></H1>

            <h2> <i>The resource cannot be found.</i> </h2></span>

            <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

            <b> Description: </b>HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. &nbsp;Please review the following URL and make sure that it is spelled correctly.
            <br><br>

            <b> Requested URL: </b>/dr9/en/tools/crossid/x_crossid.aspx<br><br>

            </font>

    </body>
</html>
```

Comments:

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index c82d3a62..d834e8b4 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -58,6 +58,7 @@ sdss
 
 - Fix ``query_crossid`` to be able to query larger list of coordinates. [#2305]
 
+- Fix ``query_crossid`` for very old data releases (< DR10). [#2318]
 
 
 Infrastructure, Utility and Other Changes and Additions
diff --git a/astroquery/casda/core.py b/astroquery/casda/core.py
index e021369e..223f9fcf 100644
--- a/astroquery/casda/core.py
+++ b/astroquery/casda/core.py
@@ -241,7 +241,7 @@ class CasdaClass(BaseQuery):
         filenames = []
         for url in urls:
             parseResult = urlparse(url)
-            local_filename = os.path.basename(parseResult.path)
+            local_filename = unquote(os.path.basename(parseResult.path))
             if os.name == 'nt':
                 # Windows doesn't allow special characters in filenames like
                 # ":" so replace them with an underscore
diff --git a/astroquery/sdss/core.py b/astroquery/sdss/core.py
index 293a7ae4..975e919e 100644
--- a/astroquery/sdss/core.py
+++ b/astroquery/sdss/core.py
@@ -32,7 +32,8 @@ class SDSSClass(BaseQuery):
     QUERY_URL_SUFFIX_DR_OLD = '/dr{dr}/en/tools/search/x_sql.asp'
     QUERY_URL_SUFFIX_DR_10 = '/dr{dr}/en/tools/search/x_sql.aspx'
     QUERY_URL_SUFFIX_DR_NEW = '/dr{dr}/en/tools/search/x_results.aspx'
-    XID_URL_SUFFIX_OLD = '/dr{dr}/en/tools/crossid/x_crossid.aspx'
+    XID_URL_SUFFIX_OLD = '/dr{dr}/en/tools/crossid/x_crossid.asp'
+    XID_URL_SUFFIX_DR_10 = '/dr{dr}/en/tools/crossid/x_crossid.aspx'
     XID_URL_SUFFIX_NEW = '/dr{dr}/en/tools/search/X_Results.aspx'
     IMAGING_URL_SUFFIX = ('{base}/dr{dr}/{instrument}/photoObj/frames/'
                           '{rerun}/{run}/{camcol}/'
@@ -123,7 +124,7 @@ class SDSSClass(BaseQuery):
                 raise TypeError("radius should be either Quantity or "
                                 "convertible to float.")
 
-        sql_query = 'SELECT '
+        sql_query = 'SELECT\r\n'  # Older versions expect the CRLF to be there.
 
         if specobj_fields is None:
             if photoobj_fields is None:
@@ -1078,8 +1079,10 @@ class SDSSClass(BaseQuery):
         return url
 
     def _get_crossid_url(self, data_release):
-        if data_release < 11:
+        if data_release < 10:
             suffix = self.XID_URL_SUFFIX_OLD
+        elif data_release == 10:
+            suffix = self.XID_URL_SUFFIX_DR_10
         else:
             suffix = self.XID_URL_SUFFIX_NEW
 


Test patch:
diff --git a/astroquery/casda/tests/test_casda.py b/astroquery/casda/tests/test_casda.py
index a868ed9b..fe74075f 100644
--- a/astroquery/casda/tests/test_casda.py
+++ b/astroquery/casda/tests/test_casda.py
@@ -284,7 +284,8 @@ def test_stage_data(patch_get):
 
 def test_download_file(patch_get):
     urls = ['https://ingest.pawsey.org/bucket_name/path/askap_img.fits?security=stuff',
-            'http://casda.csiro.au/download/web/111-000-111-000/askap_img.fits.checksum']
+            'http://casda.csiro.au/download/web/111-000-111-000/askap_img.fits.checksum',
+            'https://ingest.pawsey.org.au/casda-prd-as110-01/dc52217/primary_images/RACS-DR1_0000%2B18A.fits?security=stuff']
     casda = Casda('user', 'password')
 
     # skip the actual downloading of the file
@@ -294,3 +295,4 @@ def test_download_file(patch_get):
     filenames = casda.download_files(urls)
     assert filenames[0].endswith('askap_img.fits')
     assert filenames[1].endswith('askap_img.fits.checksum')
+    assert filenames[2].endswith('RACS-DR1_0000+18A.fits')
diff --git a/astroquery/sdss/tests/test_sdss.py b/astroquery/sdss/tests/test_sdss.py
index bb92c01b..38b7d1d4 100644
--- a/astroquery/sdss/tests/test_sdss.py
+++ b/astroquery/sdss/tests/test_sdss.py
@@ -136,7 +136,9 @@ def url_tester(data_release):
 
 
 def url_tester_crossid(data_release):
-    if data_release < 11:
+    if data_release < 10:
+        baseurl = 'http://skyserver.sdss.org/dr{}/en/tools/crossid/x_crossid.asp'
+    if data_release == 10:
         baseurl = 'http://skyserver.sdss.org/dr{}/en/tools/crossid/x_crossid.aspx'
     if data_release == 11:
         return
diff --git a/astroquery/sdss/tests/test_sdss_remote.py b/astroquery/sdss/tests/test_sdss_remote.py
index 723195f2..26251eaf 100644
--- a/astroquery/sdss/tests/test_sdss_remote.py
+++ b/astroquery/sdss/tests/test_sdss_remote.py
@@ -174,8 +174,7 @@ class TestSDSSRemote:
         assert query1.colnames == ['r', 'psfMag_r']
         assert query2.colnames == ['ra', 'dec', 'r']
 
-    # crossid doesn't work for DR<10, remove limitation once #2303 is fixed
-    @pytest.mark.parametrize("dr", dr_list[2:])
+    @pytest.mark.parametrize("dr", dr_list)
     def test_query_crossid(self, dr):
         query1 = sdss.SDSS.query_crossid(self.coords, data_release=dr)
         query2 = sdss.SDSS.query_crossid([self.coords, self.coords])
@@ -185,8 +184,7 @@ class TestSDSSRemote:
         assert isinstance(query2, Table)
         assert query2['objID'][0] == query1['objID'][0] == query2['objID'][1]
 
-    # crossid doesn't work for DR<10, remove limitation once #2303 is fixed
-    @pytest.mark.parametrize("dr", dr_list[2:])
+    @pytest.mark.parametrize("dr", dr_list)
     def test_spectro_query_crossid(self, dr):
         query1 = sdss.SDSS.query_crossid(self.coords,
                                          specobj_fields=['specObjID', 'z'],