Fossil

Check-in [cff1f785e1]
Login

Check-in [cff1f785e1]

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

Overview
Comment:Improvements to "fossil ui HOST:PATH".
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | remote-ui
Files: files | file ages | folders
SHA3-256: cff1f785e1000c5aaca270ddb21fc69d5de00ba042ebb7d4d632773b6196c63c
User & Date: drh 2021-06-30 20:15:58.550
Context
2021-06-30
20:31
Update the change log to talk about the enhancements to "fossil ui". ... (Closed-Leaf check-in: 2d19a40df3 user: drh tags: remote-ui)
20:15
Improvements to "fossil ui HOST:PATH". ... (check-in: cff1f785e1 user: drh tags: remote-ui)
19:14
Initial changes to support HOST: prefixes on the REPOSITORY argument of the "fossil ui" command. ... (check-in: cb34f1a8ac user: drh tags: remote-ui)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/main.c.
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
** checkout, it will chdir to that directory and, unless overridden by
** the --page option, select the current checkout version in the
** timeline by default.  This only works for the "fossil ui" command,
** not the "fossil server" command.
**
** If the REPOSITORY argument has a "HOST:" or "USER@HOST:" prefix, then
** the command is run on the remote host specified and the results are
** tunneled back to the localhost via SSH.  This feature only works for
** the "fossil ui" command, not the "fossil server" command.
**
** For the special case REPOSITORY name of "/", the global configuration
** database is consulted for a list of all known repositories.  The --repolist
** option is implied by this special case.  See also the "fossil all ui"
** command.
**







|







2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
** checkout, it will chdir to that directory and, unless overridden by
** the --page option, select the current checkout version in the
** timeline by default.  This only works for the "fossil ui" command,
** not the "fossil server" command.
**
** If the REPOSITORY argument has a "HOST:" or "USER@HOST:" prefix, then
** the command is run on the remote host specified and the results are
** tunneled back to the local host via SSH.  This feature only works for
** the "fossil ui" command, not the "fossil server" command.
**
** For the special case REPOSITORY name of "/", the global configuration
** database is consulted for a list of all known repositories.  The --repolist
** option is implied by this special case.  See also the "fossil all ui"
** command.
**
2859
2860
2861
2862
2863
2864
2865


2866
2867
2868
2869
2870
2871
2872
**                                       JavaScript concatenated together.
**                       Depending on the needs of any given page, inline
**                       and bundled modes might result in a single
**                       amalgamated script or several, but both approaches
**                       result in fewer HTTP requests than the separate mode.
**   --max-latency N     Do not let any single HTTP request run for more than N
**                       seconds (only works on unix)


**   --nocompress        Do not compress HTTP replies
**   --nojail            Drop root privileges but do not enter the chroot jail
**   --nossl             signal that no SSL connections are available (Always
**                       set by default for the "ui" command)
**   --notfound URL      Redirect
**   --page PAGE         Start "ui" on PAGE.  ex: --page "timeline?y=ci"
**   -P|--port TCPPORT   listen to request on port TCPPORT







>
>







2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
**                                       JavaScript concatenated together.
**                       Depending on the needs of any given page, inline
**                       and bundled modes might result in a single
**                       amalgamated script or several, but both approaches
**                       result in fewer HTTP requests than the separate mode.
**   --max-latency N     Do not let any single HTTP request run for more than N
**                       seconds (only works on unix)
**   --nobrowser         Do not automatically launch a web-browser for the
**                       "fossil ui" command.
**   --nocompress        Do not compress HTTP replies
**   --nojail            Drop root privileges but do not enter the chroot jail
**   --nossl             signal that no SSL connections are available (Always
**                       set by default for the "ui" command)
**   --notfound URL      Redirect
**   --page PAGE         Start "ui" on PAGE.  ex: --page "timeline?y=ci"
**   -P|--port TCPPORT   listen to request on port TCPPORT
2894
2895
2896
2897
2898
2899
2900

2901
2902
2903
2904
2905
2906
2907
  const char *zTimeout = 0; /* Max runtime of any single HTTP request */
#endif
  int allowRepoList;         /* List repositories on URL "/" */
  const char *zAltBase;      /* Argument to the --baseurl option */
  const char *zFileGlob;     /* Static content must match this */
  char *zIpAddr = 0;         /* Bind to this IP address */
  int fCreate = 0;           /* The --create flag */

  const char *zInitPage = 0; /* Start on this page.  --page option */
  int findServerArg = 2;     /* argv index for find_server_repository() */
  char *zRemote = 0;         /* Remote host on which to run "fossil ui" */
  

#if defined(_WIN32)
  const char *zStopperFile;    /* Name of file used to terminate server */







>







2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
  const char *zTimeout = 0; /* Max runtime of any single HTTP request */
#endif
  int allowRepoList;         /* List repositories on URL "/" */
  const char *zAltBase;      /* Argument to the --baseurl option */
  const char *zFileGlob;     /* Static content must match this */
  char *zIpAddr = 0;         /* Bind to this IP address */
  int fCreate = 0;           /* The --create flag */
  int fNoBrowser = 0;        /* Do not auto-launch web-browser */
  const char *zInitPage = 0; /* Start on this page.  --page option */
  int findServerArg = 2;     /* argv index for find_server_repository() */
  char *zRemote = 0;         /* Remote host on which to run "fossil ui" */
  

