2012-12-16

Ngày cuối năm ...


Ngày cuối năm,

Cũng những ngày này cách đây 4 năm mình đã xin nghỉ công ty mà mình đã làm việc 3 năm, vào đúng 1 ngày trước dịp xét tăng lương. Mọi người kêu sao không đợi qua Tết để nhận thưởng; mình cũng biết chứ, chỉ là cảm thấy rằng ko đợi được. 1 tháng lương đó + tiền tăng lương không đáng giá bằng việc hết phải chán nản từ nhà đi đi về về E-town suốt 2,3 tháng. Lúc đó mình đã từng viết rằng sẽ kiếm một cái gì đó vui vẻ để làm và cố gắng kiếm tiền còn những công việc buồn chán thì kệ nó.

Nói thì nói vậy nhưng hình như sau đó mình chỉ theo vế đầu. Không làm việc cho một công ty nào cả. Bạn bè kêu rằng mình  "lười" nhưng nghĩ lại mình đâu có lười, cũng làm từ trưa tới tối khuya, chỉ là lệch thời gian thôi. Thời gian rồi cũng trôi nhanh dù là làm "tạm bợ", hết tiền thì kiếm việc làm có tiền thì từ từ :D, rồi việc này việc khác, cũng vẫn đủ sống...

1 thời gian theo đuổi những không khí gọi là "mới so với trước đây" + thất bại trong việc mở quán game mất 1 số tiền cũng khá nhiều ... mình xác định mình sẽ lại đi làm thuê. Dù gì làm thuê vẫn còn có tiền đều đặn hàng tháng mà cũng nhẹ đầu hơn, đã vậy còn ra đường và ăn cơm trưa đều đặn hơn. Mình search trên 1 vòng, activate lại account trên mấy trang kiếm việc, rồi chuẩn bị CV dù chưa định gửi đi đâu. Quay qua quay lại cũng chỉ thấy E-Town, Quang Trung ... Lại lần nữa không cảm thấy thoải mái rồi từ chối các offer gọi đến.

Sau đó theo lời gọi của sếp và bạn bè cũ, mình về làm lại ở công ty trước đây, bên đó đang làm 1 số sp mới. Lúc đầu về thì cũng nhiều ý tưởng lắm, công ty cũng đã phát triển hơn. Nhưng rút cuộc 1 thời gian thì cũng chỉ làm 1 mình, phát triển mấy cái sản phẩm mà cuối cùng chẳng ai dùng. Việc thay đổi thói quen của người dùng không hề đơn giản. Năm đó đăng ký học chuyển đổi, rồi cưới vợ. Mọi việc cứ dần trôi qua ... và có lẽ đó là hai chuyện có thể coi là thành công trong năm. 1 năm sau công ty cũ "phá sản". Không phải phá sản theo nghĩa hết tiền, căn bản không phải do thiếu tiền mà thiếu hướng đi và thất bại trong định hướng. Những ngày cuối sếp có hỏi nên giữ lại nhiều developer không, mình nghĩ nên thông báo cho họ kiếm việc mới. Rồi sau đó công ty dọn VP sang Q.7, mình lại ở nhà làm, từ từ mất lửa và bỏ hẳn những việc làm dở version cho iOS, Android... Ý tưởng tốt thì sếp có nhưng có lẽ sếp nghĩ sai về IT. Nó không dễ đến nỗi ai cũng có thể làm và càng không phải là muốn làm gì thì làm. Quan trọng mình nghĩ chỉ đầu tư sơ sài trong khi mong muốn có 1 sản phẩm mang lại tiền là điều không thể.

Thời gian đó mình cũng về xem lại việc làm trong công ty đã cùng mở với thằng bạn. Dù gì công ty cũng có 1 chữ tên mình... 6 tháng sau tự nghĩ mình vẫn chưa thể giúp gì cho nó phát triển hơn mà công việc này giúp mình chán nản hơn và "ít tiền hơn" (tất nhiên)... mình lại tạm thời ra đi. Vẫn chưa thấy hướng đi và làm 1 công ty mà vẫn phải kiếm tiền chỗ khác để sống thì cũng ko khoái, cảm thấy không focus được. Lần thứ 2 lại chuẩn bị CV (update lại tình trạng hôn nhân), lại search và lại cảm thấy 1 chút gì đó lưỡng lự. Không phải sợ rằng mình không đáp ứng được công việc nhưng sợ rằng mình không phải là người thuộc 1 tổ chức nào đó. Đã 3 năm hầu không dậy sớm, công việc 1 mình, schedule chỉ có mỗi tên mình, không daily report... Công ty là một từ gì đó xa lạ và mình vẫn chần chờ...

