These scripts utilizes the administration protocol to manage the server from custom applications. This technique may be used to integrate ProVide with custom systems, such as web applications or business systems.
If you wish to see how you can start cmd, powershell etc. scripts from ProVide you can check out these links:
Email example
CMD examples
Of course, if your client supports the proper authentication exchange ProVide is able to encrypt the API connection using a regular “AUTH TLS” command (used frequently in for instance FTPS connections).
The easiest way to explore the scripting API is to use a simple telnet application (included with Windows) and connect to the admin port (default 3145):
telnet localhost 3145 220 . user admin 331 User name received, need password. pass abc 230 User logged in, proceed. help 214-The following commands are recognized: 214- PASSWD 214- LISTUSERS 214- ADDUSER 214- GETUSER 214- SETUSER 214- DELUSER 214- SETGROUP 214- DELGROUP 214- SETRESOURCE 214- GETRESOURCE 214- ADDRESOURCE 214- DELRESOURCE 214- 214 For more detailed information, use HELP <COMMAND>.
Control ProVide with PHP #
Connect to server, create accounts, manage resources
<?php /** * Class for ftp-user handling * @author shredder * @version 1.0 **/ class ftp { private $fp; private $commandlog; /** * Opens a socket connection to a server, params are read * from database * @param string $host FTP server address * @param int $port FTP server port * @param string $user Adminname * @param string $pass Adminpassword **/ public function connect($host, $port, $user, $pass) { // Open socket connection $this->fp = fsockopen($host,$port); // Retrieve welcome message ("200.") $this->commandlog .= "<tr><td>".date("i:s")."</td><td>".fread($this->fp, 1000)."</td></tr>"; // Send admin username fwrite($this->fp,"user $user\n"); $this->commandlog .= "<tr><td>".date("i:s")."</td><td>".fread($this->fp, 1000)."</td></tr>"; // Send admin password fwrite($this->fp,"pass $pass\n"); $this->commandlog .= "<tr><td>".date("i:s")."</td><td>".fread($this->fp, 1000)."</td></tr>"; } /** * Creates a user with a specific group membership and/or * a specific FTP-directory with one resource * @param string $username * @param string $password * @param string $realname * @param string $ftppath * @param string $path * @param string $group * @return bool FALSE if user already exists **/ public function createUser($username, $password, $realname, $ftppath, $path, $group) { // Adds a specific user fwrite($this->fp,"adduser \"$username\" \"$password\" \"$realname\" \"$ftppath\" \"$path\" \"$group\"\n"); $message = fread($this->fp, 1000); $this->commandlog .= "<tr><td>".date("i:s")."</td><td>$message</td></tr>"; if ($this->isError($message)) { return false; } else { return true; } } /** * Adds a ressource to a user or a group * @param string $username * @param string $ftppath * @param string $path * @param string $rights * @return bool **/ public function addResource($username, $ftppath, $path, $rights) { fwrite($this->fp,"addresource \"$username\" \"$ftppath\" \"$path\" \"$rights\"\n"); $message = fread($this->fp, 1000); $this->commandlog .= "<tr><td>".date("i:s")."</td><td>$message</td></tr>"; if ($this->isError($message)) { return false; } else { return true; } } /** * Sets a ressource of a user or a group * @param string $username * @param string $ftppath * @param string $path * @param string $rights * @return bool **/ public function setResource($username, $ftppath, $path, $rights) { fwrite($this->fp,"setresource \"$username\" \"$ftppath\" \"$path\" \"$rights\"\n"); $message = fread($this->fp, 1000); $this->commandlog .= "<tr><td>".date("i:s")."</td><td>$message</td></tr>"; if ($this->isError($message)) { return false; } else { return true; } } /** * Changes the password of a specific user * @param string $username * @param string $password * @return bool **/ public function changePassword($username, $password) { fwrite($this->fp, "passwd \"$username\" \"$password\"\n"); $message = fread($this->fp, 1000); $this->commandlog .= "<tr><td>".date("i:s")."</td><td>$message</td></tr>"; if ($this->isError($message)) { return false; } else { return true; } } /** * Checks if the command was succesful * @param string $message * @return bool **/ private function isError($message) { if (substr_count($message, "500")) { return false; } else { return true; } } /** * Returns command log * @return string **/ public function getCommandlog() { $this->commandlog = "<table border=1>".$this->commandlog."</table>"; return $this->commandlog; } } ?>
Script submitted by MasonSolutions and ReggaeGandalf
Extract information from ProVide with PHP #
Extract statistics information
//Shows user-statistics for ProVide //Created by idvis@seznam.cz $provideaccountsdir='c:/Program Files/ProVide/accounts/'; //directory of ProVide accounts directory function readvalue($astr,$avalue){ if (strpos($astr,$avalue)===false) $result=''; else{ $result=substr($astr,strpos($astr,$avalue)+strlen($avalue)); $result=substr($result,0,strpos($result,chr(13).chr(10))); } return $result; } function mb($avalue){ if ($avalue=='') $avalue=0; return number_format(round($avalue/(1024*1024),2),2); } //---------------Main code--------------- echo '<html><head><meta http-equiv="content-type" content="text/html; charset=windows-1250">'; echo '<style>.left{text-align:left;} body,table{font: 11px verdana,arial,helvetica,sans-serif;} th,td{text-align:right; padding-right:1em;}</style></head><body><table>'; echo '<tr><th class="left">FTP Username</th><th>Logins</th><th class="left">Last login</th><th class="left">Last IP</th>' .'<th>Downl. files</th><th>Upl. files</th><th>Download [MB]</th><th>Upload [MB]</th></tr>'; $sumdown=0; $sumup=0; foreach (glob($provideaccountsdir."*.uac") as $filename) { $s=file_get_contents($filename); $username=readvalue($s,"Username="); $logins=readvalue($s,"{Logins: "); if ($logins!=''){ $lastlogin=readvalue($s,"{Last Login: "); $lastknownip=readvalue($s,"{Last Known IP: "); $filesuploaded=readvalue($s,"{Files Uploaded: "); $bytesuploaded=readvalue($s,"{Bytes Uploaded: "); $filesdownloaded=readvalue($s,"{Files Downloaded: "); $bytesdownloaded=readvalue($s,"{Bytes Downloaded: "); $sumdown+=$bytesdownloaded; $sumup+=$bytesuploaded; echo "<tr><td class='left'>$username</td><td>$logins</td><td class='left'>$lastlogin</td><td class='left'>$lastknownip</td>" ."<td>$filesdownloaded</td><td>$filesuploaded</td><td>".mb($bytesdownloaded)."</td><td>".mb($bytesuploaded)."</td></tr>"; } } echo "<tr><th colspan='6'>Total:</th><th>".mb($sumdown)."</th><th>".mb($sumup)."</th></tr>"; echo '</table></body></html>'; ?>
Script submitted by Idvis
Control ProVide with PERL #
Connect to server, create accounts, manage resources
#!"c:/perl/bin/perl.exe" use Strict; use Net::Telnet; use CGI; $CGI::POST_MAX=1024 * 5; # max 5K posts $CGI::DISABLE_UPLOADS = 1; # no uploads use File::Path::Stderr; my $query = new CGI; my $t = new Net::Telnet (); my $port = 3145; my $admin_uname = "Admin"; my ($admin_passwd, $uname, $passwd, $real_name, $new_domain, $vhpath); $admin_passwd = $query->param('Admin_pass'); $uname = $query->param('new_user'); $passwd = $query->param('new_password'); $real_name = $query->param('real_name'); $domain_name = $query->param('domain'); $vhpath = "c\:\\sites\\vh\\$domain_name\.vh"; mkpath("c\:\\sites\\$domain_name\\logs"); mkpath("c\:\\sites\\$domain_name\\httpdocs"); mkpath("c\:\\sites\\$domain_name\\cgi-bin"); my @lines; $lines[0] = '<VirtualHost *:80>'; $lines[1] = ' ServerAdmin admin@dj69.com'; $lines[2] = ' DocumentRoot C:/sites/'.$domain_name.'/httpdocs/'; $lines[3] = ' ServerName '.$domain_name; $lines[4] = ' ServerAlias www.'.$domain_name; $lines[5] = ' ErrorLog C:/sites/'.$domain_name.'/logs/error_log'; $lines[6] = ' CustomLog C:/sites/'.$domain_name.'/logs/access_log common'; $lines[7] = ' ScriptAlias /cgi-bin/ C:/sites/'.$domain_name.'/cgi-bin/'; $lines[8] = '<Directory "C:/sites/'.$domain_name.'/httpdocs/">'; $lines[9] = ' Options Includes'; $lines[10] = ' AllowOverride None'; $lines[11] = ' Order allow,deny'; $lines[12] = ' Allow from all'; $lines[13] = '</Directory>'; $lines[14] = '</VirtualHost>'; open FH, ">$vhpath"; my $listitem; foreach $listitem ( @lines ) { print FH $listitem, "\n"; } close(FH); print "Content-type:text/html\n\n"; $t->open(port => $port); print "port open\n"; # Next line is not needed from some reason..... # $t->waitfor('/200\s\./'); print 'Got 220 (Got in)<br>'; # sending admin's user name $t->print('user ', $admin_uname); print "gave username<br>"; # checking for the correct response (331). $t->waitfor('/331 .*/') or die "dowant pass\n"; print "Got 331 User name received, need password.<br>"; # sending admin's password $t->print('pass ', $admin_passwd); print "gave password.<br>"; #checking for the correct response (230). $t->waitfor('/230 .*/') or die "pass is not correct\n"; print "got 230 User logged in, proceed.<br>"; #Adding the new user print "Adding new user $uname"; $t->print('ADDUSER "', $uname, '" "', $passwd, '" "', $real_name, '"'); $t->waitfor('/200 .*/') or die "user has not been creates\n"; print "Got 200 User created successfully.<br>"; #connecting resources to the user. print "connecting resources"; $t->print('SETRESOURCE "', $uname, '" "cgi-bin" "c\:\\sites\\', $domain_name, '\cgi-bin" "RF,WF,DF,AF,LD,MD,DD,RR"'); $t->waitfor('/200 .*/') or die "user did not update\n"; print "Got 200 User(s) updated successfully.<br>"; $t->print('SETRESOURCE "', $uname, '" "httpdocs" "c\:\\sites\\', $domain_name, '\httpdocs" "RF,WF,DF,AF,LD,MD,DD,RR"'); $t->waitfor('/200 .*/') or die "user did not update\n"; print "Got 200 User(s) updated successfully.<br>"; $t->print('SETRESOURCE "', $uname, '" "logs" "c\:\\sites\\', $domain_name, '\logs" "RF,LD,RR"'); $t->waitfor('/200 .*/') or die "user did not update\n"; print "Got 200 User(s) updated successfully.<br>"; # print "deleting user\n"; # $t->print('DELUSER "', $uname, '"'); # $t->waitfor('/200 .*/') or die "user has not been deleted\n"; #print "User(s) removed successfully.\n"; print "Quitting\n"; $t->print('quit'); $t-close;
Script submitted by Roi
Exporting and Importing Users to and from ProVide #
The following powershell scripts allows you to export and import ProVide users to and from a file.
You need a ProVide with the Build-Date of 2020-03-25 or later to use this functionality.
If you export/import the admin account, please make sure to remember the password.
Instructions
The first thing to do is to copy and paste the scripts below into .ps1 files.
EncryptAccountDetails.ps1
Use the EncryptAccountDetails.ps1-script to create the necessary username.txt and password.txt (These files must be at the same location as the export/import scripts.)
These files will contain your username and password but the information are encrypted and the import and Export script will use these.
Remember to run the Encrypt-script on the same computer on where you will be running the Export/Import-scripts as the encryption is tied to the current username and computer (per Windows standard).
ExportProVideAccounts.ps1
Adjust the following parameters to match your setup.
$adminHost To the IP address of the server.
$adminPort To your admin port if you have changed it in settings.ini
To use the scripts you simply run
ExportProVideAccounts.ps1 -ExportToFile “filename.bck”
ImportProVideAccounts.ps1 -ImportFromFile “filename.bck”
You can also just run the script and you get to enter the name of a file you want to export/import to/from.
The export script will create a new file if there are none, and overwrite existing ones with the same name.
If you are going to schedule this using Task Scheduler you must remember to specify the “Start in” parameter so that the script finds the username/password files.
EncryptAccountDetails.ps1
# Encrypts credentials for Export/Import ProVide account scripts # $getCredential = Get-Credential $getCredential.password | ConvertFrom-SecureString | Set-Content "password.txt" $getCredential.username | Set-Content "username.txt"
ExportProVideAccounts.ps1
# A simple account export script for ProVide Server # param ([Parameter(Mandatory=$true)] [string] $ExportToFile) try { $adminHost = "localhost" $adminPort = 3145 $adminUser = Get-Content "username.txt" $encryptedPass = Get-Content "password.txt" | ConvertTo-SecureString $credential = New-Object System.Management.Automation.PsCredential($adminUser, $encryptedPass) $adminPass = $credential.GetNetworkCredential().password Write-Host "Connecting to $adminHost on port $adminPort ... " -NoNewLine try { $socket = New-Object System.Net.Sockets.TcpClient($adminHost, $adminPort) Write-Host -ForegroundColor Green "OK" } catch { Write-Host -ForegroundColor Red "failed" exit -1 } $stream = $socket.GetStream() $writer = New-Object System.IO.StreamWriter($stream) $reader = New-Object System.IO.StreamReader($stream) $writer.AutoFlush = $true function ExpectResponseStart { $response = $reader.ReadLine() if (-not $response.StartsWith($args[0])) { Write-Host -ForegroundColor Red "Expected response start ""$($args[0])"" but got ""$response""." exit -1 } } function ExtractItems { Write-Host "Listing $($args[0])..." $writer.WriteLine($args[1]) $items = @() $response = $reader.ReadLine() if ($response.Substring(3,1) -eq "-") { $items += $response.Substring(4) } while ($response.StartsWith("200-")) { $response = $reader.ReadLine() if ($response.Substring(3,1) -eq "-") { $items += $response.Substring(4) } } Write-Host "Extracting $($args[0])..." foreach ($item in $items) { $data = @() $writer.WriteLine("$($args[2]) ""$item"""); $response = $reader.ReadLine() $data += $response.Substring(4) while ($response.StartsWith("200-")) { $response = $reader.ReadLine() $data += $response.Substring(4) } $content = ConvertTo-Json -Compress $data Add-Content -Path $ExportToFile -Encoding Unicode -Value $content } } ExpectResponseStart "220 " $writer.WriteLine("USER $adminUser") ExpectResponseStart "331 " $writer.WriteLine("PASS $adminPass") ExpectResponseStart "230 " $writer.WriteLine("OPTS UTF8 ON") ExpectResponseStart "200 " rm $ExportToFile -ErrorAction Ignore ExtractItems "users" "LISTUSERS" "GETUSER" ExtractItems "groups" "LISTGROUPS" "GETGROUP" Write-Host "Done." } finally { if ($reader) { $reader.Close() } if ($writer) { $writer.Close() } if ($stream) { $stream.Close() } }
ImportProVideAccounts.ps1
# A simple account import script for ProVide Server # param ([Parameter(Mandatory=$true)] [string] $ImportFromFile) try { $adminHost = "localhost" $adminPort = 3145 $adminUser = Get-Content "username.txt" $encryptedPass = Get-Content "password.txt" | ConvertTo-SecureString $credential = New-Object System.Management.Automation.PsCredential($adminUser, $encryptedPass) $adminPass = $credential.GetNetworkCredential().password Write-Host "Connecting to $adminHost on port $adminPort ... " -NoNewLine try { $socket = New-Object System.Net.Sockets.TcpClient($adminHost, $adminPort) Write-Host -ForegroundColor Green "OK" } catch { Write-Host -ForegroundColor Red "failed" exit -1 } $stream = $socket.GetStream() $writer = New-Object System.IO.StreamWriter($stream) $reader = New-Object System.IO.StreamReader($stream) $writer.AutoFlush = $true function ExpectResponseStart { $response = $reader.ReadLine() if (-not $response.StartsWith($args[0])) { Write-Host -ForegroundColor Red "Expected response start ""$($args[0])"" but got ""$response""." exit -1 } } function ImportItem { $data = ConvertFrom-Json $args[0] if ($data[0].StartsWith("User")) { $username = $data[0].Substring(9) $password = $data[1].Substring(9) Write-Host "Importing user ""$username""..." $writer.WriteLine("SETUSER ""$username"" ""$password""") } elseif ($data[0].StartsWith("Group")) { $groupname = $data[0].Substring(10) Write-Host "Importing group ""$groupname""..." $writer.WriteLine("SETGROUP ""$groupname""") } foreach ($row in $data) { $writer.WriteLine($row) } if (-not $data[-1] -eq ".") { $writer.WriteLine(".") } ExpectResponseStart "200 " } ExpectResponseStart "220 " $writer.WriteLine("USER $adminUser") ExpectResponseStart "331 " $writer.WriteLine("PASS $adminPass") ExpectResponseStart "230 " $writer.WriteLine("OPTS UTF8 ON") ExpectResponseStart "200 " foreach ($line in Get-Content $ImportFromFile) { ImportItem $line } Write-Host "Done." } finally { if ($reader) { $reader.Close() } if ($writer) { $writer.Close() } if ($stream) { $stream.Close() } }