how to take diff of two versions of perforce depot file - java

how to check if the file content is same as the revision in server perforce JAVA API. Before updating any file into perforce depot, I want to check is there any difference in content of local file and the depot file. if there is no difference then ignore to submit that file.

I think you want the getDiffFiles() method:
https://www.perforce.com/perforce/r15.1/manuals/p4java-javadoc/com/perforce/p4java/impl/mapbased/client/Client.html#getDiffFiles
Alternatively, for the specific thing you're doing (not submitting unchanged files), just use the "leaveUnchanged" submit option rather than doing the same work yourself.

Yes simple to do. Just generate a MD5 hash of the original file and before updating again generate a MD5 hash of the new file.
Now compare the hashes of both the files. If both are same, then the contents of both the files are same and if not then they are different and you are good to update.
Here is an utility to generate and check MD5 easily,
public class MD5Utils {
private static final String TAG = "MD5";
public static boolean checkMD5(String md5, File updateFile) {
if (TextUtils.isEmpty(md5) || updateFile == null) {
Log.e(TAG, "MD5 string empty or updateFile null");
return false;
}
String calculatedDigest = calculateMD5(updateFile);
if (calculatedDigest == null) {
Log.e(TAG, "calculatedDigest null");
return false;
}
Log.v(TAG, "Calculated digest: " + calculatedDigest);
Log.v(TAG, "Provided digest: " + md5);
return calculatedDigest.equalsIgnoreCase(md5);
}
public static String calculateMD5(File updateFile) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "Exception while getting digest", e);
return null;
}
InputStream is;
try {
is = new FileInputStream(updateFile);
} catch (FileNotFoundException e) {
Log.e(TAG, "Exception while getting FileInputStream", e);
return null;
}
byte[] buffer = new byte[8192];
int read;
try {
while ((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
String output = bigInt.toString(16);
// Fill to 32 chars
output = String.format("%32s", output).replace(' ', '0');
return output;
} catch (IOException e) {
throw new RuntimeException("Unable to process file for MD5", e);
} finally {
try {
is.close();
} catch (IOException e) {
Log.e(TAG, "Exception on closing MD5 input stream", e);
}
}
}
}

Related

Retrieve Subject alternative names of X.509 certificate in java

