Test zip password correctness in vb.net - vb.net

I want to test if a zip has a particular password in vb.net. How can I create a function like check_if_zip_pass(file, pass) As Boolean?
I can't seem to find anything in the .net framework that does this already, unless I'm missing something incredibly obvious.
This method should NOT extract the files, only return True if the attempted pass is valid and False if not.

Use a 3rd party library, like DotNetZip. Keep in mind that passwords in zipfiles are applied to entries, not to the entire zip file. So your test doesn't quite make sense.
One reason WinZip may refuse to unpack the zipfile is that the very first entry is protected with a password. It could be the case that only some entries are protected by password, and some are not. It could be that different passwords are used on different entries. You'll have to decide what you want to do about these possibilities.
One option is to suppose that only one password is used on any entries in the zipfile that are encrypted. (This is not required by the zip specification) In that case, below is some sample code to check the password. There is no way to check a password without doing the decryption. So this code decrypts and extracts into Stream.Null.
public bool CheckZipPassword(string filename, string password)
{
bool success = false;
try
{
using (ZipFile zip1 = ZipFile.Read(filename))
{
var bitBucket = System.IO.Stream.Null;
foreach (var e in zip1)
{
if (!e.IsDirectory && e.UsesEncryption)
{
e.ExtractWithPassword(bitBucket, password);
}
}
}
success = true;
}
catch(Ionic.Zip.BadPasswordException) { }
return success;
}
Whoops! I think in C#. In VB.NET this would be:
Public Function CheckZipPassword(filename As String, password As String) As System.Boolean
Dim success As System.Boolean = False
Try
Using zip1 As ZipFile = ZipFile.Read(filename)
Dim bitBucket As System.IO.Stream = System.IO.Stream.Null
Dim e As ZipEntry
For Each e in zip1
If (Not e.IsDirectory) And e.UsesEncryption Then
e.ExtractWithPassword(bitBucket, password)
End If
Next
End Using
success = True
Catch ex As Ionic.Zip.BadPasswordException
End Try
Return success
End Function

I use SharpZipLib in .NET to do this, here is a link to their wiki with a helper function for unzipping password protected zip files. Below is a copy of the helper function for VB.NET.
Imports ICSharpCode.SharpZipLib.Core
Imports ICSharpCode.SharpZipLib.Zip
Public Sub ExtractZipFile(archiveFilenameIn As String, password As String, outFolder As String)
Dim zf As ZipFile = Nothing
Try
Dim fs As FileStream = File.OpenRead(archiveFilenameIn)
zf = New ZipFile(fs)
If Not [String].IsNullOrEmpty(password) Then ' AES encrypted entries are handled automatically
zf.Password = password
End If
For Each zipEntry As ZipEntry In zf
If Not zipEntry.IsFile Then ' Ignore directories
Continue For
End If
Dim entryFileName As [String] = zipEntry.Name
' to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
' Optionally match entrynames against a selection list here to skip as desired.
' The unpacked length is available in the zipEntry.Size property.
Dim buffer As Byte() = New Byte(4095) {} ' 4K is optimum
Dim zipStream As Stream = zf.GetInputStream(zipEntry)
' Manipulate the output filename here as desired.
Dim fullZipToPath As [String] = Path.Combine(outFolder, entryFileName)
Dim directoryName As String = Path.GetDirectoryName(fullZipToPath)
If directoryName.Length > 0 Then
Directory.CreateDirectory(directoryName)
End If
' Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
' of the file, but does not waste memory.
' The "Using" will close the stream even if an exception occurs.
Using streamWriter As FileStream = File.Create(fullZipToPath)
StreamUtils.Copy(zipStream, streamWriter, buffer)
End Using
Next
Finally
If zf IsNot Nothing Then
zf.IsStreamOwner = True ' Makes close also shut the underlying stream
' Ensure we release resources
zf.Close()
End If
End Try
End Sub
To test, you could create a file compare that looks at the file before it's zipped and again after it has been unzipped (size, date, etc...). You could even compare the contents if you wanted to use a simple test file, like a file with the text "TEST" inside. Lots of choices, depends on how much and how far you want to test.

