GME  13
SvnLoginDlg.cpp
Go to the documentation of this file.
00001 // SvnLoginDlg.cpp : implementation file
00002 //
00003 
00004 #include "stdafx.h"
00005 #include "resource.h"
00006 #include "XmlBackEnd.h"
00007 #include ".\SvnLoginDlg.h"
00008 #include <io.h>
00009 #include <fstream>
00010 
00011 // SvnLoginDlg dialog
00012 
00013 IMPLEMENT_DYNAMIC(CSvnLoginDlg, CDialog)
00014 CSvnLoginDlg::CSvnLoginDlg( int p_prefChoice, CWnd* pParent /*=NULL*/)
00015         : CDialog(CSvnLoginDlg::IDD, pParent)
00016         , m_prefChoice( p_prefChoice)
00017         , m_aborted( false)
00018         , m_sshDisabled( false)
00019         , m_leftPad( 20)
00020         , m_rightPad( 20)
00021         , m_user(_T(""))
00022         , m_password(_T(""))
00023         , m_database(_T(""))
00024         , m_project(_T(""))
00025         , m_credRadioBtn(0)
00026 {
00027 }
00028 
00029 CSvnLoginDlg::~CSvnLoginDlg()
00030 {
00031 }
00032 
00033 void CSvnLoginDlg::DoDataExchange(CDataExchange* pDX)
00034 {
00035         CDialog::DoDataExchange(pDX);
00036         DDX_Text(pDX, IDC_EDIT_USER, m_user);
00037         DDX_Text(pDX, IDC_EDIT_PWD, m_password);
00038         DDX_Text(pDX, IDC_STATIC_DATABASE, m_database);
00039         DDX_Text(pDX, IDC_STATIC_PROJECT, m_project);
00040         DDX_Control(pDX, IDC_RADIO_CACHED, m_radBtnLoginMethod);
00041         DDX_Control(pDX, IDC_EDIT_USER, m_userCtrl);
00042         DDX_Control(pDX, IDC_EDIT_PWD, m_passwordCtrl);
00043         DDX_Control(pDX, IDC_LOADFROMCACHE, m_btnLoadFromCache);
00044         DDX_Radio(pDX, IDC_RADIO_CACHED, m_credRadioBtn);
00045 }
00046 
00047 
00048 BEGIN_MESSAGE_MAP(CSvnLoginDlg, CDialog)
00049         ON_WM_SIZE()
00050         ON_BN_CLICKED(IDC_ABORT, OnBnClickedAbort)
00051         ON_BN_CLICKED(IDC_RADIO_USPW, OnBnClickedRadioUspw)
00052         ON_BN_CLICKED(IDC_RADIO_CACHED, OnBnClickedRadioCached)
00053         ON_BN_CLICKED(IDC_RADIO_PPK, OnBnClickedRadioPpk)
00054         ON_BN_CLICKED(IDC_LOADFROMCACHE, OnBnClickedLoadFromCache)
00055 END_MESSAGE_MAP()
00056 
00057 
00058 // CSvnLoginDlg message handlers
00059 
00060 void CSvnLoginDlg::OnSize(UINT nType, int cx, int cy)
00061 {
00062         CDialog::OnSize(nType, cx, cy);
00063 
00064         CWnd * db = GetDlgItem( IDC_STATIC_DATABASE);
00065         CWnd * pj = GetDlgItem( IDC_STATIC_PROJECT);
00066         CRect db_rect, pj_rect;
00067         if( db && pj && db->GetSafeHwnd() && pj->GetSafeHwnd()) {
00068                 db->GetWindowRect( &db_rect);
00069                 pj->GetWindowRect( &pj_rect);
00070                 ScreenToClient( &db_rect);
00071                 ScreenToClient( &pj_rect);
00072                 int width = cx - m_leftPad - m_rightPad;
00073 
00074                 db->SetWindowPos( NULL, m_leftPad, db_rect.top, width > 20? width: 20, db_rect.Height(), SWP_NOZORDER);
00075                 pj->SetWindowPos( NULL, m_leftPad, pj_rect.top, width > 20? width: 20, pj_rect.Height(), SWP_NOZORDER);
00076         }
00077 }
00078 
00079 BOOL CSvnLoginDlg::OnInitDialog()
00080 {
00081         CDialog::OnInitDialog();
00082         
00083         m_credRadioBtn = m_prefChoice;
00084 
00085         // turn off ppk in all cases except svn+ssh
00086         CWnd* ppk = GetDlgItem( IDC_RADIO_PPK);
00087         if( ppk) ppk->EnableWindow( !m_sshDisabled); // enable also if no url to decide upon
00088 
00089         m_passwordCtrl.EnableWindow( m_credRadioBtn == 1);//either 0 or 2, m_radBtnLoginMethod.GetCheck() != BST_CHECKED);
00090         m_btnLoadFromCache.EnableWindow( m_credRadioBtn == 0);
00091 
00092         // wm_size related calculations
00093         CWnd * db = GetDlgItem( IDC_STATIC_DATABASE);
00094         CRect db_rect;
00095         if( db && db->GetSafeHwnd()) {
00096                 db->GetWindowRect( &db_rect);
00097                 ScreenToClient( &db_rect);
00098 
00099                 CRect win_rect;
00100                 GetWindowRect( &win_rect);
00101                 ScreenToClient( &win_rect);
00102 
00103                 m_leftPad = db_rect.left - win_rect.left;
00104                 m_rightPad = win_rect.right - db_rect.right;
00105         }
00106 
00107         UpdateData(FALSE); // send data modifications to controls
00108 
00109         return TRUE;  // return TRUE unless you set the focus to a control
00110         // EXCEPTION: OCX Property Pages should return FALSE
00111 }
00112 
00113 void CSvnLoginDlg::OnBnClickedRadioUspw()
00114 {
00115         m_passwordCtrl.EnableWindow( TRUE);
00116         m_btnLoadFromCache.EnableWindow( FALSE);
00117 }
00118 
00119 void CSvnLoginDlg::OnBnClickedRadioCached()
00120 {
00121         m_passwordCtrl.EnableWindow( FALSE);
00122         m_btnLoadFromCache.EnableWindow( TRUE);
00123 }
00124 
00125 void CSvnLoginDlg::OnBnClickedRadioPpk()
00126 {
00127         m_passwordCtrl.EnableWindow( FALSE);
00128         m_btnLoadFromCache.EnableWindow( FALSE);
00129 }
00130 
00131 void CSvnLoginDlg::OnBnClickedAbort()
00132 {
00133         m_aborted = true;
00134         EndDialog( IDCANCEL);
00135         //throw hresult_exception( E_FAIL);
00136 }
00137 
00138 bool CSvnLoginDlg::wasAborted()
00139 {
00140         return m_aborted;
00141 }
00142 
00143 void CSvnLoginDlg::disableSshOption()
00144 {
00145         m_sshDisabled = true;
00146 }
00147 
00148 bool CSvnLoginDlg::getDataFromCache( const std::string& p_inRealm, std::string& p_realm, std::string& p_uname)
00149 {
00150 // analyzing files as "C:\Documents and Settings\zolmol\Application Data\Subversion\auth\svn.simple\f061142afd1f61e24960515448599a09" 
00151 // with sample content below
00152         const char* svn_sim_path = "\\Subversion\\auth\\svn.simple";
00153         char        app_data_path[ _MAX_PATH];
00154         if( !SHGetSpecialFolderPath( NULL, app_data_path, CSIDL_APPDATA, true)) //most likely C:\Documents and Settings<username>\Application Data
00155                 return false;
00156 
00157         if( 1)
00158         {
00159                 char                 buf[_MAX_PATH];
00160                 _finddata_t          fileInfo;
00161 
00162                 sprintf( buf, "%s%s\\*.", app_data_path, svn_sim_path);
00163 
00164                 long searchHandle = _findfirst( buf, &fileInfo );
00165                 long ret = searchHandle;
00166                 while( ret != -1 )
00167                 {
00168                         sprintf( buf, "%s%s\\%s", app_data_path, svn_sim_path, fileInfo.name );
00169 
00170                         std::string _realm;
00171                         std::string _uname;
00172                         if( loadCacheFile( buf, _realm, _uname))
00173                         {
00174                                 std::string::size_type co_pos = _realm.find( ':');
00175                                 std::string::size_type rb_pos = _realm.find( '>');
00176                                 if( co_pos != std::string::npos && rb_pos != std::string::npos && co_pos < rb_pos)
00177                                         rb_pos = co_pos; // colon found indicating port number, so will cut right there
00178 
00179                                 if( rb_pos != std::string::npos && _realm[0] == '<')
00180                                 {
00181                                         _realm = _realm.substr( 1, rb_pos - 1);
00182                                         if( p_inRealm.substr( 0, _realm.length()) == _realm) // found
00183                                         {
00184                                                 p_realm = _realm;
00185                                                 p_uname = _uname;
00186                                                 return true;
00187                                         }
00188                                 }
00189                         }
00190                         
00191                         ret = _findnext( searchHandle, &fileInfo );
00192                 }
00193                 _findclose( searchHandle );
00194         }
00195 
00196         return false;
00197 }
00198 
00199 bool CSvnLoginDlg::loadCacheFile( const char* p_fileNamePtr, std::string& p_realm, std::string& p_uname)
00200 {
00201 // sample content of a cache file:
00202 //...
00203 //K 15 
00204 //svn:realmstring
00205 //V 68
00206 //<https://svn.isis.vanderbilt.edu:443> testrepo username and password
00207 //K 8
00208 //username
00209 //V 7
00210 //zolmol2
00211 //END 
00212 
00213         std::string value_realmstring;
00214         std::string value_username;
00215         bool        collecting_realmstring = false;
00216         bool        collecting_username    = false;
00217         bool        found_realmstring      = false;
00218         bool        found_username         = false;
00219 
00220         enum TypeOfLine
00221         {
00222                 KEY_INDICATOR
00223                 ,VAL_INDICATOR
00224                 ,KEY_STRING
00225                 ,VAL_STRING
00226         };
00227 
00228         TypeOfLine t_of_ln = VAL_STRING;
00229         TypeOfLine t_of_prev_ln;
00230         {
00231                 std::ifstream datafile;
00232                 datafile.open( p_fileNamePtr, std::ios_base::in);
00233                 if( datafile.is_open())
00234                 {
00235                         char buff[1024];
00236                         while( datafile.getline( buff, 1024))
00237                         {
00238                                 std::string line( buff);
00239                                 if( line.empty())
00240                                         continue;
00241 
00242                                 t_of_prev_ln = t_of_ln;
00243                                 
00244                                 if( line.substr( 0, 2) == "K ")
00245                                         t_of_ln = KEY_INDICATOR;
00246                                 else if( line.substr( 0, 2) == "V ")
00247                                         t_of_ln = VAL_INDICATOR;
00248                                 else if( t_of_prev_ln == KEY_INDICATOR)
00249                                         t_of_ln = KEY_STRING;
00250                                 else if( t_of_prev_ln == VAL_INDICATOR)
00251                                         t_of_ln = VAL_STRING;
00252 
00253                                 if( t_of_ln == KEY_STRING && 0 == line.find( "svn:realmstring"))
00254                                 {
00255                                         collecting_realmstring = true;
00256                                 }
00257                                 else if( t_of_ln == KEY_STRING && 0 == line.find( "username"))
00258                                 {
00259                                         collecting_username = true;
00260                                 }
00261 
00262                                 if( t_of_ln == VAL_STRING)
00263                                 {
00264                                         if( collecting_realmstring)
00265                                                 value_realmstring = line, collecting_realmstring = false, found_realmstring = true;
00266                                         if( collecting_username)
00267                                                 value_username = line, collecting_username = false, found_username = true;
00268                                 }
00269                         }
00270                 }
00271                 datafile.close();
00272         }
00273 
00274         if( found_realmstring && found_username && !value_realmstring.empty() && !value_username.empty())
00275         {
00276                 p_realm = value_realmstring;
00277                 p_uname = value_username;
00278                 return true;
00279         }
00280 
00281         return false;
00282 }
00283 
00284 void CSvnLoginDlg::OnBnClickedLoadFromCache()
00285 {
00286         std::string uname;
00287         if( getDataFromCache( (LPCTSTR) m_database, std::string(), uname))
00288         {
00289                 m_user = uname.c_str();
00290                 UpdateData( FALSE);
00291                 m_userCtrl.SetFocus(); // set the focus back to the username to allow a quick 'Enter' to be hit
00292                 m_userCtrl.SetSel( 0, m_userCtrl.LineLength());
00293         }
00294         else
00295                 AfxMessageBox( "Cached credentials were not found for this server!");
00296 }