browse by category or date

This trick is useful for handling suspicious emails. By looking on its header, we can see from which IP address the email was sent.

  1. Double click the email to make it open in a new window
  2. Click the Tags button
    OUTLOOK_2016-03-29_00-20-49

OUTLOOK_2016-03-29_00-23-16

Using online WHOIS, we can find out more about the IP address:
chrome_2016-03-29_00-31-28

Whois result:
chrome_2016-03-29_01-21-02

If you really have nothing to do, you can submit complaint to the ISP of that naughty IP address. But very likely, the PC on that IP address is just a dummy, and is a part of a BotNet.

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

Yesterday, I found myself in need of a TIFF image splitter. Reason: The scanner in my office didn’t allow me to retain the settings after a document scan. So every time I choose to ‘End Scanning’, the output image quality setting is reset to default. Which means I need change the output settings for each of document that I want to scan. The only way was to scan all documents at one go. That lead me to the situation where a TIFF splitter is needed.

A quick Google-search brought me to a simple, free and open-source program called Tiff Splitter. It is exactly the kind of program that I need. It is simple, and does its job well.

Because it does the job well, I become interested to find out how exactly Tiff Splitter works. Since it’s an open-source, I can immediately take a dive and learn.

TiffSplit_2016-01-28_15-16-40

After we click, select an input file, or, drop a file, the event handlers will eventually call processFile method.

private void processFile(string fileName)
{
   // ... SNIP ...
   
   _configs.inputFile = fileName;

   // Configure the extractor
   RetObj retObj = TiffSplitCode.Prepare(_configs, out numOfPages);
   
   // ... SNIP ...
   
   // Let user select pages to extract
   PageSelection ps = new PageSelection(numOfPages);
   ps.ShowDialog();
   _configs.fromPage = ps.PageFrom;
   _configs.toPage = ps.PageTo;
   _configs.doOverwrite = ps.OverwriteFiles;
   
   // ... SNIP ...
   
   // do the work in separate thread
   backgroundWorkerSplit.RunWorkerAsync(_configs);
}

On the worker thread it will do the splitting

private void backgroundWorkerSplit_DoWork(object sender, DoWorkEventArgs e)
{
	ConfObj input = e.Argument as ConfObj;  
	RetObj retObj = TiffSplitCode.Split(input, _updateProgress);
	e.Result = retObj;
}

The actual work was done by TiffSplitCode

public static RetObj Split(ConfObj input, UpdateProgress updateProgress)
{
	int numOfPages = input.toPage - input.fromPage + 1;                               
	// save each image
	for (int i = 0; i < numOfPages; i++)
	{
		_coder.Save(input.fromPage - 1 + i);
		// ... SNIP ...
	}
	// ... SNIP ...
}


Hmm, it looks simple. But who is _coder? How does it able to distinguish PDF, TIFF or JPG? Different format definitely requires different treatment right (or so I thought) ?

The secret is in Prepare and CoderFactory method.

public static RetObj Prepare(ConfObj input, out int numOfPages)
{
	// .. Snipped: Validate input file ..	

	// overwrite output type if the input is PDF
	if (ext.ToUpper() == ".PDF")
		input.outputType = OutputType.PDF;

	// create output coder
	_coder = CoderFactory(input.outputType);

	// open file
	numOfPages = _coder.LoadImage(input.inputFile);

	// prepare
	_coder.Prepare(input);

	return retobj;
}

static private ICoder CoderFactory(OutputType type)
{
	switch (type)
	{
		case OutputType.TIF:
			return new TiffCoder();
		case OutputType.JPG:
			return new JpegCoder();
		case OutputType.PDF:
			return new PDFCoder();
		default:
			throw new Exception("Unknown output format.");
	}
}


So now it's clear that the actual loading and splitting in classes which implement ICoder interface. So for Tiff, the work is done by TiffCoder

public class TiffCoder : ICoder
{
	private Image _image;
	private FrameDimension _dim;
	
	// ... SNIP ...

	public int LoadImage(string fileName)
	{
		_inputImageName = fileName;
		_image = Image.FromFile(fileName);
		Guid guid = _image.FrameDimensionsList[0];
		_dim = new FrameDimension(guid);
		return _image.GetFrameCount(_dim);
	}


	public void Save(int pageNum)
	{
		_image.SelectActiveFrame(_dim, pageNum);
		string outputFileName = null;

		// ... SNIP: Output file name

		if (!_config.doOverwrite)
		{
			outputFileName = HelperMethods.ModifyFileName(outputFileName);
		}

		_image.Save(outputFileName);
	}

	// ... SNIP ...
}


Well that's interesting. The program actually uses .NET's System.Drawing.Image instead of some external library to handle TIFF. As a dig deeper, I found out that System.Drawing is actually a managed interface to Windows' native library, GDI+ (mind blown!)

I'll stop my exploration here, perhaps in the future I'll have the motivation to dig deeper than today. For more reading please check the following references:

  1. System.Drawing.Image source code
  2. brief introduction to GDI
  3. Microsoft GDI+ page

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

Found via HN, rephrased for future reminder:

  1. Do not repeat yourself, always refactor/reuse, avoid copy-paste
  2. Name your variables for what they are for, not its type of data
  3. Name your methods for what they are going to do
  4. Don’t use magic number or string literals, use constants or readonly variables
  5. Strive to make your method testable (unit test, dependency injection, mock object)
  6. Don’t be afraid to ask for help
  7. See a bug? Fix it while you’re there, then move on
  8. Share your knowledge, it will help the point no. 6
  9. Don’t interrupt colleagues who are ‘in the flow’, related to point no. 6
  10. Take criticism with open-mind, defensive stance might turn this into religious-wars

Original source: 10 golden rules for becoming a better programmer

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant: