Repository: python-pillow/Pillow

Issue:
Windows build from source cannot find sourceforge dependencies
<!--
Thank you for reporting an issue.

Follow these guidelines to ensure your issue is handled properly.

If you have a ...

1.  General question: consider asking the question on Stack Overflow
    with the python-imaging-library tag:

    * https://stackoverflow.com/questions/tagged/python-imaging-library

    Do not ask a question in both places.

    If you think you have found a bug or have an unexplained exception
    then file a bug report here.

2.  Bug report: include a self-contained, copy-pastable example that
    generates the issue if possible. Be concise with code posted.
    Guidelines on how to provide a good bug report:

    * https://stackoverflow.com/help/mcve

    Bug reports which follow these guidelines are easier to diagnose,
    and are often handled much more quickly.

3.  Feature request: do a quick search of existing issues
    to make sure this has not been asked before.

We know asking good questions takes effort, and we appreciate your time.
Thank you.
-->

### What did you do?
Attempted to build Pillow from source on Windows
### What did you expect to happen?
Build should run OK
### What actually happened?
`winbuild\build_prepare.py` could not download dependencies because `SF_MIRROR` `https://iweb.dl.sourceforge.net` is not online.
### What are your OS, Python and Pillow versions?

* OS: Windows 10 Pro
* Python: 3.10.4
* Pillow: latest main source

<!--
Please include **code** that reproduces the issue and whenever possible, an **image** that demonstrates the issue. Please upload images to GitHub, not to third-party file hosting sites. If necessary, add the image to a zip or tar archive.

The best reproductions are self-contained scripts with minimal dependencies. If you are using a framework such as Plone, Django, or Buildout, try to replicate the issue just using Pillow.
-->
```
Fetching https://iweb.dl.sourceforge.net/project/libjpeg-turbo/2.1.3/libjpeg-turbo-2.1.3.tar.gz (attempt 3)...
Traceback (most recent call last):
  File "E:\r\pil\PILdev\0530\Pillow-main\winbuild\build_prepare.py", line 588, in <module>
    build_dep_all()
  File "E:\r\pil\PILdev\0530\Pillow-main\winbuild\build_prepare.py", line 466, in build_dep_all
    script = build_dep(dep_name)
  File "E:\r\pil\PILdev\0530\Pillow-main\winbuild\build_prepare.py", line 431, in build_dep
    extract_dep(dep["url"], dep["filename"])
  File "E:\r\pil\PILdev\0530\Pillow-main\winbuild\build_prepare.py", line 391, in extract_dep
    raise RuntimeError(ex)
RuntimeError: <urlopen error [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond>
```

I find that the line `SF_MIRROR = "https://iweb.dl.sourceforge.net"` is the culprit.

Also, `ping https://iweb.dl.sourceforge.net` gets me:
`Ping request could not find host https://iweb.dl.sourceforge.net. Please check the name and try again.`

I changed to `SF_MIRROR = "https://cytranet.dl.sourceforge.net"` and it works.

I don't know if `iweb` is down for good or not. Maybe  `build_prepare.py` can be modified to have fallback mirrors, or somehow detect which of several SF mirrors are up?


Discussion:
Can we use the link from https://sourceforge.net/projects/libjpeg-turbo/files/2.1.3/ ?

That is:

`https://sourceforge.net/projects/libjpeg-turbo/files/2.1.3/libjpeg-turbo-2.1.3.tar.gz/download`

That should do auto-mirror selection. For example, I did a wget of that from here in Finland and it selected a mirror from neighbouring Sweden.

https://altushost-swe.dl.sourceforge.net/project/libjpeg-turbo/2.1.3/libjpeg-turbo-2.1.3.tar.gz 

I tried `wget https://sourceforge.net/projects/libjpeg-turbo/files/2.1.3/libjpeg-turbo-2.1.3.tar.gz/download` just now (`--version` shows `GNU Wget 1.21.2 built on mingw32`) and just got the HTML download page. No actual package downloaded.
Also retried `ping https://iweb.dl.sourceforge.net` and now get:
```
Pinging sourceforge.mirror.iweb.ca [192.175.120.182] with 32 bytes of data:
Reply from 184.107.1.171: Destination host unreachable.
```
not quite the same as before but still no joy.
I do not see `iweb` on the [mirrors list](https://sourceforge.net/p/forge/documentation/Mirrors/).

The [SourceForge documentation](https://sourceforge.net/p/forge/documentation/Downloading%20files%20via%20the%20command%20line/) says wget downloads with automatic mirror should be supported. The website being returned appears to be a HTTP 302 redirect, which does seem to be supported by `urllib.request` used in `build_prepare.py`.

```python
>>> import urllib.request
>>> len(urllib.request.urlopen("https://sourceforge.net/projects/libjpeg-turbo/files/2.1.3/libjpeg-turbo-2.1.3.tar.gz/download").read())
2260756
```

Resolving patch:
diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py
--- a/winbuild/build_prepare.py
+++ b/winbuild/build_prepare.py
@@ -89,7 +89,7 @@ def cmd_msbuild(
     )
 
 
-SF_MIRROR = "https://iweb.dl.sourceforge.net"
+SF_PROJECTS = "https://sourceforge.net/projects"
 
 architectures = {
     "x86": {"vcvars_arch": "x86", "msbuild_arch": "Win32"},
@@ -107,7 +107,8 @@ def cmd_msbuild(
 # dependencies, listed in order of compilation
 deps = {
     "libjpeg": {
-        "url": SF_MIRROR + "/project/libjpeg-turbo/2.1.3/libjpeg-turbo-2.1.3.tar.gz",
+        "url": SF_PROJECTS
+        + "/libjpeg-turbo/files/2.1.3/libjpeg-turbo-2.1.3.tar.gz/download",
         "filename": "libjpeg-turbo-2.1.3.tar.gz",
         "dir": "libjpeg-turbo-2.1.3",
         "build": [
@@ -172,7 +173,7 @@ def cmd_msbuild(
         "libs": [r"output\release-static\{architecture}\lib\*.lib"],
     },
     "libpng": {
-        "url": SF_MIRROR + "/project/libpng/libpng16/1.6.37/lpng1637.zip",
+        "url": SF_PROJECTS + "/libpng/files/libpng16/1.6.37/lpng1637.zip/download",
         "filename": "lpng1637.zip",
         "dir": "lpng1637",
         "build": [
@@ -221,7 +222,7 @@ def cmd_msbuild(
         # "bins": [r"objs\{msbuild_arch}\Release\freetype.dll"],
     },
     "lcms2": {
-        "url": SF_MIRROR + "/project/lcms/lcms/2.13/lcms2-2.13.1.tar.gz",
+        "url": SF_PROJECTS + "/lcms/files/lcms/2.13/lcms2-2.13.1.tar.gz/download",
         "filename": "lcms2-2.13.1.tar.gz",
         "dir": "lcms2-2.13.1",
         "patch": {


Test patch: