Changes On Branch sub-repos
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch sub-repos Excluding Merge-Ins

This is equivalent to a diff from 13ceb46e49 to e8b15ad642

2011-03-28
22:47
Merge the sub-repo capability into trunk. check-in: ab4882588e user: drh tags: trunk
22:29
A new approach to sub-repos in which a specific user for the subrepo is specified in the CONFIG table entry. Closed-Leaf check-in: e8b15ad642 user: drh tags: sub-repos
21:46
Fixes to the capability reduction on subrepositories. check-in: 4b545a8a02 user: drh tags: sub-repos
18:08
Allow for the creation of "sub-repositories" that can be accessed through the web interface using the same login credentials as the parent repository. check-in: 97d0118794 user: drh tags: sub-repos
07:40
Use "password" instead of "passwd" because it's complete and proper, and plays nicely w/ Emacs "send-invisible" capabilities that keep typed text from echoing on screen. check-in: 13ceb46e49 user: bharder tags: trunk
2011-03-27
21:55
Changes to makeheaders so that it does not move static inline procedures into header files. Changed suggested by Yoran Heling. This has zero impact on Fossil which does not use "inline" anywhere. check-in: 99532f33af user: drh tags: trunk

Changes to src/login.c.

   498    498     }
   499    499   
   500    500     /* Set the capabilities */
   501    501     login_set_capabilities(zCap);
   502    502     login_set_anon_nobody_capabilities();
   503    503   }
   504    504   
          505  +/*
          506  +** Memory of settings
          507  +*/
          508  +static int login_anon_once = 1;
          509  +
   505    510   /*
   506    511   ** Add the default privileges of users "nobody" and "anonymous" as appropriate
   507    512   ** for the user g.zLogin.
   508    513   */
   509    514   void login_set_anon_nobody_capabilities(void){
   510         -  static int once = 1;
   511         -  if( g.zLogin && once ){
          515  +  if( g.zLogin && login_anon_once ){
   512    516       const char *zCap;
   513    517       /* All logged-in users inherit privileges from "nobody" */
   514    518       zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
   515    519       login_set_capabilities(zCap);
   516    520       if( fossil_strcmp(g.zLogin, "nobody")!=0 ){
   517    521         /* All logged-in users inherit privileges from "anonymous" */
   518    522         zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
   519    523         login_set_capabilities(zCap);
   520    524       }
   521         -    once = 0;
          525  +    login_anon_once = 0;
   522    526     }
   523    527   }
   524    528   
   525    529   /*
   526    530   ** Set the global capability flags based on a capability string.
   527    531   */
   528    532   void login_set_capabilities(const char *zCap){
................................................................................
   615    619         /* case 'q': */
   616    620         case 'r':  rc = g.okRdTkt;     break;
   617    621         case 's':  rc = g.okSetup;     break;
   618    622         case 't':  rc = g.okTktFmt;    break;
   619    623         /* case 'u': READER    */
   620    624         /* case 'v': DEVELOPER */
   621    625         case 'w':  rc = g.okWrTkt;     break;
   622         -      /* case 'x': */
          626  +      case 'x':  rc = g.okPrivate;   break;
   623    627         /* case 'y': */
   624    628         case 'z':  rc = g.okZip;       break;
   625    629         default:   rc = 0;             break;
   626    630       }
   627    631     }
   628    632     return rc;
   629    633   }
          634  +
          635  +/*
          636  +** Change the login to zUser.
          637  +*/
          638  +void login_as_user(const char *zUser){
          639  +  char *zCap = "";   /* New capabilities */
          640  +
          641  +  /* Turn off all capabilities from prior logins */
          642  +  g.okSetup = 0;
          643  +  g.okAdmin = 0;
          644  +  g.okDelete = 0;
          645  +  g.okPassword = 0;
          646  +  g.okQuery = 0;
          647  +  g.okWrite = 0;
          648  +  g.okRead = 0;
          649  +  g.okHistory = 0;
          650  +  g.okClone = 0;
          651  +  g.okRdWiki = 0;
          652  +  g.okNewWiki = 0;
          653  +  g.okApndWiki = 0;
          654  +  g.okWrWiki = 0;
          655  +  g.okRdTkt = 0;
          656  +  g.okNewTkt = 0;
          657  +  g.okApndTkt = 0;
          658  +  g.okWrTkt = 0;
          659  +  g.okAttach = 0;
          660  +  g.okTktFmt = 0;
          661  +  g.okRdAddr = 0;
          662  +  g.okZip = 0;
          663  +  g.okPrivate = 0;
          664  +
          665  +  /* Set the global variables recording the userid and login.  The
          666  +  ** "nobody" user is a special case in that g.zLogin==0.
          667  +  */
          668  +  g.userUid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUser);
          669  +  if( g.userUid==0 ){
          670  +    zUser = 0;
          671  +    g.userUid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
          672  +  }
          673  +  if( g.userUid ){
          674  +    zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", g.userUid);
          675  +  }
          676  +  if( fossil_strcmp(zUser,"nobody")==0 ) zUser = 0;
          677  +  g.zLogin = fossil_strdup(zUser);
          678  +
          679  +  /* Set the capabilities */
          680  +  login_set_capabilities(zCap);
          681  +  login_anon_once = 1;
          682  +  login_set_anon_nobody_capabilities();
          683  +}
   630    684   
   631    685   /*
   632    686   ** Call this routine when the credential check fails.  It causes
   633    687   ** a redirect to the "login" page.
   634    688   */
   635    689   void login_needed(void){
   636    690     const char *zUrl = PD("REQUEST_URI", "index");

Changes to src/main.c.

   966    966     if( zPathInfo==0 || zPathInfo[0]==0 
   967    967         || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
   968    968       fossil_redirect_home();
   969    969     }else{
   970    970       zPath = mprintf("%s", zPathInfo);
   971    971     }
   972    972   
   973         -  /* Remove the leading "/" at the beginning of the path.
          973  +  /* Make g.zPath point to the first element of the path.  Make
          974  +  ** g.zExtra point to everything past that point.
   974    975     */
   975         -  g.zPath = &zPath[1];
   976         -  for(i=1; zPath[i] && zPath[i]!='/'; i++){}
   977         -  if( zPath[i]=='/' ){
   978         -    zPath[i] = 0;
   979         -    g.zExtra = &zPath[i+1];
   980         -  }else{
   981         -    g.zExtra = 0;
          976  +  while(1){
          977  +    char *zAltRepo = 0;
          978  +    g.zPath = &zPath[1];
          979  +    for(i=1; zPath[i] && zPath[i]!='/'; i++){}
          980  +    if( zPath[i]=='/' ){
          981  +      zPath[i] = 0;
          982  +      g.zExtra = &zPath[i+1];
          983  +
          984  +      /* Look for sub-repositories.  A sub-repository is another repository
          985  +      ** that accepts the login credentials of the current repository.  A
          986  +      ** subrepository is identified by a CONFIG table entry "subrepo:NAME"
          987  +      ** where NAME is the first component of the path.  The value of the
          988  +      ** the CONFIG entries is the string "USER:FILENAME" where USER is the
          989  +      ** USER name to log in as in the subrepository and FILENAME is the
          990  +      ** repository filename. 
          991  +      */
          992  +      zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'",
          993  +                         g.zPath);
          994  +      if( zAltRepo ){
          995  +        int nHost;
          996  +        int jj;
          997  +        char *zUser = zAltRepo;
          998  +        login_check_credentials();
          999  +        for(jj=0; zAltRepo[jj] && zAltRepo[jj]!=':'; jj++){}
         1000  +        if( zAltRepo[jj]==':' ){
         1001  +          zAltRepo[jj] = 0;
         1002  +          zAltRepo += jj+1;
         1003  +        }else{
         1004  +          zUser = "nobody";
         1005  +        }
         1006  +        if( zAltRepo[0]!='/' ){
         1007  +          zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
         1008  +          file_simplify_name(zAltRepo, -1);
         1009  +        }
         1010  +        db_close(1);
         1011  +        db_open_repository(zAltRepo);
         1012  +        login_as_user(zUser);
         1013  +        g.okPassword = 0;
         1014  +        zPath += i;
         1015  +        nHost = g.zTop - g.zBaseURL;
         1016  +        g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
         1017  +        g.zTop = g.zBaseURL + nHost;
         1018  +        continue;
         1019  +      }
         1020  +    }else{
         1021  +      g.zExtra = 0;
         1022  +    }
         1023  +    break;
   982   1024     }
   983   1025     if( g.zExtra ){
   984   1026       /* CGI parameters get this treatment elsewhere, but places like getfile
   985   1027       ** will use g.zExtra directly.
   986   1028       */
   987   1029       dehttpize(g.zExtra);
   988   1030       cgi_set_parameter_nocopy("name", g.zExtra);