Using Dropbox To Host or Backup Websites and Database Folders on Windows

There are two options to host and/or backup your local development environment’s (such as WAMP) Websites and Database folders with Dropbox.

Keeping Folders Outside Dropbox Folder

Create NTFS “Junction Points” (folder links) between sub-folders in your Dropbox folder, and WAMP’s \Websites and \Database folders…

mklink /j C:\path-to\Dropbox\Websites C:\WampDeveloper\Websites
mklink /j C:\path-to\Dropbox\Database C:\WampDeveloper\Database

Note that according to DropBox, this type of set up will only sync when the DropBox service or the computer is restarted (i.e., changes before a restart will not be backed-up)…

Dropbox will follow Windows junction points (Windows Vista or later) and sync the files or folders they link to. However, any changes to those files or folders made from the Windows operating system will not sync again until the Dropbox desktop application is restarted.

The reason this is so is because Windows only creates file-system events on the real end of a Junction Point, and not on all the paths.

Keeping Folders Inside Dropbox Folder

The other option is to move everything into the Dropbox folder –

1. After the creation of a website, move its Websites\\ folder into Dropbox\.

Then, in its original place create an NTFS Junction Point into Dropbox\Websites\\.

mklink /j C:\WampDeveloper\Websites\ C:\path-to\Dropbox\Websites\

2. Move the Database\ folder into Dropbox\, and either:

A) create NTFS Junction Point in its original place into Dropbox\Database\.

mklink /j C:\WampDeveloper\Database C:\path-to\Dropbox\Database

B) or update all Config\Mysql\my-*.ini files to use the Dropbox path.

datadir = "C:\path-to\Dropbox\Database\mysql-data-*"

(and any other “\Database\” paths)

For WampDeveloper, note to reflect the accompanying MySQL version in “*”.

Notes and Limits

1. The mklink command will create the source folder as a Junction Point / Directory, with the link being made into the target folder…
A. The source folder must not exist, or has to be already deleted (mklink command will neither reform nor delete it).
B. The target folder has to already exist (mklink command will not create it).

2. Only Administrators can use mklink. Open command-line via “Run as admin”.

3. Junction Points can only point to folders and volumes.

4. Junction Points can only link across local volumes.

Disabling SSLv3 in Apache By Setting SSLProtocol (be aware of VirtualHost issue)

After doing some testing and debugging, it looks like there is a long-standing issue in openssl/mod_ssl that prevents changes to the SSLProtocol value made per VirtualHost from taking effect…

The value of SSLProtocol will be set permanently from the first SSL Virtual Host loaded by Apache. And further changes to the value in other SSL Virutal Hosts will not work and will fail silently (i.e., with no messages recorded in the error log).

It is unclear whether this is a openssl/mod_ssl bug or a general re-negotiation issue (related to SNI).

Correctly Disable SSLv3 Protocol

Edit the first VirtualHost loaded by Apache.

For WampDeveloper Pro this is –


Update the SSL Protocol (SSLProtocol) to remove SSLv3 –

SSLProtocol all -SSLv2 -SSLv3


Make sure that you do not remove SSLv3 (with !SSLv3) from the SSL Cipher Suite (SSLCipherSuite) as it is used inside TLSv1.0…

You can verify that openssl uses/links the SSLv3 cipher inside the TLSv1 protocol with this command –

openssl ciphers -v "TLSv1" | sort
ADH-AES128-SHA      SSLv3 Kx=DH       Au=None Enc=AES(128)  Mac=SHA1
ADH-AES256-SHA           SSLv3 Kx=DH       Au=None Enc=AES(256)  Mac=SHA1
ADH-CAMELLIA128-SHA      SSLv3 Kx=DH       Au=None Enc=Camellia(128) Mac=SHA1
SRP-RSA-AES-128-CBC-SHA  SSLv3 Kx=SRP      Au=RSA  Enc=AES(128)  Mac=SHA1
SRP-RSA-AES-256-CBC-SHA  SSLv3 Kx=SRP      Au=RSA  Enc=AES(256)  Mac=SHA1

Disabling the SSLv3 protocol fixes the POODLE vulnerability… The SSLv3 ciphers are not related to any vulnerabilities.

Test SSLv3 Vulnerability

You can test your configuration locally by running a manual openssl connection to check if the SSLv3 handshake fails…

openssl s_client -connect -servername -ssl3

You can also check if the SSLv3 cipher is available (it should be)…

openssl s_client -connect -servername -cipher SSLv3

Browser Compatibility Issues

