GME  13
Util.cpp
Go to the documentation of this file.
00001 
00023 #include "../StdAfx.h"
00024 #include "../MsgConsole.h"
00025 
00026 #if(USESVN)
00027 
00028 #include ".\util.h"
00029 #include <iostream> // remove this later
00030 #include <fstream>
00031 #include <string>
00032 #include "svn_path.h"
00033 #include "svn_pools.h"
00034 #include <locale.h> // for LC_ALL
00035 
00036 //#define _ 
00037 
00042 bool Util::globalInit()
00043 {
00044         // this method has to be run only once during the run a 
00045     // programm
00046     static bool run = false;
00047     if(run) // already run
00048     {
00049                 return true;
00050     }
00051     run = true;
00052 
00053     apr_status_t status;
00054 
00055     /* C programs default to the "C" locale. But because svn is supposed
00056        to be i18n-aware, it should inherit the default locale of its
00057        environment.  */
00058     if (!setlocale(LC_ALL, ""))
00059     {
00060         if (stderr)
00061         {
00062             const char *env_vars[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
00063             const char **env_var = &env_vars[0], *env_val = NULL;
00064             while (*env_var)
00065             {
00066                 env_val = getenv(*env_var);
00067                 if (env_val && env_val[0])
00068                     break;
00069                 ++env_var;
00070             }
00071 
00072             if (!*env_var)
00073             {
00074                 /* Unlikely. Can setlocale fail if no env vars are set? */
00075                 --env_var;
00076                 env_val = "not set";
00077             }
00078 
00079             fprintf(stderr,
00080                   "%s: error: cannot set LC_ALL locale\n"
00081                   "%s: error: environment variable %s is %s\n"
00082                   "%s: error: please check that your locale name is correct\n",
00083                   "svnjavahl", "svnjavahl", *env_var, env_val, "svnjavahl");
00084         }
00085         return FALSE;
00086     }
00087 
00088     /* Initialize the APR subsystem, and register an atexit() function
00089        to Uninitialize that subsystem at program exit. */
00090     status = apr_initialize();
00091     if (status)
00092     {
00093         if (stderr)
00094         {
00095             char buf[1024];
00096             apr_strerror(status, buf, sizeof(buf) - 1);
00097             fprintf(stderr,
00098                   "%s: error: cannot initialize APR: %s\n",
00099                   "svnjavahl", buf);
00100         }
00101         return FALSE;
00102     }
00103 
00104     if (0 > atexit(apr_terminate))
00105     {
00106         if (stderr)
00107             fprintf(stderr,
00108                 "%s: error: atexit registration failed\n",
00109                 "svnjavahl");
00110         return FALSE;
00111     }
00112 
00113 #ifdef ENABLE_NLS
00114 #ifdef WIN32
00115     {
00116         WCHAR ucs2_path[MAX_PATH];
00117         char* utf8_path;
00118         const char* internal_path;
00119         apr_pool_t* pool;
00120         apr_status_t apr_err;
00121         unsigned int inwords, outbytes, outlength;
00122 
00123         apr_pool_create (&pool, 0);
00124         /* get dll name - our locale info will be in '../share/locale' */
00125         inwords = sizeof (ucs2_path) / sizeof(ucs2_path[0]);
00126         HINSTANCE moduleHandle = GetModuleHandle("libsvnjavahl-1");
00127         GetModuleFileNameW (moduleHandle, ucs2_path, inwords);
00128         inwords = lstrlenW (ucs2_path);
00129         outbytes = outlength = 3 * (inwords + 1);
00130         utf8_path = (char *)apr_palloc (pool, outlength);
00131         apr_err = apr_conv_ucs2_to_utf8 ((const apr_wchar_t *) ucs2_path,
00132                                          &inwords, utf8_path, &outbytes);
00133         if (!apr_err && (inwords > 0 || outbytes == 0))
00134           apr_err = APR_INCOMPLETE;
00135         if (apr_err)
00136         {
00137           if (stderr)
00138             fprintf (stderr, "Can't convert module path to UTF-8");
00139           return FALSE;
00140         }
00141         utf8_path[outlength - outbytes] = '\0';
00142         internal_path = svn_path_internal_style (utf8_path, pool);
00143         /* get base path name */
00144         internal_path = svn_path_dirname (internal_path, pool);
00145         internal_path = svn_path_join (internal_path, SVN_LOCALE_RELATIVE_PATH,
00146                                        pool);
00147         bindtextdomain (PACKAGE_NAME, internal_path);
00148         apr_pool_destroy (pool);
00149     }
00150 #else
00151     bindtextdomain(PACKAGE_NAME, SVN_LOCALE_DIR);
00152 #endif
00153     textdomain(PACKAGE_NAME);
00154 #endif
00155 
00156 
00157 #if defined(WIN32) || defined(__CYGWIN__)
00158     apr_pool_t* pool = svn_pool_create (NULL);
00159     /* See http://svn.collab.net/repos/svn/trunk/notes/asp-dot-net-hack.txt */
00160     /* ### This code really only needs to be invoked by consumers of
00161        ### the libsvn_wc library, which basically means SVNClient. */
00162     if (getenv ("SVN_ASP_DOT_NET_HACK"))
00163     {
00164         svn_error_t *err = svn_wc_set_adm_dir("_svn", pool);
00165         if (err)
00166         {
00167             if (stderr)
00168             {
00169                 fprintf(stderr,
00170                         "%s: error: SVN_ASP_DOT_NET_HACK failed: %s\n",
00171                         "svnjavahl", err->message);
00172             }
00173             svn_error_clear(err);
00174             return FALSE;
00175         }
00176     }
00177         svn_pool_destroy(pool);
00178 #endif
00179 
00180         return true;
00181 }
00182 
00183 /*static*/ void Util::throwNullPointerException( const char * p_msg)
00184 {
00185         throw std::invalid_argument(p_msg);
00186 }
00187 
00188 
00199 void Util::assembleErrorMessage(svn_error_t *err, int depth, 
00200                                                                 apr_status_t parent_apr_err, 
00201                                                                 std::string &buffer)
00202 {
00203         // buffer for a single error message
00204         char errbuf[256];
00205 
00206         /* Pretty-print the error */
00207         /* Note: we can also log errors here someday. */
00208 
00209         /* When we're recursing, don't repeat the top-level message if its
00210            the same as before. */
00211         if (depth == 0 || err->apr_err != parent_apr_err)
00212         {
00213                 /* Is this a Subversion-specific error code? */
00214                 if ((err->apr_err > APR_OS_START_USEERR)
00215                         && (err->apr_err <= APR_OS_START_CANONERR))
00216                         buffer.append(svn_strerror (err->apr_err, errbuf, sizeof (errbuf)));
00217                 /* Otherwise, this must be an APR error code. */
00218                 else
00219                         buffer.append(apr_strerror (err->apr_err, errbuf, sizeof (errbuf)));
00220                 buffer.append("\n");
00221         }
00222         if (err->message)
00223                 buffer.append( "svn: ").append(err->message).append("\n");
00224 
00225         if (err->child)
00226                 assembleErrorMessage(err->child, depth + 1, err->apr_err, buffer);
00227 
00228 }
00229 
00230 
00236 /*static*/ void Util::handleSVNError( svn_error_t * p_err)
00237 {
00238         if( !p_err) 
00239         { 
00240                 //std::cout << "handleSVNError: p_err is 0" << std::endl; 
00241                 return; 
00242         }
00243         //std::cout << "Error " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
00244 
00245         std::string buffer;
00246     assembleErrorMessage( p_err, 0, APR_SUCCESS, buffer);
00247         buffer = "SVN Error details follow:\n" + buffer;
00248         AfxMessageBox( buffer.c_str());
00249 
00250         // modifying buffer for the console
00251         // replacing '\n's with <br>s
00252         std::string::size_type p = buffer.find( "\n");
00253         while( std::string::npos != p)
00254         {
00255                 buffer.replace( p, 1, "<br>");
00256                 p = buffer.find( "\n");
00257         }
00258         // removing '\r's
00259         p = buffer.find( "\r");
00260         while( std::string::npos != p)
00261         {
00262                 buffer.erase( p, 1);
00263                 p = buffer.find( "\r");
00264         }
00265         // FIXME: MsgConsole::ssendMsg( buffer, MSG_ERROR);
00266         //std::cout << "Error " << buffer << std::endl;
00267 
00268         //if( p_err->apr_err == SVN_ERR_RA_ILLEGAL_URL)
00269         //      std::cout << "Error SVN_ERR_RA_ILLEGAL_URL, [URL does not exist]. " << std::endl;
00270         //if( p_err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
00271         //      std::cout << "Error SVN_ERR_UNSUPPORTED_FEATURE, [URL refs to file instead of a directory]. " << std::endl;
00272         //if( p_err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE)
00273         //      std::cout << "Error SVN_ERR_UNVERSIONED_RESOURCE " << ( p_err->file? p_err->file: "<<nofile>>") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
00274         //if( p_err->apr_err == SVN_ERR_RA_ILLEGAL_URL)
00275         //      std::cout << "Error SVN_ERR_RA_ILLEGAL_URL " << ( p_err->file? p_err->file: "<<nofile>>") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
00276         //if( p_err->apr_err == SVN_ERR_RA_DAV_SOCK_INIT)
00277         //      std::cout << "Error SVN_ERR_RA_DAV_SOCK_INIT " << (p_err->file?p_err->file:"") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
00278         //if( p_err->child)
00279         //      handleSVNError( p_err->child);
00280 }
00281 
00282 /*static*/ svn_error_t * Util::preprocessPath(const char *&path, apr_pool_t * pool)
00283 {
00284         /* URLs and wc-paths get treated differently. */
00285         if (svn_path_is_url (path))
00286         {
00287                 /* No need to canonicalize a URL's case or path separators. */
00288 
00289                 /* Convert to URI. */
00290                 path = svn_path_uri_from_iri (path, pool);
00291                 /* Auto-escape some ASCII characters. */
00292                 path = svn_path_uri_autoescape (path, pool);
00293 
00294                 /* The above doesn't guarantee a valid URI. */
00295                 if (! svn_path_is_uri_safe (path))
00296                         return svn_error_createf (SVN_ERR_BAD_URL, 0,
00297                         "URL '%s' is not properly URI-encoded",
00298                         path);
00299 
00300                 /* Verify that no backpaths are present in the URL. */
00301                 if (svn_path_is_backpath_present (path))
00302                         return svn_error_createf (SVN_ERR_BAD_URL, 0,
00303                         "URL '%s' contains a '..' element",
00304                         path);
00305 
00306                 /* strip any trailing '/' */
00307                 path = svn_path_canonicalize (path, pool);
00308         }
00309         else  /* not a url, so treat as a path */
00310         {
00311                 const char *apr_target;
00312                 char *truenamed_target; /* APR-encoded */
00313                 apr_status_t apr_err;
00314 
00315                 /* canonicalize case, and change all separators to '/'. */
00316                 SVN_ERR (svn_path_cstring_from_utf8 (&apr_target, path,
00317                         pool));
00318                 apr_err = apr_filepath_merge (&truenamed_target, "", apr_target,
00319                         APR_FILEPATH_TRUENAME, pool);
00320 
00321                 if (!apr_err)
00322                         /* We have a canonicalized APR-encoded target now. */
00323                         apr_target = truenamed_target;
00324                 else if (APR_STATUS_IS_ENOENT (apr_err))
00325                         /* It's okay for the file to not exist, that just means we
00326                         have to accept the case given to the client. We'll use
00327                         the original APR-encoded target. */
00328                         ;
00329                 else
00330                         return svn_error_createf (apr_err, NULL,
00331                         "Error resolving case of '%s'",
00332                         svn_path_local_style (path,
00333                         pool));
00334 
00335                 /* convert back to UTF-8. */
00336                 SVN_ERR (svn_path_cstring_to_utf8 (&path, apr_target, pool));
00337                 path = svn_path_canonicalize (path, pool);
00338 
00339         }
00340         return NULL;
00341 }
00342 
00343 #endif