I have tried using the solution provided in this link.
I am getting following error when i tried reading subject alternative names of X.509 Certificate
java.lang.NoSuchMethodError: org.bouncycastle.asn1.ASN1InputStream.readObject()Lorg/bouncycastle/asn1/DERObject;
At below line of code
ASN1InputStream decoder = new ASN1InputStream((byte[]) item.toArray());
DEREncodable encoded = decoder.readObject();
.der file is used to create certificate as follows.
X509Certificate cert=null;
fis = new FileInputStream(file.getAbsoluteFile()); //.der file
bis = new BufferedInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0) {
try{
cert = cf.generateCertificate(bis);
}
catch (CertificateException e) {
e.printStackTrace();
}
List list=getSubjectAlternativeNames((X509Certificate) cert);
Below is the solution i got from the link mentioned above.
public static List<String> getSubjectAlternativeNames(X509Certificate certificate) {
List<String> identities = new ArrayList<String>();
try {
Collection<List<?>> altNames = certificate.getSubjectAlternativeNames();
// Check that the certificate includes the SubjectAltName extension
if (altNames == null)
return Collections.emptyList();
// Use the type OtherName to search for the certified server name
for (List item : altNames) {
Integer type = (Integer) item.get(0);
if (type == 0)
// Type OtherName found so return the associated value
try {
// Value is encoded using ASN.1 so decode it to get the server's identity
ASN1InputStream decoder = new ASN1InputStream((byte[]) item.toArray()[1]);
DEREncodable encoded = decoder.readObject();
encoded = ((DERSequence) encoded).getObjectAt(1);
encoded = ((DERTaggedObject) encoded).getObject();
encoded = ((DERTaggedObject) encoded).getObject();
String identity = ((DERUTF8String) encoded).getString();
// Add the decoded server name to the list of identities
identities.add(identity);
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
// log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
}
catch (Exception e) {
// log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
e.printStackTrace();
}
// Other types are not good for XMPP so ignore them
//log.warn("SubjectAltName of invalid type found: " + certificate);
}
}
catch (CertificateParsingException e) {
e.printStackTrace();
// log.error("Error parsing SubjectAltName in certificate: " + certificate + "\r\nerror:" + e.getLocalizedMessage(),e);
}
return identities;
}
Is it that i have not used proper .jar file?
.jar i have used is --> bcprov-jdk16-1.45.jar
Suggest me where i have gone wrong.
I tried with your code for me it is working, I tested with a certificate exported from internet explorer
Internet Explorer -> Tools -> Internet Options -> Content -> Certificates -> Untrusted Publishers -> www.google.com
I exported this as ".cer", I made few changes to your code
public static List<String> getSubjectAlternativeNames(X509Certificate certificate) {
List<String> identities = new ArrayList<String>();
try {
Collection<List<?>> altNames = certificate.getSubjectAlternativeNames();
if (altNames == null)
return Collections.emptyList();
for (List item : altNames) {
Integer type = (Integer) item.get(0);
if (type == 0 || type == 2){
try {
ASN1InputStream decoder=null;
if(item.toArray()[1] instanceof byte[])
decoder = new ASN1InputStream((byte[]) item.toArray()[1]);
else if(item.toArray()[1] instanceof String)
identities.add( (String) item.toArray()[1] );
if(decoder==null) continue;
DEREncodable encoded = decoder.readObject();
encoded = ((DERSequence) encoded).getObjectAt(1);
encoded = ((DERTaggedObject) encoded).getObject();
encoded = ((DERTaggedObject) encoded).getObject();
String identity = ((DERUTF8String) encoded).getString();
identities.add(identity);
}
catch (UnsupportedEncodingException e) {
log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
}
catch (Exception e) {
log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
}
}else{
log.warn("SubjectAltName of invalid type found: " + certificate);
}
}
}
catch (CertificateParsingException e) {
log.error("Error parsing SubjectAltName in certificate: " + certificate + "\r\nerror:" + e.getLocalizedMessage(),e);
}
return identities;
}
I saved the file to c:\aa1.cer
X509Certificate cert=null;
FileInputStream fis = new FileInputStream("c:\\aa1.cer");
BufferedInputStream bis = new BufferedInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
if (bis.available() > 0)
try{
cert = (X509Certificate)cf.generateCertificate(bis);
}
catch (CertificateException e) {
e.printStackTrace();
}
System.out.println(CertificateInfo.getSubjectAlternativeNames(cert));
I got the output as [www.google.com, google.com]
Please check your certificate, I think the problem is your certificate
Many examples use hard-coded integers. For readability, I much prefer to use:
GeneralName.dNSName = 2
GeneralName.iPAddress = 7
... etc
The code:
public static String[] parseHostNames(X509Certificate cert) {
List<String> hostNameList = new ArrayList<>();
try {
Collection<List<?>> altNames = cert.getSubjectAlternativeNames();
if (altNames != null) {
for(List<?> altName : altNames) {
if(altName.size()< 2) continue;
switch((Integer)altName.get(0)) {
case GeneralName.dNSName:
case GeneralName.iPAddress:
Object data = altName.get(1);
if (data instanceof String) {
hostNameList.add(((String)data));
}
break;
default:
}
}
}
System.out.println("Parsed hostNames: " + String.join(", ", hostNameList));
} catch(CertificateParsingException | IOException e) {
System.err.println("Can't parse hostNames from this cert.");
e.printStackTrace();
}
return hostNameList.toArray(new String[hostNameList.size()]);
}
Note: The accepted answer checks for byte[], but won't compile on my system. I found some other examples using byte[] by calling new ASN1InputStream((byte[])data).readObject();, but I have no certificate to test it with, so I've removed it from my example.

Zip File md5 Checksum - Every Time Different

I have an Android applications which gets zip file's md5 checksum. I use it to compare the file with file on a server. My problem is that every time I try to generate the md5 for the same file, the checksum is different. I'm posting my methods here. Can you tell me what is wrong?
private static String fileMD5(String filePath) throws NoSuchAlgorithmException, IOException {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
byte[] buffer = new byte[1024];
MessageDigest digest = MessageDigest.getInstance("MD5");
int numRead = 0;
while (numRead != -1) {
numRead = inputStream.read(buffer);
if (numRead > 0)
digest.update(buffer, 0, numRead);
}
byte [] md5Bytes = digest.digest();
return convertHashToString(md5Bytes);
} catch (Exception e) {
return "ERROR";
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) { }
}
}
}
private static String convertHashToString(byte[] md5Bytes) {
String returnVal = "";
for (int i = 0; i < md5Bytes.length; i++) {
returnVal += Integer.toString(( md5Bytes[i] & 0xff ) + 0x100, 16).substring(1);
}
return returnVal;
}
i try to solve same issue. I don't know how to solve it but I know reason :).
Reason is that zip file contains at least timestamp information about files. And this is what change you md5sum. Every zip entry is the same but this metadata information change result for md5.
Probably you already find answer somewhere else.
As #michal-Šiplák mentioned
Reason is that zip file contains at least timestamp information about
files. And this is what changes your md5sum. Every zip entry is the same
but this metadata information change result for md5.
To have consistent md5 you need to remove this variable and have it fixed as a constant. Bellow example
fun pack(sourceDir: File, zipFile: File) {
ZipOutputStream(zipFile.outputStream()).use { zs ->
val sourcePath = sourceDir.toPath()
Files.walk(sourcePath)
.filter { path -> path.isDirectory().not() }
.forEach { path ->
zs.putNextEntry(createZipEntry(path, sourcePath))
Files.copy(path, zs)
zs.closeEntry()
}
}
}
fun createZipEntry(filePath: Path, sourcePath: Path): ZipEntry {
val zipEntry = ZipEntry(sourcePath.relativize(filePath).toString())
zipEntry.time = 0
return zipEntry
}
key Line here is zipEntry.time = 0 which makes metadata zip file constant.

