diff mupdf-source/thirdparty/curl/src/tool_cb_wrt.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/thirdparty/curl/src/tool_cb_wrt.c	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,218 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_cb_wrt.h"
+#include "tool_operate.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* create a local file for writing, return TRUE on success */
+bool tool_create_output_file(struct OutStruct *outs)
+{
+  struct GlobalConfig *global = outs->config->global;
+  FILE *file;
+
+  if(!outs->filename || !*outs->filename) {
+    warnf(global, "Remote filename has no length!\n");
+    return FALSE;
+  }
+
+  if(outs->is_cd_filename) {
+    /* don't overwrite existing files */
+    file = fopen(outs->filename, "rb");
+    if(file) {
+      fclose(file);
+      warnf(global, "Refusing to overwrite %s: %s\n", outs->filename,
+            strerror(EEXIST));
+      return FALSE;
+    }
+  }
+
+  /* open file for writing */
+  file = fopen(outs->filename, "wb");
+  if(!file) {
+    warnf(global, "Failed to create the file %s: %s\n", outs->filename,
+          strerror(errno));
+    return FALSE;
+  }
+  outs->s_isreg = TRUE;
+  outs->fopened = TRUE;
+  outs->stream = file;
+  outs->bytes = 0;
+  outs->init = 0;
+  return TRUE;
+}
+
+/*
+** callback for CURLOPT_WRITEFUNCTION
+*/
+
+size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
+{
+  size_t rc;
+  struct per_transfer *per = userdata;
+  struct OutStruct *outs = &per->outs;
+  struct OperationConfig *config = outs->config;
+  size_t bytes = sz * nmemb;
+  bool is_tty = config->global->isatty;
+#ifdef WIN32
+  CONSOLE_SCREEN_BUFFER_INFO console_info;
+  intptr_t fhnd;
+#endif
+
+  /*
+   * Once that libcurl has called back tool_write_cb() the returned value
+   * is checked against the amount that was intended to be written, if
+   * it does not match then it fails with CURLE_WRITE_ERROR. So at this
+   * point returning a value different from sz*nmemb indicates failure.
+   */
+  const size_t failure = bytes ? 0 : 1;
+
+#ifdef DEBUGBUILD
+  {
+    char *tty = curlx_getenv("CURL_ISATTY");
+    if(tty) {
+      is_tty = TRUE;
+      curl_free(tty);
+    }
+  }
+
+  if(config->show_headers) {
+    if(bytes > (size_t)CURL_MAX_HTTP_HEADER) {
+      warnf(config->global, "Header data size exceeds single call write "
+            "limit!\n");
+      return failure;
+    }
+  }
+  else {
+    if(bytes > (size_t)CURL_MAX_WRITE_SIZE) {
+      warnf(config->global, "Data size exceeds single call write limit!\n");
+      return failure;
+    }
+  }
+
+  {
+    /* Some internal congruency checks on received OutStruct */
+    bool check_fails = FALSE;
+    if(outs->filename) {
+      /* regular file */
+      if(!*outs->filename)
+        check_fails = TRUE;
+      if(!outs->s_isreg)
+        check_fails = TRUE;
+      if(outs->fopened && !outs->stream)
+        check_fails = TRUE;
+      if(!outs->fopened && outs->stream)
+        check_fails = TRUE;
+      if(!outs->fopened && outs->bytes)
+        check_fails = TRUE;
+    }
+    else {
+      /* standard stream */
+      if(!outs->stream || outs->s_isreg || outs->fopened)
+        check_fails = TRUE;
+      if(outs->alloc_filename || outs->is_cd_filename || outs->init)
+        check_fails = TRUE;
+    }
+    if(check_fails) {
+      warnf(config->global, "Invalid output struct data for write callback\n");
+      return failure;
+    }
+  }
+#endif
+
+  if(!outs->stream && !tool_create_output_file(outs))
+    return failure;
+
+  if(is_tty && (outs->bytes < 2000) && !config->terminal_binary_ok) {
+    /* binary output to terminal? */
+    if(memchr(buffer, 0, bytes)) {
+      warnf(config->global, "Binary output can mess up your terminal. "
+            "Use \"--output -\" to tell curl to output it to your terminal "
+            "anyway, or consider \"--output <FILE>\" to save to a file.\n");
+      config->synthetic_error = ERR_BINARY_TERMINAL;
+      return failure;
+    }
+  }
+
+#ifdef WIN32
+  fhnd = _get_osfhandle(fileno(outs->stream));
+  if(isatty(fileno(outs->stream)) &&
+     GetConsoleScreenBufferInfo((HANDLE)fhnd, &console_info)) {
+    DWORD in_len = (DWORD)(sz * nmemb);
+    wchar_t* wc_buf;
+    DWORD wc_len;
+
+    /* calculate buffer size for wide characters */
+    wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len,  NULL, 0);
+    wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
+    if(!wc_buf)
+      return failure;
+
+    /* calculate buffer size for multi-byte characters */
+    wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len, wc_buf, wc_len);
+    if(!wc_len) {
+      free(wc_buf);
+      return failure;
+    }
+
+    if(!WriteConsoleW(
+        (HANDLE) fhnd,
+        wc_buf,
+        wc_len,
+        &wc_len,
+        NULL)) {
+      free(wc_buf);
+      return failure;
+    }
+    free(wc_buf);
+    rc = bytes;
+  }
+  else
+#endif
+    rc = fwrite(buffer, sz, nmemb, outs->stream);
+
+  if(bytes == rc)
+    /* we added this amount of data to the output */
+    outs->bytes += bytes;
+
+  if(config->readbusy) {
+    config->readbusy = FALSE;
+    curl_easy_pause(per->curl, CURLPAUSE_CONT);
+  }
+
+  if(config->nobuffer) {
+    /* output buffering disabled */
+    int res = fflush(outs->stream);
+    if(res)
+      return failure;
+  }
+
+  return rc;
+}