Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Download all your file from Basecamp Classic
define('BASE', './basecamp'); // Folder to store files (must be writable)
define('BASECAMP_URL', '[YOUR BASECAMP URL HERE]'); // e.g. (Don't forget the trailing slash!)
define('BASECAMP_KEY', '[YOUR API KEY HERE]'); // e.g. one huge string (found in 'My info' in the Authentication tokens section)
define('COOKIE', tempnam(sys_get_temp_dir(), uniqid()));
function curl($url, $prefix = true)
$url = ($prefix ? BASECAMP_URL : '').$url;
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPGET, true);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
if ($prefix) {
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Accept: application/xml', 'Content-Type: application/xml']);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_USERPWD, BASECAMP_API.':X');
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_COOKIESESSION, true);
curl_setopt($curl, CURLOPT_COOKIEJAR, COOKIE);
curl_setopt($curl, CURLOPT_COOKIEFILE, COOKIE);
curl_setopt($curl, CURLOPT_AUTOREFERER, true);
curl_setopt($curl, CURLOPT_REFERER, $url);
echo "Downloading {$url}\n";
curl_setopt($curl, CURLOPT_URL, $url);
$response = curl_exec($curl);
return $prefix ? simplexml_load_string($response) : $response;
function remote($project, array $file, array $files)
$location = BASE.'/'.$project->name.'/'.$file['filename'];
if (in_array($file['filename'], $files)) {
$location .= '-'.uniqid(rand());
if (!empty($file['extension'])) {
$location .= '.'.$file['extension'];
return $location;
$projects = curl('projects.xml');
$projectsTotal = count($projects);
$projectsCounter = 0;
foreach ($projects->project as $project) {
echo "\nSaving attachments for project {$project->name} (".(++$projectsCounter)."/{$projectsTotal})\n";
if (!is_dir(BASE.'/'.$project->name)) {
mkdir(BASE.'/'.$project->name, 0755, true);
$files = array();
$page = 0;
do {
$attachments = curl('projects/'.$project->id.'/attachments.xml?n='.$page);
if (empty($attachments->attachment)) {
$attachmentsTotal = count($attachments->attachment);
$attachmentsCounter = 0;
$page += 100;
foreach ($attachments->attachment as $attachment) {
$file = pathinfo($attachment->name);
$storage = remote($project, $file, $files);
if (is_file($storage)) {
echo "Already downloaded file {$attachment->name} on {$storage} (".(++$attachmentsCounter)."/{$attachmentsTotal})\n";
file_put_contents($storage, curl($attachment->{'download-url'}, false));
$files[] = $file['filename'];
echo "Saving file {$attachment->name} on {$storage} (".(++$attachmentsCounter)."/{$attachmentsTotal})\n";
} while (count($attachments->attachment) === 100);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment