Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save eusonlito/26095c2e903a02a3b8011e2a923b4b66 to your computer and use it in GitHub Desktop.
Save eusonlito/26095c2e903a02a3b8011e2a923b4b66 to your computer and use it in GitHub Desktop.
Download all your file from Basecamp Classic
<?php
define('BASE', './basecamp'); // Folder to store files (must be writable)
define('BASECAMP_URL', '[YOUR BASECAMP URL HERE]'); // e.g. https://stelabouras.basecamphq.com/ (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_HTTPAUTH, CURLAUTH_BASIC);
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)) {
continue;
}
$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";
continue;
}
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