There's not much built into the framework for doing this. Here's a big sloppy mess you could try using the SharpZipLib library:
public static bool CheckIfCorrectZipPassword(string fileName, string tempDirectory, string password)
{
byte[] buffer= new byte[2048];
int n;
bool isValid = true;
using (var raw = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
using (var input = new ZipInputStream(raw))
{
ZipEntry e;
while ((e = input.GetNextEntry()) != null)
{
input.Password = password;
if (e.IsDirectory) continue;
string outputPath = Path.Combine(tempDirectory, e.FileName);
try
{
using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite))
{
while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, n);
}
}
}
catch (ZipException ze)
{
if (ze.Message == "Invalid Password")
{
isValid = false;
}
}
finally
{
if (File.Exists(outputPath))
{
// careful, this can throw exceptions
File.Delete(outputPath);
}
}
if (!isValid)
{
break;
}
}
}
}
return isValid;
}
Apologies for the C#; should be fairly straightforward to convert to VB.NET.

Related

vb.net stream reader reads from a .accdb and .xml file without an error [duplicate]

How can I test whether a file that I'm opening in C# using FileStream is a "text type" file? I would like my program to open any file that is text based, for example, .txt, .html, etc.
But not open such things as .doc or .pdf or .exe, etc.
In general: there is no way to tell.
A text file stored in UTF-16 will likely look like binary if you open it with an 8-bit encoding. Equally someone could save a text file as a .doc (it is a document).
While you could open the file and look at some of the content all such heuristics will sometimes fail (eg. notepad tries to do this, by careful selection of a few characters notepad will guess wrong and display completely different content).
If you have a specific scenario, rather than being able to open and process anything, you should be able to do much better.
I guess you could just check through the first 1000 (arbitrary number) characters and see if there are unprintable characters, or if they are all ascii in a certain range. If the latter, assume that it is text?
Whatever you do is going to be a guess.
As others have pointed out there is no absolute way to be sure. However, to determine if a file is binary (which can be said to be easier than determining if it is text) some implementations check for consecutive NUL characters. Git apparently just checks the first 8000 chars for a NUL and if it finds one treats the file as binary. See here for more details.
Here is a similar C# solution I wrote that looks for a given number of required consecutive NUL. If IsBinary returns false then it is very likely your file is text based.
public bool IsBinary(string filePath, int requiredConsecutiveNul = 1)
{
const int charsToCheck = 8000;
const char nulChar = '\0';
int nulCount = 0;
using (var streamReader = new StreamReader(filePath))
{
for (var i = 0; i < charsToCheck; i++)
{
if (streamReader.EndOfStream)
return false;
if ((char) streamReader.Read() == nulChar)
{
nulCount++;
if (nulCount >= requiredConsecutiveNul)
return true;
}
else
{
nulCount = 0;
}
}
}
return false;
}
To get the real type of a file, you must check its header, which won't be changed even the extension is modified. You can get the header list here, and use something like this in your code:
using(var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
using(var reader = new BinaryReader(stream))
{
// read the first X bytes of the file
// In this example I want to check if the file is a BMP
// whose header is 424D in hex(2 bytes 6677)
string code = reader.ReadByte().ToString() + reader.ReadByte().ToString();
if (code.Equals("6677"))
{
//it's a BMP file
}
}
}
I have a below solution which works for me.This is general solution which check all types of Binary file.
/// <summary>
/// This method checks whether selected file is Binary file or not.
/// </summary>
public bool CheckForBinary()
{
Stream objStream = new FileStream("your file path", FileMode.Open, FileAccess.Read);
bool bFlag = true;
// Iterate through stream & check ASCII value of each byte.
for (int nPosition = 0; nPosition < objStream.Length; nPosition++)
{
int a = objStream.ReadByte();
if (!(a >= 0 && a <= 127))
{
break; // Binary File
}
else if (objStream.Position == (objStream.Length))
{
bFlag = false; // Text File
}
}
objStream.Dispose();
return bFlag;
}
public bool IsTextFile(string FilePath)
using (StreamReader reader = new StreamReader(FilePath))
{
int Character;
while ((Character = reader.Read()) != -1)
{
if ((Character > 0 && Character < 8) || (Character > 13 && Character < 26))
{
return false;
}
}
}
return true;
}

How I can use Shell32.dll in Silverlight OOB