Với tâm trạng đó xui rủi thế nào mình lại gặp 1 công ty làm 1 sp mới. Và bây giờ khoảng 1 năm sau ... lần thứ 3 nghĩ rằng mình sẽ chuẩn bị CV. Lần này là vì tiền, thời gian và quan trọng là cảm thấy không thoải mái. Đầu tiên, tiền là một phần quan trọng kéo nhiều thứ khác đi xuống, tất nhiên không phải là tất cả. Mình nghĩ mình không thể nào tiếp tục làm nếu quá tốn thời gian mà thu nhập lại không ổn định, không có đủ niềm tin. Mình có thể không nhận gì 1 thời gian nhất định. Nhưng cả team thì khác, tới tháng chưa nhận lương thì tinh thần xuống thảm, không thể làm gì trong cái không khí như vậy. Quan trọng hơn là cảm thấy thời gian trôi qua mà không làm được gì. Cảm thấy mất dần niềm tin từ gia đình người thân- những người đã tôn trọng lựa chọn của mình khi mình đã đánh đổi hướng đi này với những hướng đi khác.

Rút cuộc nhìn lại mình nhận thấy mình đang trốn chạy? Trốn chạy công việc đã từng làm là outsourcing, trốn chạy E-Town, Quang Trung, CNC... Nhìn lại mình thích làm cái gì đó khác, bị hấp dẫn bởi nhưng dự án làm sp mới. Mình cũng nhận ra những gì mình gặp thuộc 2 dạng có tiền thì lại không có những thứ khác (nhân sự cùi, kế hoạch, tiếp cận khách hàng) và ngược lại 1 số có thể làm được cái gì đó (chí ít cũng có người cho là vậy) thì lại không có tiền. Tất nhiên sống bằng niềm tin không xấu, chỉ có điều mình không nhận thấy những căn cứ mình có đủ để tin. Tóm lại là chưa đủ tầm và chưa đủ tài, mà ko dám đối mặt. Còn gia đình và nhiều thứ khác cần tiền... 3-4 năm trời không làm được gì, 4-5 tháng không có lương, mượn tiền vợ và bỏ ra cả vài trăm triệu :(. Không làm IT nữa thì bỏ việc và cũng không cần ở tp này nữa???

Cuối cùng năm 2012, nếu không tận thế thì mình vẫn sẽ theo những gì đã viết 4 năm trước nhưng có lẽ sẽ phải hành động khác.

2012-12-11

Windows Shell Extensions


Lâu lắm mới viết lại shell extension ...
Để viết Shell extensions thì có nhiều tutorials ko cần phải nói nữa, search 1 vòng trên CodeProject có thể list ra như series http://www.codeproject.com/Articles/441/The-Complete-Idiot-s-Guide-to-Writing-Shell-Extens hoặc các ví dụ trên CodePlex http://1code.codeplex.com/wikipage?title=WinShell

Hầu hết các ví dụ này dùng ATL, tất nhiên vậy cũng OK. Nhưng có 1 cách tiếp cận hay khá linh động viết COM bình thường không dùng ATL cần note lại là của TortoiseSVN. Đơn giản có thể tóm tắt như sau: ví dụ cần wrap 1 số shell extensions vào 1 chỉ DLL hoặc sử dụng trong trường hợp cần nhiều icon overlays mỗi cho 1 trạng thái của file như syncing, synced, do handler chỉ xử lý bằng IsMemberOf có nghĩa là chỉ xác định có/không hiển thị icon nên phải có 2 CLSID cho 2 trạng thái file.

Giả sử cần 2 icon overlay handlers cho syncing, synced và 1 context menu. Class xử lý icon overlay là IconOverlayExt và class xử lý context menu là ContextMenuExt. IconOverlayExt xử lý hiển thị hay không 2 trạng thái syncing và synced. Ta có các CLSID tương ứng CLSID_Synced, CLSID_Syncing, CLSID_ContextMenu.

Khai báo một enum xác định extension cần tạo:


enum ExtensionState
{
       Invalid,
       IconSynced,
       IconSyncing,
       ContextMenu
};


ShellExtClassFactory chịu trách nhiệm tại ext tùy theo loại ext cần tạo, nhận 1 ExtensionState là member


// This class factory object creates the main handlers -
// its constructor says which OLE class it has to make.
class ShellExtClassFactory : public IClassFactory
{
protected:
    ULONG _refCount;
    // Variable to contain class of object (i.e. syncing, synced, context menu)
    ExtensionState _stateToMake;
      
public:
    ShellExtClassFactory(ExtensionState stateToMake);
    virtual ~ShellExtClassFactory();
      
       // IUnknown members
    STDMETHODIMP         QueryInterface(REFIID, LPVOID FAR *);
    STDMETHODIMP_(ULONG) AddRef();
    STDMETHODIMP_(ULONG) Release();
   
       // IClassFactory members
    STDMETHODIMP           CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *);
    STDMETHODIMP           LockServer(BOOL);
};