Issue with Converting XML file into single String

I am creating an XML file from my Database and storing it in Internal storage. I require data from XML file into a single string. For which, i am using the following method.
BufferedReader br;
try {
br = new BufferedReader(new FileReader(new File(pathDAR)));
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line.trim());
String temp = sb.toString().substring(38);
Log.v("XML TO String", "" + temp);
Log.v("Lengths : ", "" + temp.length() + " " + sb.length());
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I have been getting string in the Log, but it seems to be stopping abruptly in the middle.
For e.g. I am supposed to get records string like this. Beginning and ending with database tag.
<database name="DAR.db"><table name="DARWorkDetails"><row><col name="id">1</col><col name="date">05-28-2013</col><col name="visited_city_ID">1264</col><col name="employee_ID">107</col><col name="work_type_ID">1</col><col name="name">null</col><col name="customer_Id">null</col><col name="customer_type_ID">null</col><col name="sub_customer_id">null</col><col name="reason_ID">14</col><col name="reason">ABM SM MEETING</col><col name="remarks">gfhii</col><col name="work_with">211,162</col><col name="IsCustomer">N</col><col name="created_by">107</col><col name="position_id">72</col><col name="designation_Id">3</col><col name="submit_date">05-28-2013</col><col name="IsFinal">null</col></row></table></database>
Instead i have been getting string like this :
<database name="DAR.db"><table name="DARWorkDetails"><row><col name="id">1</col><col name="date">05-28-2013</col><col name="visited_city_ID">1264</col><col name="employee_ID">107</col><col name="work_type_ID">1</col><col name="name">null</col><col name="customer_Id">null</col><col name="customer_type_ID">null</col><col name="sub_customer_id">null</col><col name="reason_ID">14</col><col name="reason">ABM SM MEETING</col><col name="remarks">gfhii</col><col name="work_with">211,162</col><col name="IsCustomer">N</col><col name="created_by">107</col><col name="position_id">72</col><col name="designation_Id">3</col><col name="submit_date">05-28-2013</col><col name="IsFinal">null</co
The String is stopping in the middle. For the sake of example i have only put small example string above. In reality my database has multiple records and i have counted length of the string to around 15640, before abrupt end of the string.
Are there any limitations with StringBuilder in regards to storing characters? I suppose there is memory issue since i have been able to get string fully for records fewer than 10. Problem seems to be arising when records go into upwards of 10. Any help in understanding of solving this issue would be much appreciated.
Please check
It may happen your output is perfect but your Log cat is not displaying it whole.
Log.v("XML TO String", "" + temp);
Log.v("Lengths : ", "" + temp.length() + " " + sb.length());
See reference
I created this class to read strings from a xml file saved in internal storage device, it returns a list , if you want the whole extended string you only need concatenate to link together, if doesn't found the file return an empty list this is all you need to read XML files and parse to Strings, I hope to help!
public class readXMLFile {
private String filePath = "FileStorage";
private String fileName = "File.xml";
private final String tag = "Internal Read Persistence";
File internalFileData;
public readXMLFile() {// default constructor
}
public File getXMLFile(Context context){
File directory = null;
ContextWrapper cw = new ContextWrapper(context);
directory = cw.getDir(filePath, Context.MODE_PRIVATE);
internalFileData = new File(directory, fileName);
if(internalFileData.exists()){
Log.i("ReadXMLFile","File returned");
return internalFileData;
}
else{
Log.i(tag,"the file doesn't exists!");
return null;
}
}
public List<String> readFile(Context context) {
List<String> l = new LinkedList<String>();
try {
File directory = null;
ContextWrapper cw = new ContextWrapper(context);
directory = cw.getDir(filePath, Context.MODE_PRIVATE);
internalFileData = new File(directory, fileName);
if (internalFileData.exists()) {
Log.i("Internal Data", "the root exists!!");
try {
FileInputStream fis = new FileInputStream(internalFileData);
DataInputStream in = new DataInputStream(fis);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = br.readLine()) != null) {
l.add(line);
}
try {
if (in != null) {
in.close();
}
} catch (Exception e) {
Log.i(tag, "Exception closing persistence connection");
}
} catch (Exception e) {
Log.wtf("Fatal Exception", "Exception: " + e.getMessage());
}
} else {
Log.i(tag, "File doesn't exists");
return l;//return empty list
}
} catch (Exception e) {
Log.wtf(tag, "Exception DATA READING: " + e.getMessage());
return l;
}
Log.i(tag, "file found return");
return l;
}
}