I'd like to get the target information from a shortcut file using my silverlight OOB app, so I'm going to make the following code to work in my silverlight OOB. It seems I have to used P/Invoke to use Shell32.dll, but I'm not sure how I can use Folder, FolderItem, and ShellLinkObject? Most references explain how I can use the functions in the .dll using P/invoke:( Please give me any comments or sample code/links:)
public string GetShortcutTargetFile(string shortcutFilename)
{
string pathOnly = Path.GetDirectoryName(shortcutFilename);
string filenameOnly = Path.GetFileName(shortcutFilename);
Shell32.Shell shell = new Shell32.ShellClass();
Shell32.Folder folder = shell.NameSpace(pathOnly);
Shell32.FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null)
{
Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;
MessageBox.Show(link.Path);
return link.Path;
}
return String.Empty; // Not found
}
I found a solution.
public string GetShortcutTargetFile(string shortcutFilename)
{
string pathOnly = System.IO.Path.GetDirectoryName(shortcutFile);
string filenameOnly = System.IO.Path.GetFileName(shortcutFile);
dynamic shell = AutomationFactory.CreateObject("Shell.Application");
dynamic folder = shell.NameSpace(pathOnly);
dynamic folderItem = folder.ParseName(filenameOnly);
if (folderItem != null)
{
dynamic link = folderItem.GetLink;
return "\""+link.Path +"\"" + " " + link.Arguments;
}
return String.Empty; // Not found
}

Cached Variables in VSTO Office 2010

After having a look around the web, I have found the following posts (below) which are quite similar to my problem. However, after trying the solutions, I am still stuck.
VSTO Frustration
Setting cached variables in VSTO 3.0
Basically, I want to populate some data in a Excel file on a web server before I send it to the client.
Here is my code in the Workbook:
namespace Inno.Data.Excel
{
public partial class ThisWorkbook
{
[Cached]
public DataSet Config = new DataSet();
private void ThisWorkbook_Startup(object sender, System.EventArgs e)
{
//InitializeCachedData();
var baseUrl = (string)Config.Tables["Config"].Rows[0].ItemArray[0];
var streamIds = (string)Config.Tables["Config"].Rows[0].ItemArray[1];
MessageBox.Show(baseUrl + " " + streamIds);
}
}
}
and on the server side I have the following:
let rootUrl = Uri(x.Request.Url.GetLeftPart(UriPartial.Authority))
let setUpData (report : Report) (sd : ServerDocument) =
let url = rootUrl.AbsoluteUri
let streamIds = String.Join(",", report.series |> Seq.map(fun s -> s.id))
let dt = new System.Data.DataTable("Config")
dt.Columns.Add("BaseUrl", typeof<String>) |> ignore
dt.Columns.Add("StreamIds", typeof<String>) |> ignore
dt.Rows.Add([|box url; box streamIds|]) |> ignore
dt.AcceptChanges()
let cache = sd.CachedData.HostItems.["Inno.Data.Excel.ThisWorkbook"]
let urlItem = cache.CachedData.["Config"]
urlItem.SerializeDataInstance(dt)
sd.Save()
sd.Close()
let initialiseDocument (report : Report) (path : string) =
let fileName = report.name.Replace(" ", "_") + ".xlsx"
let sd = (new ServerDocument(path))
sd |> setUpData report
fileName
let docPath = x.Request.MapPath(Path.Combine(liveReportPath, "Inno.Data.Excel.xlsx"))
let fileName = initialiseDocument report docPath
x.File(File.OpenRead(docPath), "application/vnd.ms-excel", fileName) :> ActionResult
However, when I go to open the file after it has downloaded, I get the following error:
Microsoft.VisualStudio.Tools.Applications.Runtime.CannotFindObjectToFillException: Cannot find any public instance member with ID Config in object Inno.Data.Excel.ThisWorkbook.
Things I have tried:-
Using a simple string rather than a DataSet
Calling StartCaching("Config")
Manipulating the ServerDocument in memory using the byte[] file overload
Copying the original Excel file and operating on the copy
But now I'm out of ideas. I see that a fair number of people have had this error, and as is pointed out in this post, there was a known bug in VSTO 3.0 with manipulating files in memory.
Thanks in advance.

How do I know whether the zip file is password protected or not with dotnetzip?

now let's think we got a random zip file so how do I know that file is password protected?
cause there ain't a method like
bool IsPasswordProtected(string fileName);
I am asking this cause there are couple of methods to extract entries from a zip file
but still I have to use either Extract() or ExtractWithPassword()
but to use this I have to know the file that I am going to extract is actually password protected or not. I know the password applies to the entries not to the zip file itself.
I checked every methods in the documentation but I couldn't find a suitable method to solve this issue or did I miss something?
Thanks.!
Check the ZipEntry.UsesEncryption property.
I would try the ZipEntry.Extract method and if it fails due to missing a password you will get an exception, and then try the ExtractWithPassword and see if that works. If it does not work, then fail with the original exception. Unfortunately the Password property is write-only.
According to the documentation ZipEntry.UsesEntryption is not the same as requiring a password.
ZipFile zip = ZipFile.Read(zipFileName);
if (!password.Equals(""))
{
zip.Password = password;
}
try
{
if (Directory.Exists(outputDirectory))
{
Directory.Delete(outputDirectory);
}
Directory.CreateDirectory(outputDirectory);
zip.ExtractAll(outputDirectory);
System.Windows.Forms.MessageBox.Show("Unzip process is complete.", "Information");
}
catch (BadPasswordException e)
{
string value = "Type password for unzip";
if (InputBox("Zip file was password protected.", "Password : ",ref value ) == System.Windows.Forms.DialogResult.OK)
{
ExtractFileToDirectory(filename, outputpath,value);
}
}
And InputBox method is follow...
public DialogResult InputBox(string title, string promptText, ref string value)
{
Form form = new Form();
System.Windows.Forms.Label label = new System.Windows.Forms.Label();
System.Windows.Forms.TextBox textBox = new System.Windows.Forms.TextBox();
System.Windows.Forms.Button buttonOk = new System.Windows.Forms.Button();
System.Windows.Forms.Button buttonCancel = new System.Windows.Forms.Button();
form.Text = title;
label.Text = promptText;
textBox.Text = value;
buttonOk.Text = "OK";
buttonCancel.Text = "Cancel";
buttonOk.DialogResult = System.Windows.Forms.DialogResult.OK;
buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
label.SetBounds(9, 20, 372, 13);
textBox.SetBounds(12, 36, 372, 20);
buttonOk.SetBounds(228, 72, 75, 23);
buttonCancel.SetBounds(309, 72, 75, 23);
label.AutoSize = true;
textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
form.ClientSize = new System.Drawing.Size(396, 107);
form.Controls.AddRange(new System.Windows.Forms.Control[] { label, textBox, buttonOk, buttonCancel });
form.ClientSize = new System.Drawing.Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MinimizeBox = false;
form.MaximizeBox = false;
form.AcceptButton = buttonOk;
form.CancelButton = buttonCancel;
DialogResult dialogResult = form.ShowDialog();
value = textBox.Text;
return dialogResult;
}
The code is useful when zip file have password. If zip file have password, input text dialog appear and request password for extract. Note that (outputDirectory is string that for extract zip file location). I think that code was very useful for you.
I have the same problem too.i tried the code from Francis Upton .it wasn't useful.
You can try
ZipFile.CheckZipPassword(TemporaryFilePath, PassWord);
make the PassWord to null;like...
bool ExistPassWord = ZipFile.CheckZipPassword(TemporaryFilePath, null);

Terminating an application programmatically using a file path in vb.net

I want to terminate an application using the full file path via vb.net, yet I could not find it under Process. I was hoping for an easy Process.Stop(filepath), like with Process.Start, but no such luck.
How can I do so?
You would have to look into each process' Modules property, and, in turn, check the filenames against your desired path.
Here's an example:
VB.NET
Dim path As String = "C:\Program Files\Ultrapico\Expresso\Expresso.exe"
Dim matchingProcesses = New List(Of Process)
For Each process As Process In process.GetProcesses()
For Each m As ProcessModule In process.Modules
If String.Compare(m.FileName, path, StringComparison.InvariantCultureIgnoreCase) = 0 Then
matchingProcesses.Add(process)
Exit For
End If
Next
Next
For Each p As Process In matchingProcesses
p.Kill()
Next
C#
string path = #"C:\Program Files\Ultrapico\Expresso\Expresso.exe";
var matchingProcesses = new List<Process>();
foreach (Process process in Process.GetProcesses())
{
foreach (ProcessModule m in process.Modules)
{
if (String.Compare(m.FileName, path, StringComparison.InvariantCultureIgnoreCase) == 0)
{
matchingProcesses.Add(process);
break;
}
}
}
matchingProcesses.ForEach(p => p.Kill());
EDIT: updated the code to take case sensitivity into account for string comparisons.
try
System.Diagnostics.Process.GetProcessesByName(nameOfExeFile).First().Kill()
This ignores the path of the file.