Như vậy code DllGetClassObject như sau:


STDAPI DllGetClassObject(const CLSID& rclsid, const IID& riid, void** ppv)
{
       if(ppv == 0)
       {
              return E_POINTER;
       }

       *ppv = NULL;

       // State to get factory
       ExtensionState stateToMake = ExtensionState::Invalid;
       if (IsEqualIID(rclsid, CLSID_Synced))
       {
              stateToMake = ExtensionState::IconSynced;
       }
       else if (IsEqualIID(rclsid, CLSID_Syncing))
       {
              stateToMake = ExtensionState::IconSyncing;
       }
       else if (IsEqualIID(rclsid, CLSID_ContextMenu))
       {
              stateToMake = ExtensionState::ContextMenu;
       }

       if (stateToMake != ExtensionState::Invalid)
       {
              ShellExtClassFactory *classFactory = new (std::nothrow)ShellExtClassFactory(stateToMake);
              if (classFactory == NULL)
              {
                     return E_OUTOFMEMORY;
              }

              // IMPORTANT NOTE: ref count set to 0 at this moment -> do not call Release
              // If your ClassFactory object's reference count initialize with 0, DO NOT call the release method,
              // it seems the COM library would call the release method automatically.
              // Otherwise, you'd get an access exception.
              //
              // If ClassFactory initialize with ref count = 1 -> must call Release
              // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms680760(v=vs.85).aspx
              const HRESULT hr = classFactory->QueryInterface(riid, ppv);
              if (FAILED(hr))
              {
                     delete classFactory;
              }            

              return hr;
       }

       return CLASS_E_CLASSNOTAVAILABLE;
}

NOTE: ở đây cũng lưu ý code COM trong TortoiseSVN khác với code mẫu ClassFactory hay COM hay thấy như trong MSDN chẳng hạn, sau khi QueryInterface sử dụng xong thường gọi Release tuy nhiên reference count TortoiseSVN init là zero trong khi ví dụ thông thường init là 1. Xem thêm http://msdn.microsoft.com/en-us/library/windows/desktop/ms680760(v=vs.85).aspx

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{
    HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;

    if (IsEqualCLSID(CLSID_FileContextMenuExt, rclsid))
    {
        hr = E_OUTOFMEMORY;

        ClassFactory *pClassFactory = new ClassFactory();
        if (pClassFactory)
        {
            hr = pClassFactory->QueryInterface(riid, ppv);
            pClassFactory->Release();
        }
    }

    return hr;
}



Như vậy là OK đã có ClassFactory và ext cần tạo, trong CreateInstance


STDMETHODIMP ShellExtClassFactory::CreateInstance(LPUNKNOWN unkOuter,
       REFIID riid, LPVOID *out)
{
       if(out == 0)
       {
              return E_POINTER;
       }

       *out = NULL;

       // Shell extensions typically don't support aggregation (inheritance)     
       if (unkOuter)
       {
              return CLASS_E_NOAGGREGATION;
       }

       HRESULT hr;  
       if(_stateToMake == ExtensionState::ContextMenu)
       {
              // The shell will then call QueryInterface with IID_IShellExtInit--this
              // is how shell extensions are initialized.
              ContextMenuExt* contextMenu = new (std::nothrow)ContextMenuExt();  // create the ContextMenuExt object
              if (contextMenu == nullptr)
              {
                     return E_OUTOFMEMORY;
              }

              hr = contextMenu->QueryInterface(riid, out);
              if(FAILED(hr))
              {
                     delete contextMenu;
              }
       }
       else
       {
              // Create the main shell extension object.
              IconOverlayExt* iconOverlay = new (std::nothrow)IconOverlayExt(_stateToMake);  // create the IconOverlayExt object
              if (iconOverlay == nullptr)
              {
                     return E_OUTOFMEMORY;
              }

              hr = iconOverlay->QueryInterface(riid, out);
              if(FAILED(hr))
              {
                     delete iconOverlay;
              }
       }

       return hr;
}

