
Load the sample project FileServer.sln. The server component can be accessed via
the control variable c_FileSrv. Let's review its main properties and methods.
Starting the server
In order to start accepting connections, we have to go through the following steps":
1. Setting the property ListenningPort
to the number of the listening port.
We take the value from the Settings form. The default one in our case is 2345.
2. If we want to establish encrypted connections, we have to set the property
SecurityMode to 2, and SecretKey to the value of the
crypto key, specified on the settings form.
If we don't need encryption, we must set SecurityMode to 0.
3. If we want to use packet compression, we must set UseCompression to TRUE.
4. Invoke the method Start().
//Set the component properties
void CbsFileSrvDlg::SetProperties(void)
{
c_FileSrv.put_ListeningPort(dlgSettings.m_Port);
if ((dlgSettings.m_edKey) > "")
{
c_FileSrv.put_SecurityMode(2); //shared secret key
c_FileSrv.put_SecretKey(dlgSettings.m_edKey);
}
else
c_FileSrv.put_SecurityMode(0); //no encryption
c_FileSrv.put_UseCompression(dlgSettings.m_chkCompress);
}
//Start the server
void CbsFileSrvDlg::OnBnClickedbtnstart()
{
if (c_FileSrv.Start())
LogMsg("Server started");
else
MessageBox("Cannot start the server!", "Error", MB_OK);
UpdateStatus();
}
Stop().
If we have some client currently connected, we should remove them with the method
RemoveClient().
//Stop the server
void CbsFileSrvDlg::OnBnClickedbtnstop()
{
int i;
LVITEM lvi;
c_FileSrv.Stop();
for (i=c_lvClients.GetItemCount()-1; i>= 0; i--)
{
lvi.mask = LVIF_TEXT | LVIF_IMAGE;
lvi.iItem = i;
lvi.iSubItem = 0;
if (c_lvClients.GetItem(&lvi))
c_FileSrv.RemoveClient(int(lvi.iImage));
c_lvClients.DeleteItem(i);
}
UpdateStatus();
LogMsg("Server stopped");
}
OnNewClient is fired.
At this point we should the client information (address/port) and store it's handle somewhere
for later on use.
//A new connection is available
void CbsFileSrvDlg::OnNewClientBsfilesrvx(long aHandle)
{
LVITEM lvi;
CString Addr, Port, Tm;
Addr = c_FileSrv.GetClientAddress(aHandle);
Port.Format("%d", c_FileSrv.GetClientPort(aHandle));
int i = c_lvClients.GetItemCount();
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.lParam = aHandle;
lvi.pszText = "Not signed in";
c_lvClients.InsertItem(&lvi);
c_lvClients.SetItemText(i, 1, Addr);
c_lvClients.SetItemText(i, 2, Port);
CTime tm = time(NULL);
Tm = tm.Format("%m/%d/%Y %H:%M:%S");
c_lvClients.SetItemText(i, 3, Tm);
c_lvClients.SetItemText(i, 4, "Connected");
UpdateStatus();
LogMsg("New connection from " + Addr + ":" + Port);
}
OnClientDisconnected is fired.
At this point we should release all data associated with this client.
//A connection is broken
void CbsFileSrvDlg::OnClientDisconnectedBsfilesrvx(long aHandle)
{
int i;
LVITEM lvi;
CString Name, Addr, Port;
i = IndexFromHandle(aHandle);
if (i < 0) return;
lvi.mask = LVIF_TEXT;
lvi.iItem = i;
lvi.iSubItem = 0;
c_lvClients.GetItem(&lvi);
Name = c_lvClients.GetItemText(i, 0);
Addr = c_lvClients.GetItemText(i, 1);
Name = c_lvClients.GetItemText(i, 2);
LogMsg("Disconnected " + Name + " " + Addr + ":" + Port);
c_FileSrv.RemoveClient(int(lvi.iImage));
c_lvClients.DeleteItem(i);
UpdateStatus();
}
OnNeedPassword the asked username should be always
empty, and we always pass an empty string for the password value.
//A request for a password
void CbsFileSrvDlg::OnNeedPasswordBsfilesrvx(long aHandle, LPCTSTR aUsername, BOOL* aOkay, BSTR* aPassword)
{
if (aUsername == "")
{
//this is the user Guest
*aOkay = true;
}
else
{
//Unknown user, we accept only guests
*aOkay = false;
}
}
OnSignin.
Since that moment, the clent can perform various file operations.
//A user is signed-in
void CbsFileSrvDlg::OnSigninBsfilesrvx(long aHandle, long aCode)
{
int i;
CString Name, S;
i = IndexFromHandle(aHandle);
if (i < 0) return;
Name = GetUsername(aHandle);
c_lvClients.SetItemText(i, 0, Name);
S.Format("%s %s:%d", Name, c_FileSrv.GetClientAddress(aHandle), c_FileSrv.GetClientPort(aHandle));
if (aCode == 0)
S = S + " signed in successfully";
else
S = S + " failed sign-in";
LogMsg(S);
}
OnNeedListFolder is reponsible to grant or refuse a permission
for the operation. There are two input and two output parameters:
aHandle - Handle of the client object firing the event.aPath - Relative pathname of the folder of interest.aOkay - Set this variable to true in order to permit the operation.aRoot - If the operation is permitted, write here the root folder assigned to this user.
//A request to list the folder contents
void CbsFileSrvDlg::OnNeedListFolderBsfilesrvx(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
CString Dir = GetAppDir();
*aOkay = true;
*aRoot = Dir.AllocSysString();
LogMsg(GetUsername(aHandle) + ": list folder " + PreSlash(aPath));
}
OnListFolderDone.
OnNeedNewFolder is fired.
The handler must grant or refuse a permission for the operation. The parameters are:
aHandle - Handle of the client object firing the event.aPath - Relative pathname of the file to be zipped.aOkay - Set this variable to true in order to permit the operation.aRoot - If the operation is permitted, write here the root folder assigned to this user.
//A request to zip
void CbsFileSrvDlg::OnNeedZipBsfilesrvx(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
CString Dir = GetAppDir();
*aOkay = true;
*aRoot = Dir.AllocSysString();
LogMsg(GetUsername(aHandle) + ": starting zip operaton" + PreSlash(aPath));
}
OnZipDone informs about the end of the operation.
//The zip operation is completed
void CbsFileSrvDlg::OnZipDoneBsfilesrvx(long aHandle, long aCode)
{
LogMsg(GetUsername(aHandle) + ": finishing zip operation");
}
OnNeedRename is fired.
The handler must grant or refuse a permission for the operation. The parameters are:
aHandle - Handle of the client object firing the event.aPath - Relative pathname of the file to be renamed.aOkay - Set this variable to true in order to permit the operation.aRoot - If the operation is permitted, write here the root folder assigned to this user.
//A request to rename a file
void CbsFileSrvDlg::OnNeedRenameFileBsfilesrvx(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
CString Dir = GetAppDir();
*aOkay = true;
*aRoot = Dir.AllocSysString();
LogMsg(GetUsername(aHandle) + ": rename file " + PreSlash(aPath));
}
OnNeedDeleteFile is fired.
The handler must grant or refuse a permission for the operation. The parameters are:
aHandle - Handle of the client object firing the event.aPath - Relative pathname of the file to be deletedaOkay - Set this variable to true in order to permit the operation.aRoot - If the operation is permitted, write here the root folder assigned to this user.
//A request to delete a file
void CbsFileSrvDlg::OnNeedDeleteFileBsfilesrvx(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
CString Dir = GetAppDir();
*aOkay = true;
*aRoot = Dir.AllocSysString();
LogMsg(GetUsername(aHandle) + ": delete file " + PreSlash(aPath));
}
OnNeedDownload is fired.
The handler must grant or refuse a permission for the operation. The parameters are:
aHandle - Handle of the client object firing the event.aPath - Relative pathname of the file to be downloaded.aOkay - Set this variable to true in order to permit the operation.aRoot - If the operation is permitted, write here the root folder assigned to this user.
//A request to download
void CbsFileSrvDlg::OnNeedDownloadBsfilesrvx(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
CString Dir = GetAppDir();
*aOkay = true;
*aRoot = Dir.AllocSysString();
LogMsg(GetUsername(aHandle) + ": starting download " + PreSlash(aPath));
}
OnDownloadDone informs about the end of the operation.
//The download operation is completed
void CbsFileSrvDlg::OnDownloadDoneBsfilesrvx(long aHandle, long aCode)
{
LogMsg(GetUsername(aHandle) + ": finishing download");
}
OnNeedUpload is fired.
The handler must grant or refuse a permission for the operation. The parameters are:
aHandle - Handle of the client object firing the event.aPath - Relative pathname of the fer of interest.aOkay - Set this variable to true in order to permit the operation.aRoot - If the operation is permitted, write here the root folder assigned to this user.
//A request to upload
void CbsFileSrvDlg::OnNeedUploadBsfilesrvx(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
CString Dir = GetAppDir();
*aOkay = true;
*aRoot = Dir.AllocSysString();
LogMsg(GetUsername(aHandle) + ": starting upload " + PreSlash(aPath));
}
OnUploadDone informs about the end of the operation.
//The upload operation is completed
void CbsFileSrvDlg::OnUploadDoneBsfilesrvx(long aHandle, long aCode)
{
LogMsg(GetUsername(aHandle) + ": finishing upload");
}
OnNeedZip is fired.
The handler must grant or refuse a permission for the operation. The parameters are:
aHandle - Handle of the client object firing the event.aPath - Relative pathname of the file to be zipped.aOkay - Set this variable to true in order to permit the operation.aRoot - If the operation is permitted, write here the root folder assigned to this user.
//A request to zip
void CbsFileSrvDlg::OnNeedZipBsfilesrvx(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
CString Dir = GetAppDir();
*aOkay = true;
*aRoot = Dir.AllocSysString();
LogMsg(GetUsername(aHandle) + ": starting zip operaton" + PreSlash(aPath));
}
OnZipDone informs about the end of the operation.
//The zip operation is completed
void CbsFileSrvDlg::OnZipDoneBsfilesrvx(long aHandle, long aCode)
{
LogMsg(GetUsername(aHandle) + ": finishing zip operation");
}
OnNeedUnzip is fired.
The handler must grant or refuse a permission for the operation. The parameters are:
aHandle - Handle of the client object firing the event.aPath - Relative pathname of the file to be unzipped.aOkay - Set this variable to true in order to permit the operation.aRoot - If the operation is permitted, write here the root folder assigned to this user.
//A request to unzip
void CbsFileSrvDlg::OnNeedUnzipBsfilesrvx(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
CString Dir = GetAppDir();
*aOkay = true;
*aRoot = Dir.AllocSysString();
LogMsg(GetUsername(aHandle) + ": starting unzip operaton" + PreSlash(aPath));
}
OnUnzipDone informs about the end of the operation.
//The unzip operation is completed
void CbsFileSrvDlg::OnUnzipDoneBsfilesrvx(long aHandle, long aCode)
{
LogMsg(GetUsername(aHandle) + ": finishing unzip operation");
}
Connect(Addr, Port) , passing as parameters
the IP address/Domain name and the listening port of the server.
//Initiate a connection request
void CbsFileClnDlg::OnBnClickedbtnconnect()
{
CString Msg;
if (dlgConnect.DoModal() != IDOK) return;
if (dlgConnect.m_edKey > "")
{
c_FileCln.put_SecurityMode(2); //shared secret key
c_FileCln.put_SecretKey(dlgConnect.m_edKey);
}
else
c_FileCln.put_SecurityMode(0); //no encryption
c_FileCln.put_UseCompression(dlgConnect.m_chkCompress);
if (!c_FileCln.Connect(dlgConnect.m_edHost, dlgConnect.m_edPort))
{
Msg.Format("Error Code: %d", c_FileCln.get_LastError());
AfxMessageBox(Msg);
}
UpdateStatus();
}
Disconnect().
//Disconnect from the server
void CbsFileClnDlg::OnBnClickedbtndisconnect()
{
if (!c_FileCln.get_Connected()) return;
c_FileCln.Disconnect();
OnDisconnectedBsfileclnx();
}
ListFolder() sends a requets for folder contents.
//Request the folder contents
void CbsFileClnDlg::ListFolder(void)
{
CString S;
if (m_NowList) return;
c_stFolder.GetWindowText(S);
if (c_FileCln.ListFolder(S))
{
m_NowList = true;
c_lvFiles.DeleteAllItems();
c_btnList.EnableWindow(false);
if (S > "\\")
OnHaveListItemBsfileclnx("..", true, 0, 0, 0, 0);
}
else
CheckError(c_FileCln.get_LastError());
}
OnHaveListItem is fired for each available folder item.
//A list item is available
void CbsFileClnDlg::OnHaveListItemBsfileclnx(LPCTSTR aName, BOOL aFolder, long aSizeLo, long aSizeHi, long aTimeLo, long aTimeHi)
{
LVITEM lvi;
CString Sz, Tm;
FILETIME ft;
int i = c_lvFiles.GetItemCount();
lvi.mask = LVIF_TEXT | LVIF_IMAGE;
lvi.iItem = i;
lvi.iSubItem = 0;
if (aFolder)
{
lvi.iImage = 0;
Sz = "";
}
else
{
lvi.iImage = 1;
Sz.Format("%d", aSizeLo);
}
lvi.pszText = (LPTSTR)(LPCTSTR) aName;
c_lvFiles.InsertItem(&lvi);
if (aName == "..")
Tm = "";
else
{
ft.dwLowDateTime = aTimeLo;
ft.dwHighDateTime = aTimeHi;
CTime tm(ft, -1);
Tm = tm.Format("%m/%d/%Y %H:%M:%S");
}
c_lvFiles.SetItemText(i, 1, Sz);
c_lvFiles.SetItemText(i, 2, Tm);
}
OnListFolderDone().
//End of the list
void CbsFileClnDlg::OnListFolderDoneBsfileclnx(long aCode)
{
m_NowList = false;
CheckError (aCode);
UpdateButtons();
}
CreateFolder() sends a request to create a new folder.
//Request a new folder
void CbsFileClnDlg::OnBnClickedbtnnew()
{
CString Nm, Fol;
if (!GetInputText(Nm, "Create folder", "Folder name:")) return;
c_stFolder.GetWindowText(Fol);
Nm = AddSlash(Fol) + Nm;
if (c_FileCln.CreateFolder(Nm))
m_NowCreateFolder = true;
else
CheckError(c_FileCln.get_LastError());
UpdateButtons();
}
OnCreateFolderDone() is fired when the folder is created.
//A new folder is created
void CbsFileClnDlg::OnCreateFolderDoneBsfileclnx(long aCode)
{
m_NowCreateFolder = false;
CheckError(aCode);
UpdateButtons();
if (aCode > 0) return;
ListFolder();
}
RenameFile() send a request to rename a file on the server.
//Send rename request
void CbsFileClnDlg::OnBnClickedbtnrename()
{
CString Nm, Fol;
if (c_lvFiles.GetSelectedCount() == 0) return;
if (GetImageIndex(GetSelectedIndex()) == FolderImgIdx)
{
//folder
if (!GetInputText(Nm, "Rename folder", "New name:")) return;
Nm = AddSlash(GetCurFol()) + Nm;
if (c_FileCln.RenameFolder(AddSlash(GetCurFol()) + c_lvFiles.GetItemText(GetSelectedIndex(), 0), Nm))
m_NowRenameFolder = true;
else
CheckError(c_FileCln.get_LastError());
}
else
{
//file
if (!GetInputText(Nm, "Rename file", "New name:")) return;
Nm = AddSlash(GetCurFol()) + Nm;
if (c_FileCln.RenameFile(AddSlash(GetCurFol()) + c_lvFiles.GetItemText(GetSelectedIndex(), 0), Nm))
m_NowRenameFile = true;
else
CheckError(c_FileCln.get_LastError());
}
UpdateButtons();
}
OnRenameFileDone() is fired when the confirmation is received.
//A file is renamed
void CbsFileClnDlg::OnRenameFileDoneBsfileclnx(long aCode)
{
m_NowRenameFile = false;
CheckError(aCode);
UpdateButtons();
if (aCode > 0) return;
ListFolder();
}
DeleteFile() sends a requests to delete a file.
//Send delete request
void CbsFileClnDlg::OnBnClickedbtndelete()
{
CString Nm, Fol;
if (c_lvFiles.GetSelectedCount() == 0) return;
if (GetImageIndex(GetSelectedIndex()) == FolderImgIdx)
{
//folder
if (c_FileCln.DeleteFolder(AddSlash(GetCurFol()) + c_lvFiles.GetItemText(GetSelectedIndex(), 0)))
m_NowDeleteFolder = true;
else
CheckError(c_FileCln.get_LastError());
}
else
{
//file
if (c_FileCln.DeleteFile(AddSlash(GetCurFol()) + c_lvFiles.GetItemText(GetSelectedIndex(), 0)))
m_NowDeleteFile = true;
else
CheckError(c_FileCln.get_LastError());
}
UpdateButtons();
}
OnDeleteFileDone() is fired when the confirmation is received.
//A file is deleted
void CbsFileClnDlg::OnDeleteFileDoneBsfileclnx(long aCode)
{
m_NowDeleteFile = false;
CheckError(aCode);
UpdateButtons();
if (aCode > 0) return;
ListFolder();
}
Download() sends a request to download a file.
//Send a download request
void CbsFileClnDlg::GoDownload(void)
{
CString Nm, Fol;
if (c_lvFiles.GetSelectedCount() == 0) return;
if (GetImageIndex(GetSelectedIndex()) == FolderImgIdx) return;
Nm = c_lvFiles.GetItemText(GetSelectedIndex(), 0);
CFileDialog FileDlg(FALSE, "", Nm, 0, NULL);
if( FileDlg.DoModal() != IDOK ) return;
m_DnldFile = Nm;
if (c_FileCln.Download(AddSlash(GetCurFol()) + Nm, ExtractFilePath(FileDlg.GetPathName())))
{
m_NowDownload = true;
c_stDownload.SetWindowText(m_DnldFile + ": handshaking");
}
else
CheckError (c_FileCln.get_LastError());
UpdateStatus();
}
OnDownloadProgress() informs about the download progress.
//Download progress info
void CbsFileClnDlg::OnDownloadProgressBsfileclnx(long aCountLo, long aCountHi, long aSizeLo, long aSizeHi)
{
CString S;
S.Format("%s - %d/%d", m_DnldFile, aCountLo, aSizeLo);
c_stDownload.SetWindowText(S);
}
OnDownloadDone() is fired when the download is completed.
//The download operation is completed
void CbsFileClnDlg::OnDownloadDoneBsfileclnx(long aCode)
{
if (aCode == 0)
c_stDownload.SetWindowText(m_DnldFile + " - Done.");
else
c_stDownload.SetWindowText(m_DnldFile + " - Aborted: " + ErrorText(aCode));
m_NowDownload = false;
UpdateButtons();
}
Upload() sends a requets to upload a file.
//Send an upload request
void CbsFileClnDlg::OnBnClickedbtnupload()
{
CFileDialog FileDlg(TRUE, "", NULL, 0, NULL);
if( FileDlg.DoModal() != IDOK ) return;
m_UpldFile = FileDlg.GetFileName();
if (c_FileCln.Upload(FileDlg.GetPathName(), GetCurFol()))
{
m_NowUpload = true;
m_UpldFol = GetCurFol();
c_stUpload.SetWindowText(m_UpldFile + ": handshaking");
}
else
CheckError (c_FileCln.get_LastError());
UpdateStatus();
}
OnUploadProgress() provides information about the upload progress.
//Upload progress info
void CbsFileClnDlg::OnUploadProgressBsfileclnx(long aCountLo, long aCountHi, long aSizeLo, long aSizeHi)
{
CString S;
S.Format("%s - %d/%d", m_UpldFile, aCountLo, aSizeLo);
c_stUpload.SetWindowText(S);
}
The event OnUploadDone() is fired when the upload operation is completed.
//The upload is completed
void CbsFileClnDlg::OnUploadDoneBsfileclnx(long aCode)
{
if (aCode == 0)
c_stUpload.SetWindowText(m_UpldFile + " - Done.");
else
c_stUpload.SetWindowText(m_UpldFile + " - Aborted: " + ErrorText(aCode));
m_NowUpload = false;
UpdateButtons();
if (m_UpldFol == GetCurFol())
ListFolder();
}
Zip method starts a new compression operation.
'Start the zip operation
Private Sub btnZip_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnZip.Click
Dim Nm As String
Nm = InputBox("Zip file name", "Zipping") 'ask the user for the zip file name
If Nm = "" Then Exit Sub 'canceled by the user
If ExtractFileExt(Nm) = "" Then
Nm = Nm + ".zip"
End If
If FileCln.Zip(AddSlash(txtFolder.Text) + Nm, AddSlash(txtFolder.Text) + lvFiles.SelectedItems(0).Text) Then
'the request is accepted
NowZip = True 'raise the flag
ZipFile = Nm 'remember the zip file
ZipFol = txtFolder.Text 'remember the current folder
txtZip.Text = "Handshaking..."
Else
CheckError(FileCln.LastError) 'the request is rejected
End If
UpdateStatus()
End Sub
We prompt the user for the zip file name, and if it's not empty, we call the Zip method with two parameters.
The first one is the relative pathname of the zip archive, the second one is the relative pathname of the file to be
compressed. If the request is successful, we remember the current folder and the zip file name.
Otherwise, we show an error message.
OnZipProgress event provides progress information about the zip operation.
//Progress information is available for the zip operation
void CbsFileClnDlg::OnZipProgressBsfileclnx(long aFileCount, long aFileTotal, long aByteCountLo, long aByteCountHi, long aByteTotalLo, long aByteTotalHi)
{
CString S;
//Show the current byte count and the total amount of bytes (low 32 bits)
S.Format("%s - %d/%d", m_ZipFile, aByteCountLo, aByteTotalLo);
c_stZip.SetWindowText(S);
}
We display two counters (low 32 bits only) - the number of bytes compressed so far,
and the total number of requested bytes.
OnZipDone reports the result of the zip operation.
//The zip operation is completed
void CbsFileClnDlg::OnZipDoneBsfileclnx(long aCode)
{
if (aCode == 0)
{
c_stZip.SetWindowText(m_ZipFile + " - Done."); //success
}
else
c_stZip.SetWindowText(m_ZipFile + " - Aborted: " + ErrorText(aCode)); //there is an error, describe it
m_NowZip = false;
if (m_ZipFol == GetCurFol())
ListFolder(); //Refresh the folder
UpdateButtons();
}
We display the completion status of the zip operation, and if the current folder is affected, we update the file list.
Unzip method starts a new decompression operation.
//Start the unzip operation
void CbsFileClnDlg::OnBnClickedbtnunzip()
{
CString Arc, Nm, Fol;
if (c_lvFiles.GetSelectedCount() == 0) return;
if (GetImageIndex(GetSelectedIndex()) == FolderImgIdx) return;
Arc = c_lvFiles.GetItemText(GetSelectedIndex(), 0);
if (ExtractFileExt(Arc) != ".zip") return; //not a zip file
//Ask the user for the extraction folder
if (!GetInputText(Fol, "Unzipping", "Extract to folder (leave blank for current):")) return;
if (c_FileCln.Unzip(AddSlash(GetCurFol()) + Arc, Fol))
{
//the request is accepted
m_NowUnzip = true; //raise the flag
m_UnzipFile = Arc; //remember the unzip file name
m_UnzipFol = GetCurFol(); //remember the current folder
c_stUnzip.SetWindowText(m_UnzipFile + ": handshaking");
}
else
CheckError (c_FileCln.get_LastError());
UpdateStatus();
}
We prompt the user for the destination folder, where the extracted file will be placed.
Then we call the Unzip method with two parameters.
The first one is the relative pathname of the zip archive, the second one is the relative pathname of the destination
folder. If the request is successful, we remember the current folder and the zip file name.
Otherwise, we show an error message.
OnUnzipProgress event provides progress information about the unzip operation.
//Progress information is available for the zip operation
void CbsFileClnDlg::OnUnzipProgressBsfileclnx(long aFileCount, long aFileTotal, long aByteCountLo, long aByteCountHi, long aByteTotalLo, long aByteTotalHi)
{
CString S;
//Show the current byte count and the total amount of bytes (low 32 bits)
S.Format("%s - %d/%d", m_ZipFile, aByteCountLo, aByteTotalLo);
c_stUnzip.SetWindowText(S);
}
We display two counters (low 32 bits only) - the number of bytes decompressed so far,
and the total number of bytes in the archive.
OnUnzipDone event reports the result of the unzip operation.
//The zip operation is completed
void CbsFileClnDlg::OnUnzipDoneBsfileclnx(long aCode)
{
if (aCode == 0)
{
c_stUnzip.SetWindowText(m_UnzipFile + " - Done."); //success
}
else
c_stUnzip.SetWindowText(m_UnzipFile + " - Aborted: " + ErrorText(aCode)); //there is an error, describe it
m_NowUnzip = false;
if (m_UnzipFol == GetCurFol())
ListFolder(); //Refresh the folder
UpdateButtons();
}
We display the completion status of the unzip operation, and if the current folder is affected, we update the file list.
In nowadays, the Internet is insecure for a variety of reasons.
Exchanging sensitive information could be a problem in many situations.
In this article, we have presented one simple and affordable solution
for secure private file sharing without need of certificates.