A client asked me to develop a simple method for protecting a download (or digital product) by generating a unique URL that can be distributed to authorized users via email. The URL would contain a key that would be valid for a certain amount of time and number of downloads. The key will become invalid once the first of those conditions is exceeded. The idea is that distributing the unique URL will limit unauthorized downloads resulting from the sharing of legitimate download links.
In addition, once the key has been validated, the download starts immediately, preventing the visitor from seeing the actual location of the download file. What’s more, the file name of the download in the “Save as” dialogue box isn’t necessarily the same as the file name of the file on the server, making the file itself pretty much undiscoverable.
How it works
There are five main components to this system:
- the MySQL database that holds each key, the key creation time, and the number of times the key has been used
- the downloadkey.php page that generates the unique keys and corresponding URLs
- the download.php page that accepts the key, verifies its validity, and either initiates the download or rejects the key as invalid
- a dbconnect.php file that contains the link to the database and which is included into both of the other PHP files
- the download .zip file that is to be protected
Place all three PHP scripts and the .zip file into the same directory on your server.
The MySQL database
Using whatever method you’re comfortable with, create a new MySQL database named “download” and add the following table:
CREATE TABLE `downloadkey` ( `uniqueid` varchar(255) NOT NULL default '', `timestamp` varchar(255) NOT NULL default '', `downloads` varchar(255) NOT NULL default '0', PRIMARY KEY (uniqueid) );
The downloadkey.php page
This page generates the key, creates a URL containing the key, and writes the key to the database. Never give out the location of this page – this is for only you to access.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Download Key Generator</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <meta name="author" content="//ardamis.com/" /> <style type="text/css"> #wrapper { font: 15px Verdana, Arial, Helvetica, sans-serif; margin: 40px 100px 0 100px; } .box { border: 1px solid #e5e5e5; padding: 6px; background: #f5f5f5; } </style> </head> <body> <div id="wrapper"> <h2>Download Key Generator</h2> <?php // A script to generate unique download keys for the purpose of protecting downloadable goods require ('dbconnect.php'); if(empty($_SERVER['REQUEST_URI'])) { $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME']; } // Strip off query string so dirname() doesn't get confused $url = preg_replace('/\?.*$/', '', $_SERVER['REQUEST_URI']); $folderpath = 'http://'.$_SERVER['HTTP_HOST'].'/'.ltrim(dirname($url), '/').'/'; // Generate the unique download key $key = uniqid(md5(rand())); // echo "key: " . $key . "<br />"; // Get the activation time $time = date('U'); // echo "time: " . $time . "<br />"; // Generate the link echo "<p>Here's a new download link:</p>"; echo "<p><span class=\"box\">" . $folderpath . "download.php?id=" . $key . "</span></p>"; // Write the key and activation time to the database as a new row $registerid = mysql_query("INSERT INTO downloadkey (uniqueid,timestamp) VALUES(\"$key\",\"$time\")") or die(mysql_error()); ?> <p> </p> <p>Each time you refresh this page, a unique download key is generated and saved to a database. Copy and paste the download link into an email to allow the recipient access to the download.</p> <p>This key will be valid for a certain amount of time and number of downloads, which can be set in the download.php script. The key will expire and no longer be usable when the first of these conditions is exceeded.</p> <p>The download page has been written to force the browser to begin the download immediately. This will prevent the recipient of the email from discovering the location of the actual download file.</p> </div> </body> </html>
The download.php page
The URL generated by downloadkey.php points to this page. It contains the key validation script and then forces the browser to begin the download if it finds the key is valid.
<?php // Set the maximum number of downloads (actually, the number of page loads) $maxdownloads = "2"; // Set the key's viable duration in seconds (86400 seconds = 24 hours) $maxtime = "86400"; require ('dbconnect.php'); if(get_magic_quotes_gpc()) { $id = stripslashes($_GET['id']); }else{ $id = $_GET['id']; } // Get the key, timestamp, and number of downloads from the database $query = sprintf("SELECT * FROM downloadkey WHERE uniqueid= '%s'", mysql_real_escape_string($id, $link)); $result = mysql_query($query) or die(mysql_error()); $row = mysql_fetch_array($result); if (!$row) { echo "The download key you are using is invalid."; }else{ $timecheck = date('U') - $row['timestamp']; if ($timecheck >= $maxtime) { echo "This key has expired (exceeded time allotted).<br />"; }else{ $downloads = $row['downloads']; $downloads += 1; if ($downloads > $maxdownloads) { echo "This key has expired (exceeded allowed downloads).<br />"; }else{ $sql = sprintf("UPDATE downloadkey SET downloads = '".$downloads."' WHERE uniqueid= '%s'", mysql_real_escape_string($id, $link)); $incrementdownloads = mysql_query($sql) or die(mysql_error()); // Debug echo "Key validated."; // Force the browser to start the download automatically /* Variables: $file = real name of actual download file on the server $filename = new name of local download file - this is what the visitor's file will actually be called when he/she saves it */ ob_start(); $mm_type="application/octet-stream"; $file = "actual_download.zip"; $filename = "bogus_download_name.zip"; header("Cache-Control: public, must-revalidate"); header("Pragma: no-cache"); header("Content-Type: " . $mm_type); header("Content-Length: " .(string)(filesize($file)) ); header('Content-Disposition: attachment; filename="'.$filename.'"'); header("Content-Transfer-Encoding: binary\n"); ob_end_clean(); readfile($file); } } } ?>
The dbconnect.php script (database connection)
This is the PHP include referenced by both scripts that contains the database link.
<?php // Connect to database "download" using: dbname , username , password $link = mysql_connect('localhost', 'root', '') or die("Could not connect: " . mysql_error()); mysql_select_db("download") or die(mysql_error()); ?>
This file will almost certainly require some editing. You will need to specify a host name for your MySQL server and a MySQL username and password in that file at mysql_connect('localhost', 'root', '')
so that you can connect to the database you’ve set up. It’s extremely unlikely that your production MySQL database will be installed on localhost with a user “root” and no password.
That’s all there is to it. Whenever you want to give someone access to the download, visit the downloadkey.php page. It will generate a unique key code, save it to a database, and print out a URL that you can copy and paste into an email or whatever. The page at that URL checks to see if the key code is legit, then checks to see if the code is less than X hours old, then checks to see if it has been used less than X times. The visitor will get a descriptive message for the first unmet condition and the script will terminate. If all three conditions are met, the download starts automatically.
Very, very helpful. Clear and concise, just what I needed! Thanks!
How would I allow resume through a download manager? I use a similar system and allow my tickets to be used for up to a week but I cannot get it to resume.
Hmm. That’s a good question. I’m not at all sure. I’ll look into it, though.
Clear and concise. Good snippet. Thx!
This is really useful – was looking for something like that for ages. Thanks a lot for sharing! Much appreciated.
You are THE MAN! This is the best script I have have ever found relating to digital content. If you combine this script with a solid chunk of .htaccess and .htpassword security you got yourself a top notch setup!
Thank you so much!
Listen my friend! This is great!!!
Hi,
I have tried the above code but I get the error message below:-
——————————————————————
Warning: mysql_connect() [function.mysql-connect]: Access denied for user ‘root’@’localhost’ (using password: NO) in /home/alanpotts93/public_html/hiddenfiles/dbconnect.php on line 3
Could not connect: Access denied for user ‘root’@’localhost’ (using password: NO)
——————————-
I have already created a mysql table as was instructed with the default value for the third field being a zero.
I am a novice at website building and only know html, but any help would be welcome.
Thanks in advance
Great tutorial. I have a question if you can help: I have an ebook I am selling through clickbank. How can I make it so that each time a visitor buys the ebook, when they are returned to the THANK YOU Page, the link for download is already there, unique, so they can only download the file after payment and not be able to pass it forward to others or guess the download link?
I wish I knew how to do that. I wanted to do something similar with Paypal, where a completed transaction would send the buyer to a download page, but I never figured it out.
If you figure it out, I’d be interested in hearing about how you did it.
Many thanks!
I have just enough html knowledge to maintain my site and even less php.
I was able to create the five main components and apply them to 3 zip files I need to protect. A little help with the database settings from the support folks at Host Rocket and I was up and running.
Thanks again, JP
To Val:
You can integrate your thankyou.php page with the downloadkey.php so that each successful payment will redirected them to your thank you page where the unique id is already created.
I tested this on my test server running lighttpd and it works perfectly. Now I will find ways how to make it an expiring URL with embedded details to be use on my email marketing campaigns…
i am also facing the same problem as joe
____________________________________
Warning: mysql_connect() [function.mysql-connect]: Access denied for user 'root'@'localhost' (using password: NO) in /www/oxyhost.com/m/y/h/myhotspot/htdocs/dbconnect.php on line 3
Could not connect: Access denied for user 'root'@'localhost' (using password: NO)
_____________________________________________
please do help me
please some reply
I suspect that you need to edit the “dbconnect.php” file so that it uses YOUR database information.
You will need to specify a host name, a username and a password in that file so that you can connect to the database you’ve set up. It’s extremely unlikely that your production MySQL database will be installed on localhost with a user root and no password.
ardamis
i have already done this
i have write my dbname,my login or pass in the position of * but nothing happen
now what reply
Nice work mate works nicely… I would like to be able to work with multiple zip file with a unique URL. So I can have different directories of zip files then when the user click on the link it will point to a particular zip file… how can I associate a link to a particular zip file. Would this be easy to achieve…?
Thanks…
This piece of code is a work of art. Thanks for sharing.
This is a LIFESAVER. I have been trying to figure something like this out for months if not years now and you present it in a simple php script that I easily edited to suit my needs.
Thanks!
Remy
Just what i needed but i need the ability to have one code generator with the ability for multiple files. IE enter the URL to be scrambled and it creates one for that URL only. If you get my drift. How can i edit it to do that? Can someone help? email me at webdev (at) chemical-productions (dot) co (dot) uk if anyone knows how to do that.
I have a mobile download site where user can download without login or register but i wan to protect all downloadable files that only registered users can download. Anyone please help with thanks.
This is a fantastic solution for unique links. I do have a question. I got this error
Access denied for user ‘XXXXX’@’XXXXX’ to database ‘download’. I have the dbconnect.php file with “localhost” still. Should that be changed?
It sounds like localhost is the correct location of the database, but maybe the username or password is incorrect.
I’ve written a simple script that will help you test these things:
http://www.ardamis.com/2008/05/26/a-php-script-for-testing-a-mysql-database-connection/
nice i ll use it
Are there issues with signed files? I’m trying this with a couple of downloads–one is a zip file and one is a Windows .MSI. In both cases, the resulting download file shows as corrupt. Not sure what is happening here.
Hmm, I’m not aware of any issues. Can you provide a link to a file that I can use to test?
I had the same problem as Manu and Joe Black until I realized that I needed to change:
mysql_select_db("download")
the download part in the dbconnect. I changed it to the name of my database and it now works. Seems obvious in hindsight. Maybe others are making the same mistake I did. Great Script!
Very cool! One question – how do I protect the file directory where the download resides so that no one can access it unless they have the download code? Obviously legitimate downloads should be possible, but were someone to figure out the directory where the files live they could just get them directly from there, no?
I’m glad you like it.
The script allows you to use anything as the file name on the server, and then show something different to the user in the download dialogue box. This prevents even legitimate users from knowing the location of the file on the server.
For example, the file on the server may be named
k6Fw9Ik.zip
while the file name presented to the user may bedownload.zip
.If you use a suitably long string of random alpha-numeric characters (I use https://www.grc.com/passwords.htm) as the file name, the chances of someone successfully guessing it are astronomical.
I would strongly recommend renaming downloadkey.php, though, as knowing the location of that page allows unlimited access to the file.
If you want to prevent people from viewing the folder contents, this is most easily done by just dropping an index file into the folder. It’s possible to restrict the listing of folder contents via a server setting, too, and this is done by default by many commercial hosting companies.
If you’re on Apache, you could also use htpassword to limit access to a folder, but this level of security probably isn’t necessary.
An example folder structure that should work for most people:
/
/index.html
/download.php
/downloadkey-00.php
/the-download-file.zip
Hey, I absolutely love your code. I have a question though, and I have a feeling other people might be able to use this.
What I need is a way to generate a long list of codes, that way I can enter them all into an excel file and hand them out individually. So, without reloading the page every time I need a new code, I wonder if you could help me modify the download key generator so that it repeats its process X number of times.
That way, I could get a big block of download keys to work with.
Nice Script…. can we do something like email this link to the visitor????
Right, that’s the idea. You can then email the link to someone.
I have this script functioning perfectly, it is very easy to install and use. Thank you!
I would love for their to be a way to mark each key created with a simple text note, so when I create a key for a special download and email it to ten different people, I can mark the key with the person’s name or email address for tracking it easily.
I am using this script to keep track of a new album release for a band, and we are emailing to specific industry contacts. We need to track who has downloaded it and how many times. Currently, the database does show how many times it has been downloaded.
However, in order to keep track of whose link is whose, I am maintaining a google spreadsheet where I have three columns: unique id, person’s name, email address. I am updating this google doc manually but I’m sure there’s a more elegant way to do this with the database, but I am fairly new to SQL commands, and still messing around on how to write the SQL code to do this with your script.
I was thinking about adding another column to the downloadkey database called ‘note’ and manually insert the information from my phpAdmin page provided by my hosting provider. Then I could export the table to PDF and see my notes next to each key.
Is there an easier way to do this or am I pretty close?
Thanks again for anyone’s feedback, I think that others may find this answer useful as well as the only thing this snappy scipt seems to be missing is any sort of tracking/reporting.
I am getting a FATAL ERROR only at larger sized downloads.
If I replace the file with a small zip with the same name, than it works perfect.
THIS IS THE TEXT ERROR MESSAGE:
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 41400320 bytes) in /hermes/web08/b2683/pow.leberj/htdocs/store/Land/Land_p1/download.php on line 60
What am I doing wrong?
Can I edit the code to reflect a larger download?
Best Regards,
Jim
Pingback: Protecting multiple downloads using unique URLs | Ardamis
I found the following code to be able to limit the download speed:
How can I incorporate this code into download.php? I’m not very PHP savvy but I’ve tried several ways to include it. Two ways I did it didn’t cause any script errors but when when trying to access the random link, it just tries and tries. Browser says “waiting website.com” on the bottom left corner. Eventually, it gives a download prompt but it just downloads a blank file. Any ideas?
Thanks in advance.
Actually, it eventually does download the file, not a blank file. It takes probably 2 minutes though after pressing “Go” for the download link. Also, please ignore the download rate comment in the code above; I meant to change the 8.5kb/s.
Thank you very much for your code.
However, I have the following problem: When I put the URL in the address bar to get the file, it is open as text instead of appearing the menu to save it. I’m using Firefox on Debian Lenny and I have verified that the file is a standard zip file.
I would appreciate any suggestion.
Great script! Thank you!
I have an issue with the download file. Everything works perfectly until I open up the downloaded file. The zip file attached is empty.
Does it support other file formats (e.g. PDFs)?
Thanks for your help.
This is an incredible piece of code, and thanks so much, as a client was looking for just this very thing.
Once the download key is generated, instead of posting this, can we redirect the output from a form to an email, so the user gets an email with the unique download link?
Thanks!
~ Michael
hello ardamis
its really Good script for beginner
$url = preg_replace(‘/?.*$/’, ”, $_SERVER[‘REQUEST_URI’]);
$folderpath = ‘http://’.$_SERVER[‘HTTP_HOST’].’/’.ltrim(dirname($url), ‘/’).’/’;
can you tell me how to give the path url to file
Cool script, but when i open the link de browser opens the zipfile in de browser instead of presenting a save as window. Any idea how to fix this?
RLBO, i found this to work for your purpose. i am using it to create download cards for my music and other stuff.
it can generate a code with however many you need
<?php
// A script to generate unique download keys for the purpose of protecting downloadable goods
require ('dbconnect.php');
if(empty($_SERVER['REQUEST_URI'])) {
$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'];
}
// Strip off query string so dirname() doesn't get confused
$url = preg_replace('/?.*$/', '', $_SERVER['REQUEST_URI']);
$folderpath = 'http://'.$_SERVER['HTTP_HOST'].'/'.ltrim(dirname($url), '/').'/';
// Function to generate a 10 digit alpha-numeric code
function randomPrefix($length)
{
$random= "";
srand((double)microtime()*1000000);
$data = "AbcDE123IJKLMN67QRSTUVWXYZ";
$data .= "aBCdefghijklmn123opq45rs67tuv89wxyz";
$data .= "0FGH45OP89";
for($i = 0; $i < $length; $i++)
{
$random .= substr($data, (rand()%(strlen($data))), 1);
}
return $random;
}
// Generate the link
echo "Here are the download keys”;
$i = 1;
while ($i <= 10) {
$i++;
// $random = randomPrefix(MUMBER OF CHARACTERS DESIRED);
$random = randomPrefix(10);
$time = date('U');
//print the codes to page
echo "”. $random. “”;
//sends codes to Database
$registerid = mysql_query(“INSERT INTO downloadkey (uniqueid,timestamp) VALUES(“$random”,”$time”)”) or die(mysql_error());
}
?>
i also forgot.. after you run that gen.php file
you can go to your database manager and export it for excel. then use that for mail merge in Microsoft office publisher on say a business card. 🙂
hey everyone i just wanted to show my implementation of this code for my bands music.
Site: http://download.soundmilitia.com/index3.html
Download Code: ardamis
*note the code will only work on the above URL and not on the base site.
and also try using a fake code such as: Apples or 15d6as17f8afd178a6
im having trouble making the downloadkey table and having it work right, it says
Unknown column ‘uniqueid’ in ‘field list’
I’m getting the same error as DTS.
I have followed your instructions and everything worked except for the message:
Unknown column ‘uniqueid’ in ‘field list’
when trying to generate a downloadkey.
The download key is generated, but when I test the link I get the same error and nothing downloads.
It must be something with the mysql database.
Where have I gone wrong?
Hey Ardamis,
This is a fantastically simple, clear and useful example. Thank you very, very, very much!
Tim
If it says ” Unknown column ‘uniqueid’ in ‘field list’ ”
i assume that means it cant find your database or the column named “uniqeid” in your database.
did you change the names when running your MySQL query to create the tables? if you did you have to change “uniqueid” to whichever column your keys are in.
Hi,
I’m pretty sure i set it up correctly but am getting the following error:
Download Key Generator
Access denied for user ‘MYCPANELLOGINNAME_USERNAME’@’localhost’ to database ‘download’.
I set all priviledges for the MYCPANELLOGINNAME_USERNAME to MYCPANELLOGINNAME_database? What am i doing wrong?
@alex
In the dbconnect.php, you need to edit the last line and insert “MYCPANELLOGINNAME_database” where it reads “download”. This line is calling the specific name of the database which I assume you didn’t name “download”.
Great idea. I think it will be better to make generated link clickable.
I’m unable to force save as file. In my case I can see only source code of zip file in a different browsers, but there is no save as dialog.
I know this is old now but thought i’d update as I struggled to get this to work with multiple rar files being corrupted.
My only solution was to make an iso image of all the files then use it like this:
$mm_type=”application/iso”;
$file = “download.iso”;
$filename = “bogus_download_name.iso”;
header(“Cache-Control: public, must-revalidate”);
header(“Pragma: no-cache”);
header(“Content-Type: ” . $mm_type);
header(“Content-Length: ” .(string)(filesize($file)) );
header(‘Content-Disposition: attachment; filename=”‘.$filename.'”‘);
header(“Content-Transfer-Encoding: binaryn”);
ob_end_clean();
readfile($file);
Very usefull script indeed. thanksKe
Great script. Is there an easy way to have the link open a page then have the user click a download button instead of automatically starting the download? I want to present information then have the user input their email and agree to TOS before they can proceed with the download.
Thanks
Great script, thanks so much.
Has anyone managed to integrate this with Paypal yet so the user gets their code right away?
The PHP server I’m using does not allow large files on their website. Is it possible to have the download files on a different server?
I added the full address (for example,
http://dl.dropbox.com/u/17563876/Volume1_chant.zip
in the config.php.
The generate key works but when I click the link http://mperiard.free.fr/Boutique2Rives/download.php?id=e4a9053a6920
the downloaded file is much smaller and unreadable .
Thank you for your help.
This is amazing and works like a charm. thank you!!!!
Ann (comment #38), you need to change the values for $file and $filename. $file is the actual file name, and $filename is the filename of $file that the PHP script will deliver to the user.
For those who are getting the mysql errors (#45, #46, & #48), try removing the single quote marks around each field being created.
This is an eye-opener. Thank you so much, ardamis!
I wrote: “and $filename is the filename of $file that the PHP script will deliver to the user.”
What I mean is that using this hides the actual file by using an alias name, if you will, to deliver to the end user. On my implementation:
They’ll never guess the real filename, you know? And they get a file called your-file.zip”.
In your script only $key is fetched in download.php. I want song name to be fetched. like this the code header(‘Content-Type: application/octet-stream’);
$fname=$_GET[‘f’];
$file= “music/”.$fname;
header(“Content-Disposition: attachment; filename=$file”);
header(“Content-Length: ” . filesize(“$file”));
header(“Content-Description: Download”);
$fp = fopen(“$file”, “r”);
fpassthru($fp);
fclose($fp);
where can i put $fname=$_GET[‘f’];
$file= “music/”.$fname;
Hi, is it possible to have this version re done with “CURL” instead of “readfile” as most of us our on shared servers where “readfile” and “get_file_contents” are disabled or throw an error about file sizes being unable to allocate etc. as this script loads the file into the RAM instead of just letting the user download it.
Thanks.
This was exactly I was searching for. But I need another script that needs an e-mail address to be subscribed and then the generated link will be sent automatically via email.
Thanks.
Reply ASAP
Hello,
Your script is great, thanks for the share. I have a quick query though!
I have an include script for serving my pages, such as index.php?page=download
When i use your script in my include script the video is always corrupt when it finishes download, The file name is correct, file size is correct i cant work out why its corrupt when accessed through my index.php?page=download include script.
If i access the download key directly through the browser it works absolutely fine.
Any ideas?
My include script is as follows:
if you are not interested in coding your self you can use a ready made script like http://sixthlife.net/product/secure-download-links/
Nice one!!! can you post, how to restrict video downloads from our sites
The key generation works nice for me. How would a code snippet look like that takes the generated code and sends it to a visitor who puts his email-address into a form?
Thanks in advance, your script is great.
it sends me following error:
Parse error: syntax error, unexpected T_STRING, expecting ‘,’ or ‘;’ in /homepages/11/d336918148/htdocs/einmal/downloadkey.php on line 50
does anybody know what might be wrong?
Thanks for this great article. It works great if I am not using any download manager (like – Internet Download Manager). But when I am using any download manager software, it is unable to download the file with a message saying –
“The web site sent a web page instead of a file when IDM requested this file second time. Probably this site uses temporary links and does not allow requesting the same address twice.
Try to delete this download, then start it again from your browser and, when IDM captures it, download it without a stop/pause.”
Please advise if anything can be done to make this work with download managers too.
Great Stuff. Though is there any way to make a few changes to the script so instead of downloading a file you can enter URL’s to webpages that are also disquised?
I’ve been searching for a script like this for a while! In fact a competant PHP Coder, as our New-ish Community-Based Dev Collective has lost our only PHP/mySQL Coder to an overseas UNI Semester & have some urgent work (great for Portfolio’s & we offer great incentives provided by our growing Sponsor list).
Thanks to the Author (&/OR) ANYONE ELSE WHO CAN ASSIST WITH THIS &/or OTHER CUSTOMIZATIONS of ALPHA & BETA SCRIPTS in PROGRESS.
Regards,
@Code_Collective (Open Community Dev Collaborative Project)
fantastic job
how can i submit the values $maxdownloads, $maxtime, $file, $filename, from form page
other then editing the php file directly
Great code! Does the job. There is a new startup that is tackling this problem with a SaaS product. If you don’t use PHP or just don’t want to install any code, you may prefer a solution like theirs. Their site is http://maskit.io
Is there a script or a modification to this one that will prevent a specific IP address from accessing the file after having done so once? Thanks.
Thank you so, so much for this script! Absolutely brilliant. Have been searching for something like this for such a long time!
is there any way that the link will be generated automatically and that automatically send to him via mail
Hi!
Is there anyway you could update this for PHP 7?
I’ve tried changing and fixing some of the errors thrown, but I’m a good enough coder and not confident enough to fix it completely and trust that the script doesn’t do anything weird to the database.