Thêm std::nothrow để kiểm tra kết quả trả về thay vì nhận exception. Tại đây dựa vào ext cần tạo sẽ xử lý.

Còn 1 việc cần giải quyết là IPC giữa shell và app. Có thể dùng RPC, DLL shared segment cũng là 1 khả năng tuy nhiên phải cùng x86 hay 64-bit (app x86 chẳng hạn không thể load shell ext 64-bit), và named pipe có lẽ là hợp lý nhất.

Debug

Về debug chỉ có 1 lưu ý, nếu trong máy có install nhiều app có ext thì nên disable hay tạm thời uninstall. Giả sử máy bạn là developer hay cài TortoiseSVN thì tạm thời bỏ nó đi vì không thể nào debug được, lý do TortoiseSVN sẽ block ngay explorer khi reach break point đâu đó, khi đó chỉ có nước nhấn reset máy (cry).

Để tránh các app khác load ext: 1 số thằng rất hay load như Google Chrome, IDM và Skype trong DLL Attach code 1 đoạn như sau nếu có debugger hay là app test-shell của mình hoặc Explorer hay regsvr32 thì OK:

BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved)
{
#ifdef _DEBUG
       // If no debugger is present, then don't load the dll.
       // this prevents other apps from loading the dll and locking
       // it.

       bool isInShellTest = false;
       TCHAR fullPath[MAX_PATH + 1];       // MAX_PATH ok, the test really is for debugging anyway.
       DWORD len = GetModuleFileName(NULL, fullPath, MAX_PATH);
       TCHAR fileNameWithoutExt[MAX_PATH + 1];
       TCHAR ext[MAX_PATH + 1];
      
       _tsplitpath_s(fullPath, NULL, 0, NULL, 0, fileNameWithoutExt, MAX_PATH, ext, MAX_PATH);

       TCHAR fileName[MAX_PATH + 1];
       _tmakepath_s(fileName, MAX_PATH, NULL, NULL, fileNameWithoutExt, ext);

       if ((_tcsicmp(fileName, _T("test-shell.exe"))) == 0 || (_tcsicmp(fileName, _T("explorer.exe"))) == 0 ||
              (_tcsicmp(fileName, _T("verclsid.exe"))) == 0 || (_tcsicmp(fileName, _T("regsvr32.exe"))) == 0)
       {
              isInShellTest = true;
       }

       if (!::IsDebuggerPresent() && !isInShellTest)
       {
              return FALSE;
       }
#endif

       switch (reason)
       {
              ...
       }

       return TRUE;
}


Để có thể debug thực hiện:
Thêm Properties -> Build Events -> Post-Build Event:
Command Line: echo "Registering Icon Overlay Library" regsvr32 "$(TargetPath)"

Thêm Debugging
Command: explorer.exe

Để restart Explorer unload ext DLL không tắt bằng Taskbar Manager mà thực hiện
Ctrl + Shift + Right Click vào khoảng trống như hình bên dưới
















2012-10-22

PKCS#12 to GnuPG: Extract and import RSA key

X509 p12 (pfx) file và GnuPG (OpenPGP) không tương thích nhau. Tuy nhiên có thể export RSA key từ p12 file, convert rồi import vào gpg. Theo lý thuyết cả 2 đều thao tác trên public/private cryptography có dùng RSA.


Thực ra nếu xem xét ASCII-armored và PEM chúng ta sẽ thấy khá là giống nhau ngoại trừ BEGIN/END markers thì PGP còn có thêm 1 dòng (line cuối cùng) là checksum. Mình không rõ nhưng theo RFC 4880 là CRC24.

Ví dụ xem xét public key PGP ASCII-armored và RSA PEM

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (GNU/Linux)

mQINBE9NBIQBEADMSzN6b0FaPP0rGiLDWKfH4ehN66Z0SAIynXm6lBHjmO69pNsm
....
5NsttvIOclBY5A==
=Zqph
-----END PGP PUBLIC KEY BLOCK-----