#if defined(_WIN32)
  const char *zStopperFile;    /* Name of file used to terminate server */
2939
2940
2941
2942
2943
2944
2945

2946
2947
2948
2949
2950
2951
2952
  zAltBase = find_option("baseurl", 0, 1);
  fCreate = find_option("create",0,0)!=0;
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;

  if( find_option("https",0,0)!=0 ){
    cgi_replace_parameter("HTTPS","on");
  }
  if( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }
  g.zCkoutAlias = find_option("ckout-alias",0,1);







>







2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
  zAltBase = find_option("baseurl", 0, 1);
  fCreate = find_option("create",0,0)!=0;
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
  fNoBrowser = find_option("nobrowser", 0, 0)!=0;
  if( find_option("https",0,0)!=0 ){
    cgi_replace_parameter("HTTPS","on");
  }
  if( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }
  g.zCkoutAlias = find_option("ckout-alias",0,1);
2982
2983
2984
2985
2986
2987
2988

2989
2990
2991
2992
2993
2994
2995
      g.argv[2] = 0;
      --g.argc;
    }
  }
  if( isUiCmd && 3==g.argc
   && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0
  ){

    const char *zRepoTail = file_skip_userhost(g.argv[2]);
    unsigned x;
    int n;
    sqlite3_randomness(2,&x);
    zPort = mprintf("%d", 8100+(x%32000));
    n = (int)(zRepoTail - g.argv[2]) - 1;
    zRemote = mprintf("%.*s", n, g.argv[2]);







>







2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
      g.argv[2] = 0;
      --g.argc;
    }
  }
  if( isUiCmd && 3==g.argc
   && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0
  ){
    /* The REPOSITORY argument has a USER@HOST: or HOST: prefix */
    const char *zRepoTail = file_skip_userhost(g.argv[2]);
    unsigned x;
    int n;
    sqlite3_randomness(2,&x);
    zPort = mprintf("%d", 8100+(x%32000));
    n = (int)(zRepoTail - g.argv[2]) - 1;
    zRemote = mprintf("%.*s", n, g.argv[2]);
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048



3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
      }
    }
    iPort = mxPort = atoi(zPort);
  }else{
    iPort = db_get_int("http-port", 8080);
    mxPort = iPort+100;
  }
  if( isUiCmd ){
    char *zBrowserArg;
    zBrowser = fossil_web_browser();
    if( zIpAddr==0 ){
      zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
    }else if( strchr(zIpAddr,':') ){
      zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
    }else{
      zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
    }
#ifdef _WIN32
    zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg);
#else
    zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
#endif
    fossil_free(zBrowserArg);
  }
  if( zRemote && zBrowserCmd ){



    FILE *sshIn;
    Blob ssh;
    char zLine[1000];
    blob_init(&ssh, 0, 0);
    transport_ssh_command(&ssh);
    blob_appendf(&ssh, 
       " -t -L127.0.0.1:%d:127.0.0.1:%d -- %!$"
       " fossil server --nossl --port %d %!$",
       iPort, iPort, zRemote, iPort, g.argv[2]);
    fossil_print("%s\n", blob_str(&ssh));
    sshIn = popen(blob_str(&ssh), "r");
    if( sshIn==0 ){
      fossil_fatal("unable to %s", blob_str(&ssh));
    }
    while( fgets(zLine, sizeof(zLine), sshIn) ){
      fossil_print("%s", zLine);
      fflush(stdout);
      if( zBrowserCmd ){
        char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort);
        fossil_system(zCmd);
        fossil_free(zCmd);
        fossil_free(zBrowserCmd);
        zBrowserCmd = 0;







|
















|
>
>
>







|







|







3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
      }
    }
    iPort = mxPort = atoi(zPort);
  }else{
    iPort = db_get_int("http-port", 8080);
    mxPort = iPort+100;
  }
  if( isUiCmd && !fNoBrowser ){
    char *zBrowserArg;
    zBrowser = fossil_web_browser();
    if( zIpAddr==0 ){
      zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
    }else if( strchr(zIpAddr,':') ){
      zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
    }else{
      zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
    }
#ifdef _WIN32
    zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg);
#else
    zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
#endif
    fossil_free(zBrowserArg);
  }
  if( zRemote ){
    /* If a USER@HOST:REPO argument is supplied, then use SSH to run
    ** "fossil ui --nobrowser" on the remote system and to set up a
    ** tunnel from the local machine to the remote. */
    FILE *sshIn;
    Blob ssh;
    char zLine[1000];
    blob_init(&ssh, 0, 0);
    transport_ssh_command(&ssh);
    blob_appendf(&ssh, 
       " -t -L127.0.0.1:%d:127.0.0.1:%d -- %!$"
       " fossil ui --nobrowser --localauth --port %d %$",
       iPort, iPort, zRemote, iPort, g.argv[2]);
    fossil_print("%s\n", blob_str(&ssh));
    sshIn = popen(blob_str(&ssh), "r");
    if( sshIn==0 ){
      fossil_fatal("unable to %s", blob_str(&ssh));
    }
    while( fgets(zLine, sizeof(zLine), sshIn) ){
      fputs(zLine, stdout);
      fflush(stdout);
      if( zBrowserCmd ){
        char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort);
        fossil_system(zCmd);
        fossil_free(zCmd);
        fossil_free(zBrowserCmd);
        zBrowserCmd = 0;