octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

front-end of libcurl


From: Alexander Barth
Subject: front-end of libcurl
Date: Wed, 27 Sep 2006 12:08:23 -0400
User-agent: Thunderbird 1.5.0.7 (X11/20060913)

Hi all,

I wrote a front-end of libcurl to download files from a web or ftp server. This 
syntax is quite
straight forward:

download('url','localfile');

The error handling is similar to the copyfile function in matlab.
The attached source can be compiled with:

mkoctfile download.cc `curl-config --cflags --libs`

This function may be useful for the package manager. Like rpm is able to 
install a package from a
web-server (for example: rpm -ihv http://example.com/package.rpm), a similar 
functionality could be
added to pkg.m

I would be glad if this function would be considered for inclusion in octave or 
octave-forge. If
octave-forge turns out to be the appropriate place, I can add it myself, maybe 
in main/miscellaneous.

Cheers,
Alex


-- 
_______________________________________________________________

  Alexander Barth

  Ocean Circulation Group
  University of South Florida
  College of Marine Science
  140 Seventh Avenue South
  St. Petersburg, Florida  33701
  USA

  Phone: +1-727-553-3508     FAX:   +1-727-553-1189

_______________________________________________________________


/*
  download, a curl front-end for octave 
  Copyright (C) 2006 Alexander Barth <address@hidden>

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
*/

/*
  Compile with:
  mkoctfile download.cc `curl-config --cflags --libs`
*/

#include <octave/oct.h>

#include <stdio.h>
#include <string>

#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

using namespace std;

struct FileStruct {
  string filename;
  FILE *stream;
};

// write callback function

int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
  struct FileStruct *out=(struct FileStruct *)stream;
  if(out && !out->stream) {
    // printf("file %s\n",out->filename.c_str());

    // open file for writing 

    out->stream=fopen(out->filename.c_str(), "wb");
    if(!out->stream)
      return -1; // failure, can't open file to write 
  }
  return fwrite(buffer, size, nmemb, out->stream);
}

// progress callback function

int my_progress_func(char *url,
                     double dltotal,
                     double dlnow,
                     double ultotal,
                     double ulnow)
{
  // macro that picks up Ctrl-C signalling
  OCTAVE_QUIT;

  printf("\r%s: ",url);

  if (dltotal != 0) {
    printf("%4.1f %%",dlnow*100.0/dltotal);
  }

  fflush(stdout);
  return 0;
}

DEFUN_DLD (download, args, nargout,
           "-*- texinfo -*-\n\
@deftypefn {Loadable Function} {} download(@var{URL},@var{localfile}) \n\
@deftypefnx {Loadable Function} address@hidden,@var{message] =} 
download(@var{url},@var{localfile})} \n\
Downloads a remote file specified by its @var{URL} and saves it as 
@var{localfile}. \n\n\
Example: \n\
@example \n\
download('ftp://ftp.octave.org/pub/octave/README','README.txt'); \n\
@end example \n\n\
The variable @var{success} is 1 if the download was successful, otherwise it \n\
is 0 in which case @var{message} contains the error message. If no output 
argument \n\
is specified and if an error occurs, then the error is signaled throught \n\
octave's error handling mechanism. \n\
\n\
This function uses libcurl. Curl supports, among others, the HTTP, FTP and FILE 
protocols. \n\
Username and password may be specified in the URL, for example: \n\
@example \n\
download('http://username:password@@example.com/file.txt','file.txt'); \n\
@end example \n\
@end deftypefn")
{
  CURL *curl;
  // curl return code
  CURLcode res; 
  // argument for my_fwrite callback function
  struct FileStruct filestruct;
  // octave's return value
  octave_value_list retval;

  // verify arguments
  if (args.length() != 2) {
    print_usage();
    return octave_value();
  }

  if (!args(0).is_string() || !args(1).is_string()) {
    error("download only expects string arguments");
    return octave_value();
  }

  string url = args(0).string_value();

  // name to store the file if download is succesful 
  filestruct.filename = args(1).string_value();
  filestruct.stream = NULL;

  curl_global_init(CURL_GLOBAL_DEFAULT);

  curl = curl_easy_init();
  if (curl) {
    curl_easy_setopt(curl, CURLOPT_URL,url.c_str());
    
    // Define our callback to get called when there's data to be written
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
    // Set a pointer to our struct to pass to the callback
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &filestruct);

    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
    curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, url.c_str());
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
    // Switch on full protocol/debug output
    // curl_easy_setopt(curl, CURLOPT_VERBOSE, true);

    res = curl_easy_perform(curl);
    printf("\n");

    // always cleanup
    curl_easy_cleanup(curl);

  } else {
    res = CURLE_FAILED_INIT;
  }

  if(filestruct.stream)
    fclose(filestruct.stream); // close the local file

  curl_global_cleanup();


  // return error code if desired

  if(nargout == 0 & res != CURLE_OK) 
    error("curl: %s\n", curl_easy_strerror(res));
  else {
    retval(0) = res == CURLE_OK;
    // return empty string if no error occured
    retval(1) = string(res == CURLE_OK ? "" : curl_easy_strerror(res));
  }

  return retval;
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]