-----BEGIN RSA PUBLIC KEY-----
mQINBE9NBIQBEADMSzN6b0FaPP0rGiLDWKfH4ehN66Z0SAIynXm6lBHjmO69pNsm
...
5NsttvIOclBY5A==
-----END RSA PUBLIC KEY-----

Tại Sysmic.org có chỉ cách convert từ OpenSSL sang GnuPG tuy nhiên là gpgsm (with S/MIME)

Có thể thực hiện như sau:
sudo apt-get install dirmngr
GPG_TTY="tty"
gpgsm --import -v file.p12

Tuy nhiên không thể dùng với gpg. Nếu làm manual thì có lẽ rất vất vả, phải nói là không khả thi. Để import RSA key từ OpenSSL sang GPG mình thực hiện như sau:

Extract private key with passphrase
openssl pkcs12 -in file.p12 -nocerts -out private.pem

Remove passphrase
openssl rsa -in private.pem -out rsa-private.key

Dùng pem2openpgp để convert sang OpenPGP với một string là $USERID (lưu ý install monkeysphere trước để có pem2openpgp)

PEM2OPENPGP_USAGE_FLAGS=authenticate,certify,sign pem2openpgp "Some desc for User ID <any@gmail.com>" < rsa-private.key | gpg --import

Lưu ý: biến môi trường PEM2OPENPGP_USAGE_FLAGS xác định usage là SCA, mặc định pem2openpgp sẽ convert với usage là certify.

gpg: key AC37D3E3: secret key imported

gpg: key AC37D3E3: public key "Some desc for User ID <any@gmail.com>" imported


gpg: Total number processed: 1

gpg:               imported: 1  (RSA: 1)
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

$ gpg --list-secret-keys
/home/xxxx/.gnupg/secring.gpg
------------------------------
sec   2048R/AC37D3E3 2012-10-22
uid                 

Some desc for User ID

<
any@gmail.com

>

Sau khi import xong nhớ thực hiện --edit-key với ID eg 
AC37D3E3 thực hiện enable và trust


2012-09-06

Linux - Embedding a file in an executable

Original http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967


Embedding a File in an Executable, aka Hello World, Version 5967


Jun 12, 2008  By Mitch Frazier

I recently had the need to embed a file in an executable. Since I'm working at the command line with gcc, et al and not with a fancy RAD tool that makes it all happen magically it wasn't immediately obvious to me how to make this happen. A bit of searching on the net found a hack to essentially cat it onto the end of the executable and then decipher where it was based on a bunch of information I didn't want to know about. Seemed like there ought to be a better way...
And there is, it's objcopy to the rescue. objcopy converts object files or executables from one format to another. One of the formats it understands is "binary", which is basicly any file that's not in one of the other formats that it understands. So you've probably envisioned the idea: convert the file that we want to embed into an object file, then it can simply be linked in with the rest of our code.
Let's say we have a file name data.txt that we want to embed in our executable:
  # cat data.txt
  Hello world
To convert this into an object file that we can link with our program we just useobjcopy to produce a ".o" file:
  # objcopy --input binary \
            --output elf32-i386 \
            --binary-architecture i386 data.txt data.o
This tells objcopy that our input file is in the "binary" format, that our output file should be in the "elf32-i386" format (object files on the x86). The --binary-architecture option tells objcopy that the output file is meant to "run" on an x86. This is needed so that ld will accept the file for linking with other files for the x86. One would think that specifying the output format as "elf32-i386" would imply this, but it does not.
Now that we have an object file we only need to include it when we run the linker:
  # gcc main.c data.o
When we run the result we get the prayed for output:
  # ./a.out
  Hello world
Of course, I haven't told the whole story yet, nor shown you main.c. When objcopydoes the above conversion it adds some "linker" symbols to the converted object file:
   _binary_data_txt_start
   _binary_data_txt_end
After linking, these symbols specify the start and end of the embedded file. The symbol names are formed by prepending _binary_ and appending _start or _end to the file name. If the file name contains any characters that would be invalid in a symbol name they are converted to underscores (eg data.txt becomes data_txt). If you get unresolved names when linking using these symbols, do a hexdump -C on the object file and look at the end of the dump for the names that objcopy chose.
The code to actually use the embedded file should now be reasonably obvious:
#include 

extern char _binary_data_txt_start;
extern char _binary_data_txt_end;