While disabling the SSLv3 Protocol will prevent the POODLE attack, and mitigate on other security issues and vulnerabilities, it will also break SSL connections made by IE 6 (on Windows XP or older).

And if you follow the PCI requirements of also disabling TLSv1.0, this can break IE 10, 9, and 8 compatibility (when released they did not have TLSv1.1 nor TLSv1.2 enabled by default).

Automatically Backup MySQL Databases on Windows (WAMP)

The best way to create and automate backups of MySQL databases is to:

1. Use the Windows Task Scheduler to automatically run a backup task every day or week.

2. Have the task run a BATCH file containing the “mysqldump” and “makecab” commands to export and compress the databases.

3. For additional recovery, use MySQL’s Binary Log files to record transactions between backup jobs (to rebuild the database to the last transaction recorded).

This solution will work for everything from Windows 10, down to XP, and Server 2003. No external tools are required.

Backup MySQL Databases with Batch File

Create a mysql-backup.bat file to export all the databases (or only select databases), using a DATE-TIME file-name stamp, and compress the SQL file…


set TIMESTAMP=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%

REM Export all databases into file C:\path\backup\databases.[year][month][day].sql
"C:\path-to\mysql\bin\mysqldump.exe" --all-databases --result-file="C:\path-to\backup\databases.%TIMESTAMP%.sql" --user=username --password=password

REM Change working directory to the location of the DB dump file.
CD \path-to\backup\

REM Compress DB dump file into CAB file (use "EXPAND" to decompress).
MAKECAB "databases.%TIMESTAMP%.sql" ""

REM Delete uncompressed DB dump file.
DEL /q /f "databases.%TIMESTAMP%.sql"

Make sure to update all the paths used, and the MySQL’s username (root) and password (if no password is used, leave the “--password” switch out).

Why use CAB instead of ZIP?…

MS-CAB files have almost 50% better compression ratios over ZIP (especially for single files), and the MAKECAB/EXPAND commands exist on all Windows versions.

Scheduled MySQL Backup Task

Create a Windows Task to run the above BATCH file every day or every week.

Make sure that:

1. The user has rights to Log on as a batch job.

2. If the drive/path you are exporting to is a mapped drive, to use the UNC path.

3. If the drive/path is a shared folder, the user the task is ran on has the correct permissions.

Use MySQL Binary Log

Verify that my.ini has the Binary Log enabled, set to either a MIXED or ROW mode, and does not expire between backup tasks (make it 2x the frequency of the backup task schedule +1 day).


This way you can restore to the last transaction recorded by replaying the log over the last backup job.

MySQL Won’t Start Because of InnoDB Table Corruption (Repair and Recover Database)

Hardware failures and power outages are the usual cause of database crashes, corrupted tables, and bad data.

Normally, as MySQL starts it will check itself and attempt to automatically recover from the previous crash (by redoing incomplete transactions using ib_logfiles). But when MySQL encounters an abnormal issue or corrupt InnoDB data, it will refuse to start and will let the user decide what to do next.

InnoDB: Database was not shutdown normally!
InnoDB: Starting crash recovery.
InnoDB: Reading tablespace information from the .ibd files…

InnoDB: Error:…

Before attempting to repair the existing database: if you have a recent database backup (either a full SQL dump-file or a directory copy), you can rebuild the database to the last transaction recorded by using MySQL’s Binary Log (if the Binary Log’s “expire_logs_days” value is still within the backup date).

If the issue is that an InnoDB table has become corrupt, you have to attempt to get as much good data from it, and then manually reload it…

If the corrupt table is not important, you can skip all the steps, and just delete its IBD file (\Database\mysql-data\mysql\table-name.ibd).

1. First you have to make a backup of the entire \Database directory (as data and files are going to be changed and mistakes can happen easily).

“7zip” is a good compression utility, that will properly zip/unzip NTFS Junction Point / folder-links (some apps will not), which this folder contains.

2. Open file Config\Mysql\my.ini (in Notepad), and in section “[mysqld]” add in line:

innodb_force_recovery = 1

Save file. Attempt to start MySQL.

The value above (“1″) specifies which level of regular startup checks MySQL will skip over – so it can start. The value goes from 1 to 6, 4 + is considered dangerous, and the minimum value should be used to get MySQL to start…

This will also put the Database into a predominantly read-only mode (but you can still DROP tables).

3. If MySQL starts, mysqldump (export) the corrupt table, then DROP (remove) it…

Open the command-line (Systems tab, button: Command Line).

Export the specific table into an SQL file –

mysqldump -u root -p > database.table.sql

(* it will ask you for the root password, if it is not set then just leave the “-p” switch out)