How to computer CRC32/MD5 of a specific file withing my APK

I want to calculate the CRC or MD5 of a specific file (Activity) in my Application (within my APK) so that I can compare that value in another file and make sure that the first file has not been tampered with.
Can I do that? Is so, can you guide me with it?
Example:
Let say I have file A.java and B.java. I want to calculate A.java CRC32/MD5 and store this value in B.java so that when B.java executes it recalaculates A.java and compares it to the known value
You can't do this. There are no separate class files on Android, you get a single DEX file with all classes and libraries compiled in. You have to compute the hash of the classes.dex file and store it in a resource file, because putting it in a class file will change the overall hash value. However, if I decompile your app and changes your classes.dex, I can also changes the resources, so that doesn't really offer any real protection. Of course, you can try to obfuscate or hide the value to make it harder, but some tools will look for CRC/MessageDigest references and simply hook them to return the same value every time.
Get the contents of A.java into a string using a java.io.BufferedReader and proceed as follows:
public byte[] getMD5(String fileAContents) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(fileAContents.getBytes());
return messageDigest.digest();
}
public static void calculate(Context context) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
ZipInputStream fis = get(context);
System.out.println("fis: " + fis);
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
};
byte[] mdbytes = md.digest();
//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Digest(in hex format):: " + sb.toString());
//convert the byte to hex format method 2
StringBuffer hexString = new StringBuffer();
for (int i=0;i<mdbytes.length;i++) {
String hex=Integer.toHexString(0xff & mdbytes[i]);
if(hex.length()==1) hexString.append('0');
hexString.append(hex);
}
System.out.println("Digest(in hex format):: " + hexString.toString());
if(fis!=null){
fis.close();
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static ZipInputStream get(Context context){
// Get the path to the apk container.
String apkPath = context.getApplicationInfo().sourceDir;
JarFile containerJar = null;
try {
// Open the apk container as a jar..
containerJar = new JarFile(apkPath);
// Look for the "classes.dex" entry inside the container.
ZipEntry zzz = containerJar.getEntry("classes.dex");
// If this entry is present in the jar container
if (zzz != null) {
System.out.println("long " + zzz.getCrc());
// Get an Input Stream for the "classes.dex" entry
InputStream in = containerJar.getInputStream(zzz);
ZipInputStream zin = new ZipInputStream(in);
return zin;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (containerJar != null)
try {
containerJar.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}

How do I download a image file from google webapp engine?

AppEngineFile AFE = new AppEngineFile(FILESYSTEM + alist.get(0).getPath());
BlobKey bk = FileServiceFactory.getFileService().getBlobKey(AFE);
if("image/jpeg".equals(alist.get(0).getContentType()) ){
resp.setContentType("image/jpeg");
}
resp.setHeader("Content-Disposition", "attachment; filename=\"" + alist.get(0).getTitle() + "\"");
FileService fileService = FileServiceFactory.getFileService();
AppEngineFile file = null;
try {
file = fileService.getBlobFile(bk);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
FileReadChannel ch = null;
try {
ch = fileService.openReadChannel(file, false);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (LockException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
byte[] barray = new byte[MAXSIZE];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ByteBuffer bb = ByteBuffer.wrap(barray);
int nRead;
while ((nRead=ch.read(bb)) != -1) {
for (int i=0; i < nRead; i++) {
try {
baos.write(barray[i]);
} catch (Exception e) {
e.printStackTrace();
}
}
bb.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
resp.setContentLength(baos.size());
// resp.getOutputStream().write(baos.toByteArray()); // <= if I use it, this message, "Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found.", is showed.
// out.print(baos); // <= if I use this, I can download a file but it is byte code.
baos.flush();
baos.close();
How do I fix whole this code for downloading an image file? because If I use Number 1, it make a error, which is "Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found.", is showed." or if i use number 2, it looks fine but the type of stored file is byte code. This means is not image file.
Who can give me any idea or example?
I ran into this problem a while back. You cannot read files uploaded with the application. They are considered static application blobs and do not exist in any way accessible to your code.
Take a look here and notice that the only available option right now is BLOBSTORE.
If you want something to be readable by application code, it must be stored in the Blobstore or as a BlobProperty on an object in the Datastore (which is very inefficient, use the Blobstore if you can).

Categories