main()
{
    char*  p = &_binary_data_txt_start;

    while ( p != &_binary_data_txt_end ) putchar(*p++);
}
One important and subtle thing to note is that the symbols added to the object file aren't "variables". They don't contain any data, rather, their address is their value. I declare them as type char because it's convenient for this example: the embedded data is character data. However, you could declare them as anything, as int if the data is an array of integers, or as struct foo_bar_t if the data were any array of foo bars. If the embedded data is not uniform, then char is probably the most convenient: take its address and cast the pointer to the proper type as you traverse the data.
Mitch Frazier is an Associate Editor for Linux Journal.

2012-07-13

Compile OpenSSL with Visual Studio 2010


Download Perl, nasm, source OpenSSL -> chỉnh lại path trong file bat (copy trong link trên)

@rem @echo off
@cls

@rem 1. Download and unzip Netwide Assembler (http://nasm.us/) to some folder
@rem 2. Download and uzip Strawberry Perl (http://strawberryperl.com/)
@rem    or ActivePerl (http://www.activestate.com/activeperl/downloads)
@rem 3. Download and uzip (xxx.tar.gz) latest version of OpenSSL (http://www.openssl.org/)

@rem NOTE: For more info, please read INSTALL.W32 file in OpenSSL folder

@rem ***************************************************************
@rem Setup paths
@rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@set strPathNetwideAssembler=D:\workspace\nasm-2.09.10
@set strPathStrawberryPerl=D:\workspace\strawberry
@set strPathActivePerl=D:\workspace\Perl64\bin
@rem set strPathActivePerl=D:\workspace\Perl64\bin
@set strPathOpenSSLDir=D:
@set strPathOpenSSL=%strPathOpenSSLDir%\download\openssl-1.0.1c
@set strPathTargetOpenSSLDir=D:\workspace\openssl-1.0.1c
@set bEnableStaticEngine=True
@rem True -> the shared library build will compile the engines into libeay32.dll
@rem ***************************************************************

@IF NOT "%strPathNetwideAssembler%" == "" set PATH=%strPathNetwideAssembler%;%PATH%
@IF NOT "%strPathStrawberryPerl%" == "" set PATH=%strPathStrawberryPerl%\c\bin;

%strPathStrawberryPerl%\perl\site\bin;%strPathStrawberryPerl%\perl\bin;%PATH%
@IF NOT "%strPathActivePerl%" == "" set PATH=%strPathActivePerl%;%PATH%
@set strEnableStaticEngine=
@IF "%bEnableStaticEngine%"=="True" set strEnableStaticEngine=enable-static-engine

@rem START

@rem Create OpenSSL installation dir
@rmdir /S /Q %strPathTargetOpenSSLDir%
@mkdir %strPathTargetOpenSSLDir%
@echo OpenSSL will be installed into %strPathTargetOpenSSLDir%

@%strPathOpenSSLDir%
@cd %strPathOpenSSL%

@IF NOT "%strPathNetwideAssembler%" == "" call :ConfigureMakefileWithASM
@IF "%strPathNetwideAssembler%" == ""     call :ConfigureMakefileWithoutASM

@if "%VS100COMNTOOLS%" == "" goto ErrorNoVS2010
@call "%VS100COMNTOOLS%vsvars32.bat"

@cls
@echo ***************************************************************
@echo Compile OpenSSL
@echo ***************************************************************
@pause
@nmake -f ms\ntdll.mak
@echo ***************************************************************
@echo Compile OpenSSL DONE
@echo ***************************************************************
@echo .
@echo ***************************************************************
@echo Test OpenSSL
@echo ***************************************************************
@pause
@nmake -f ms\ntdll.mak test
@echo ***************************************************************
@echo Test OpenSSL DONE
@echo ***************************************************************
@echo .
@echo ***************************************************************
@echo install OpenSSL to the specified location (%strPathTargetOpenSSLDir%)
@echo ***************************************************************
@pause
@nmake -f ms\ntdll.mak install
@echo ***************************************************************
@echo install OpenSSL to %strPathTargetOpenSSLDir% DONE
@echo ***************************************************************
@pause

goto EOF



:ConfigureMakefileWithoutASM
@rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@rem Configure with platform VC-WIN32 but without Assembler and Build Makefiles
@rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@echo ***************************************************************
@echo Configure with platform VC-WIN32 but without Assembler
@echo ***************************************************************
@perl Configure VC-WIN32 no-asm %strEnableStaticEngine% --prefix=%strPathTargetOpenSSLDir%
@echo ***************************************************************
@echo Configure with platform VC-WIN32 but without Assembler. DONE
@echo ***************************************************************
@echo .
@echo ***************************************************************
@echo Build the Makefiles
@echo ***************************************************************
@call ms\do_ms.bat
@echo ***************************************************************
@echo Build the Makefiles DONE
@echo ***************************************************************
@pause
@cls
goto EOF

:ConfigureMakefileWithASM
@rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@rem Configure with platform VC-WIN32 and with Assembler, and Build Makefiles
@rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@echo ***************************************************************
@echo Configure with platform VC-WIN32 and Assembler
@echo ***************************************************************
perl Configure VC-WIN32 %strEnableStaticEngine% --prefix=%strPathTargetOpenSSLDir%
@echo ***************************************************************
@echo Configure with platform VC-WIN32 and Assembler. DONE
@echo ***************************************************************
@echo .
@echo ***************************************************************
@echo Build the Makefiles and optionally the assembly language files:
@echo ***************************************************************
@call ms\do_nasm.bat
@echo ***************************************************************
@echo Build the Makefiles DONE
@echo ***************************************************************
@pause
@cls
goto EOF

rem Errors
rem ***********************************************************
:ErrorNoVS2010
echo Visual Studio 2010 is not installed on your computer. Please install it and run this file again.
goto EOF

:EOF

LNK1181: cannot open input file ‘rpcndr.lib’

Mở đám code cũ COM ra, convert xong build bị cái lỗi này.

Note lại
Vào Linker bỏ rpcndr.lib tất nhiên vẫn giữ lại rpcrt4.lib
http://henbo.wordpress.com/2006/11/22/lnk1181-cannot-open-input-file-rpcndr-lib/

Compiling gcc on Mac OSX


Link hướng dẫn ở đây

Tạo link cho g++, gcc, cpp
cd /usr/bin
sudo ln -s /usr/local/g++ g++-4.2

Thêm -m32 hay -m64 vào export, không sẽ bị lỗi
checking for __gmpz_init in -lgmp... no
configure: error: libgmp not found or uses a different ABI.
Please read the INSTALL file -- see "In case of problem".

Thay export CXX như sau:
export CXX=/usr/bin/g++-4.2
chuyển thành
export CXX="/usr/bin/g++-4.2 -m32"

Nhanh hơn thì dùng macports
sudo port install gmp
sudo port install mpfr
sudo port install mpc

macports install vào /opt/local

2012-04-28

Một bản "cực kỳ" nháp syncing file (file storage)


Theo cách liệt kê thì tất cả các trường hợp có thể conflict:

Đối với file
Local
Remote
Notes
Created
Created
Type 1
Created
Modified
Hạn chế *
Created
Renamed
Hạn chế *
Created
Deleted
Hạn chế *
Created
Deleted container folder
Có thể không coi là conflict **
Modified
Created
logically
Modified
Modified
Type 2
Modified
Renamed
Type 2
Modified
Deleted
Type 3
Modified
Deleted container folder
Type 4
Renamed
Created
logically
Renamed
Modified
Type 2
Renamed
Renamed
Type 2
Renamed
Deleted
Type 3
Renamed
Deleted container folder
Type 4
Deleted
Created
logically
Deleted
Modified
Type 3
Deleted
Renamed
Type 3
Deleted
Deleted
Type 5
Deleted
Deleted container folder
Type 6

* hạn chế là trường hợp ít khả năng xảy ra, ví dụ Created – Modified là ít khả năng xảy ra, khi local tạo file mà không biết rằng remote đã tạo file, và không biết cả việc thay đổi nội dung file sau đó.
** trường hợp Created file vs Deleted parent folderCreated folder vs Deleted parent folder có thể không coi là conflict vì chúng ta sẽ phải luôn giữ các file mới tạo tại remote dù đã bị xóa tại local vì vấn đề an toàn (do local không biết nội dung file/folder mới tạo).
Notes: trường hợp loại bỏ là liệt kê theo logic và không tính là conflict à dạng Deleted vs CreatedModified (Renamed) vs Created à sẽ phải rơi vào trường hợp Created vs Created và phải giải quyết trước khi có thể xảy ra, implementation sẽ không để xảy ra những trường hợp này.

Đối với folder tương tự nhưng không có modified, chỉ còn trường hợp renamed
Local
Remote
Notes
Created
Created
Type 7
Created
Renamed
Hạn chế *
Created
Deleted
Hạn chế *
Created
Deleted container folder
Có thể không coi là conflict
Renamed
Created
logically
Renamed
Renamed
Type 8
Renamed
Deleted
Type 9
Renamed
Deleted container folder
Type 10
Deleted
Created
logically
Deleted
Renamed
Type 9
Deleted
Deleted
Type 11
Deleted
Deleted container folder
Type 12


Gom lại có tất cả 7 trường hợp conflict (cả case conflict)


1.       Created  file – Created file conflict

Tạo file khi không biết thông tin về file đã được tạo

2.       Modified file – Modified file conflict

Thay đổi nội dung file (kể cả đổi tên) khi không biết file đã bị thay đổi

3.       Modified file – Deleted file conflict

Thay đổi nội dung file (kể cả đổi tên) khi không biết chính file đó bị xóa

4.       Modified file – Deleted parent folder conflict

Thay đổi nội dung file (kể cả đổi tên) khi không biết folder chứa file (parent hoặc ancestor đã bị xóa)

5.       Deleted file – Deleted file conflict

Xóa file khi không biết chính file đã bị xóa

6.       Deleted file – Deleted parent folder conflict

Xóa file khi không biết folder chứa file (parent hoặc ancestor đã bị xóa)

7.       Case conflict

Trên Mac và Windows không phân biệt hoa thường trong khi trên Linux có phân biệt à case conflict giải quyết à force rename?
Dựa trên các trường hợp có thể detect conflict phân thành theo file và theo folder
DetectFileConflict(…) kiểm tra conflict từ 1 đến 6
DetectFolderConflict(…) kiểm tra conflict đối với folder

Phát hiện conflict

ü  Khi download notice changes từ server, pause sync, kiểm tra giữa 2 file list để xác định conflict về file với Type từ 1 đến 6.
ü  Khi thực hiện sync up lên server à phát hiện conflict do thực hiện thất bại và theo error code trả về.
Xét với từng loại
ü  Type 1: xác định cùng file name nhưng khác file size, modified date à conflict
ü  Type 2 & Type 3: Modified file vs Modified file và Modified file vs Deleted file
ü  Type 4: là conflict

ü  Type 5 & 6: có thể không coi là conflict

Startup syncing

Download server snapshot

Thực hiện download snapshot file và folder list trên server insert vào table snapshot tại client. Table snapshot giữ thông tin mới nhất về file và folder, chỉ download 1 lần khi start app. Table snapshot cấu trúc giống table signstore.
Table signstore dung để keep track thay đổi khi app running, mọi thay đổi nếu đã sync với server sẽ được update vào signstore.

Có thể dùng thuật toán Eugene Myers?

Tìm danh sách file chỉ có tại local và danh sách file chỉ có tại server?

Coi thông tin trong stored là chuẩn à tính diff của local files và server files để có thông tin thay đổi của local và server đối với stored.

Tính diff giữa local và stored à local deleted files, no changes và local added files.
Tính diff giữa server và stored à server deleted files, no changes và server added files.

Xử lý các trường hợp xảy ra như sau:



Giải thích:
1 + 4: local added
2 + 5: local both
3 + 6: local deleted
4 + 7: server added
5 + 6: server both
2 + 3: server deleted

1.      Local added (1 + 4)  và server added (4 + 7)

Local add bắt buộc sync up, server added bắt buộc sync down. Local va server cùng added à conflict.
1: created sync up
7: created sync down
4: conflict

2.      Local added (1 + 4) và server both (5 + 6) à không intersect

3.      Local added (1 + 4)  và server deleted (2 + 3) à không intersect

4.      Local both (2 + 5)  và server added (4 + 7) à không intersect

5.      Local both (2 + 5)  và server both (5 + 6) à không chọn vì cả 2 list cùng có nhiều items

Nếu có cả server và local kiểm tra modified cho phần 5: có cả tại local, stored và server
5: check modified

6.      Local both (2 + 5)  và server deleted (2 + 3)

2: deleted sync down
3: delete khỏi stored (có trong stored nhưng không có tại local và server)
5: check modified à làm cho case 5

7.      Local deleted (3 + 6)  và server added (4 + 7) à không intersect

8.      Local deleted (3 + 6)  và server both (5 + 6) à server both nhiều items

6: deleted sync up

9.      Local deleted (3 + 6)  và server deleted (2 + 3)

2: deleted sync down
3: không cần sync deleted à xóa khỏi stored
6: deleted sync up à làm cho case 8