The above exported table copy will only contain table rows/entries that MySQL could read (and it is possible that no data could be recovered from the table).

Then access the MySQL shell –

mysql -u root -p

(* it will ask you for the root password, if it is not set then just leave the “-p” switch out)

Drop (remove) the corrupt table which is preventing MySQL from starting –

drop table;

Exit the MySQL shell –


4. Restart MySQL in normal recovery mode (undo the my.ini edit), and re-import the “recovered” table. This table will only contain non-corrupted rows/entries; it will likely have some data missing…

Remove from file my.ini, section “[mysqld]” –

innodb_force_recovery = 1

Save file. Start MySQL.

Open the command-line.

Import the table –

mysql < database.table.sql

5. If more than 1 table is corrupted, check MySQL log and repeat the above process.

6. If the corrupt table issues are fixed, but MySQL still has some problems starting due to “binary log files errors”…

Move out the “mysql-bin.*” files that are in \Database\mysql-data\ (but not the ib_logfile*, nor ibdata* files).

7. Once MySQL is running, you can also perform a general check and repair of all databases –

mysqlcheck -u root -p --auto-repair --check --optimize --all-databases

MySQL Error “Impossible to write to binary log since BINLOG_FORMAT = STATEMENT”

A user trying to install a webapp reported this MySQL error –

Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.

This error is a result of using a mode for MySQL’s Binary Log Format that is not compatible with TRANSACTION/COMMIT type statements when using InnoDB tables…

The above error is specifically mentioned here

If you are using InnoDB tables and the transaction isolation level is READ COMMITTED or READ UNCOMMITTED, only row-based logging can be used.

MySQL has 3 BINLOG-FORMAT modes:

  • STATEMENT, statement-based logging: every SQL statement is recorded.
  • ROW, row-based logging: every SQL result is recorded.
  • MIXED, mixed logging: if data modification is non-deterministic uses ROW, otherwise STATEMENT.

While the Binary Log is only used for Replication and Point-in-Time Recovery (i.e., nothing to do with installing single-DB webapps), when enabled + using the above transactional statements, SQL results (ROW) must be recorded instead of SQL statements (STATEMENT).

Edit my.ini (via notepad) –

Modify the Binary Log Format from –

# binary logging format

To –


Save file. Restart MySQL.

If this does not fix the issue, then instead of “MIXED” use value “ROW”.

Installing StartCom’s StartSSL SSL Certificates for Apache (on WAMP)

Before proceeding, if you have downloaded or received a zip file that contains all the various certificate and key files, you should – right click the zip file, select Properties, and click “Unblock” (if that is displayed, otherwise Windows won’t let you use some of the files after unzipping).

Extract/place the provided files into the website’s certs folder –


If the Private Key (ssl.key) was generated by StartCom for you, you’ll need to remove the password that is set on it (as it’s not needed, and also Apache on Windows cannot use password protected Keys) –

openssl rsa -in ssl.key -out ssl.key

This will ask you for the password, remove it from the key, and save the key back into the same file.

Create the Bundle file that packages all intermediate certificates (as 1_root_bundle.crt, but only if this file has not been already provided)…

copy /B intermediate.crt + root.crt 1_root_bundle.crt

This will create a bundle file named “1_root_bundle.crt” containing the needed CA (Certificate Authority) intermediate certificates which establish the chain between your public certificate up to the root CA certificate.

Then update the website’s SSL VirtualHost file with –

SSLCertificateFile "C:/WampDeveloper/Websites/"
SSLCertificateKeyFile "C:/WampDeveloper/Websites/"
SSLCertificateChainFile "C:/WampDeveloper/Websites/"

Usually nothing more needs to be changed in the VirtualHost (as WAMPs such as WampDeveloper Pro have all other parts of SSL pre-configured).

Save the VirtualHost file and restart Apache.

How to enable cURL and curl_exec in PHP

Client URL library (cURL) is not enabled in this server. cURL is needed to perform URL fetching.

curl_exec() function is disabled in this server. This function must be enabled in php.ini

The PHP extension “cURL” is enabled (usually by default) in php.ini –


But it is also possible to disable individual functions, such as curl_exec(), in php.ini (“disable_functions” cannot be set in VirtualHost nor .htaccess files).

For example, php.ini might be using disable_functions to disable curl_exec() from being used –

disable_functions =  ...,curl_exec,...

If this is the case, the website’s PHP and HTTP error log files will contain this warning –

Warning: curl_exec() has been disabled for security reasons

Edit the value of “disable_functions” to remove “curl_exec”, save php.ini, and restart Apache.