36#include <unordered_set>
45#include "XrdSys/XrdWin32.hh"
69#define ENODATA ENOATTR
82 idInfo(
const char *name, time_t keep)
83 : Expr(time(0)+keep), Name(strdup(name)) {}
84 ~idInfo() {free(Name);}
87typedef std::map<unsigned int, struct idInfo*> idMap_t;
93void AddID(idMap_t &idMap,
unsigned int id,
const char *name, time_t keepT)
95 std::pair<idMap_t::iterator,bool> ret;
96 idInfo *infoP =
new idInfo(name, keepT);
99 ret = idMap.insert(std::pair<unsigned int, struct idInfo*>(
id, infoP));
100 if (ret.second ==
false)
delete infoP;
104int LookUp(idMap_t &idMap,
unsigned int id,
char *buff,
int blen)
106 idMap_t::iterator it;
111 if (it != idMap.end())
112 {
if (it->second->Expr <= time(0))
116 if (blen > 0) luRet = snprintf(buff, blen,
"%s", it->second->Name);
135for (j = 0; j < argC; j++)
136 {
while(*aP ==
' ') aP++;
139 if (*aP ==
'"' || *aP ==
'\'')
141 aP = index(aP+1, *aP);
142 if (!aP || (*(aP+1) !=
' ' && *(aP+1)))
143 {
if (!j) argV[0] = 0;
return -EINVAL;}
147 if ((aP = index(aP+1,
' '))) *aP++ =
'\0';
155 if (j > argC-1)
return -E2BIG;
170 static const char hv[] =
"0123456789abcdef";
171 char *outbuff = buff;
172 for (
int i = 0; i < dlen && blen > 2; i++) {
173 *outbuff++ = hv[(inbuff[i] >> 4) & 0x0f];
174 *outbuff++ = hv[ inbuff[i] & 0x0f];
176 if (sep && blen > 1 && ((i & 0x03) == 0x03 || i+1 == dlen))
177 {*outbuff++ =
' '; blen--;}
189 int len = 0, lo = -1, hi = -1;
191 while (
int c = *hex++) {
192 if (c ==
' ' || c ==
'\n')
220 bin[len++] = (hi << 4) | lo;
223 if (hi >= 0 || lo >= 0 || len == 0)
234 int tlen = strlen(text);
236 return (tlen >= endlen && !strcmp(text+(tlen-endlen), ending));
281 const char *what,
const char *hname,
282 const char *nname,
const char *pname)
284 static const char *brk[] = {
"defined",
"exec",
"named", 0};
291 if (!(val = Config.GetWord()))
292 {
if (
eDest)
eDest->Emsg(
"Config",
"Host name missing after 'if' in", what);
298 if (!
is1of(val, brk))
300 val = Config.GetWord();
301 }
while(!hostok && val && !
is1of(val, brk));
303 {
while(val && !
is1of(val, brk)) val = Config.GetWord();
311 while(!strcmp(val,
"defined"))
312 {
if (!(val = Config.GetWord()) || *val !=
'?')
314 {
eDest->Emsg(
"Config",
"'?var' missing after 'defined' in",what);}
319 if (!theEnv && (theEnv = Config.SetEnv(0))) Config.SetEnv(theEnv);
320 if (!theEnv && *(val+1) !=
'~')
return 0;
325 while(val && *val ==
'?')
326 {
if (*(val+1) ==
'~' ? getenv(val+2) : theEnv->
Get(val+1)) isDef=1;
327 val = Config.GetWord();
329 if (!val || !isDef)
return isDef;
330 if (strcmp(val,
"&&"))
332 {
eDest->Emsg(
"Config",val,
"is invalid for defined test in",what);}
335 if (!(val = Config.GetWord()))
337 {
eDest->Emsg(
"Config",
"missing keyword after '&&' in",what);}
341 if (!
is1of(val, brk))
343 {
eDest->Emsg(
"Config",val,
"is invalid after '&&' in",what);}
351 if (!strcmp(val,
"exec"))
352 {
if (!(val = Config.GetWord()) || !strcmp(val,
"&&"))
354 {
eDest->Emsg(
"Config",
"Program name missing after 'if exec' in",what);}
360 if (!pname)
return 0;
361 while(val && strcmp(val, pname))
362 if (!strcmp(val,
"&&"))
return 0;
363 else val = Config.GetWord();
365 while(val && strcmp(val,
"&&")) val = Config.GetWord();
368 if (!(val = Config.GetWord()))
370 {
eDest->Emsg(
"Config",
"Keyword missing after '&&' in",what);}
373 if (strcmp(val,
"named"))
375 {
eDest->Emsg(
"Config",val,
"is invalid after '&&' in",what);}
383 if (!(val = Config.GetWord()))
385 {
eDest->Emsg(
"Config",
"Instance name missing after 'if named' in", what);}
391 if (!nname)
return 0;
392 while(val && strcmp(val, nname)) val = Config.GetWord();
410 {
if (
stat(pgm, &
Stat) || !(
Stat.st_mode & S_IXOTH))
return false;
417 const char *pEnv = getenv(
"PATH");
418 if (!pEnv)
return false;
424 prog +=
'/'; prog += pgm;
428 while((from = pList.
tokenize(path, from,
':')) != -1)
441 static const long long Kval = 1024LL;
442 static const long long Mval = 1024LL*1024LL;
443 static const long long Gval = 1024LL*1024LL*1024LL;
444 static const long long Tval = 1024LL*1024LL*1024LL*1024LL;
450 if (val < 1024)
return snprintf(buff, bsz,
"%lld", val);
451 if (val < Mval) {val = val*10/Kval; sName =
'K';}
452 else if (val < Gval) {val = val*10/Mval; sName =
'M';}
453 else if (val < Tval) {val = val*10/Gval; sName =
'G';}
454 else {val = val*10/Tval; sName =
'T';}
455 resid = val%10LL; val = val/10LL;
459 return snprintf(buff, bsz,
"%lld.%d%c", val, resid, sName);
463 static const char* units[] = {
"",
"K",
"M",
"G",
"T",
"P",
"E"};
464 const int maxUnit = 6;
466 double value =
static_cast<double>(size);
469 while (value >=
static_cast<double>(base) && unitIndex < maxUnit) {
470 value /=
static_cast<double>(base);
474 auto ceil_to = [](
double x,
int decimals) {
475 if (x == 0.0)
return 0.0;
476 const double p = std::pow(10.0, decimals);
478 return std::ceil(x * p - 1e-12) / p;
481 auto decimals_for = [](
double x,
int u) {
482 return (u > 0 && x < 10.0) ? 1 : 0;
485 int prec = decimals_for(value, unitIndex);
486 double shown = ceil_to(value, prec);
489 if (shown >=
static_cast<double>(base) && unitIndex < maxUnit) {
490 shown /=
static_cast<double>(base);
493 prec = decimals_for(shown, unitIndex);
494 shown = ceil_to(shown, prec);
497 std::ostringstream out;
498 out << std::fixed << std::setprecision(prec) << shown << units[unitIndex];
510 int i =
strlcpy(buff, p_path,
sizeof(buff));
512 if (buff[i-1] !=
'/') {buff[i++] =
'/'; buff[i] =
'\0';}
513 if (inst) {strcpy(buff+i, inst); strcat(buff,
"/");}
514 if (s_path) strcat(buff, s_path);
517 if (buff[i-1] !=
'/') {buff[i++] =
'/'; buff[i] =
'\0';}
529 j = (psfx ? strlen(psfx) : 0);
530 if (i+j+3 > blen)
return -ENAMETOOLONG;
534 {
if (buff[i-1] !=
'/') buff[i++] =
'/';
535 strcpy(&buff[i], psfx);
536 if (psfx[j-1] !=
'/') strcat(buff,
"/");
551 ~fdHelper() {
if (fd >= 0)
close(fd);}
562 if ((file.fd =
open(path, O_RDONLY)) < 0) {rc = errno;
return 0;}
566 if (
fstat(file.fd, &
Stat)) {rc = errno;
return 0;}
570 if (
Stat.st_size > maxsz) {rc = EFBIG;
return 0;}
574 if (
Stat.st_size == 0 && notempty) {rc =
ENODATA;
return 0;}
578 if ((buff = (
char *)malloc(
Stat.st_size+1)) == 0)
579 {rc = errno;
return 0;}
584 {
if ((flen =
read(file.fd, buff,
Stat.st_size)) < 0)
585 {rc = errno; free(buff);
return 0;}
604 struct group Grp, *result;
607 getgrnam_r(gName, &Grp, buff,
sizeof(buff), &result);
608 if (!result)
return false;
620 struct passwd pwd, *result;
623 getpwnam_r(uName, &pwd, buff,
sizeof(buff), &result);
624 if (!result)
return false;
627 if (gID) *gID = pwd.pw_gid;
638 static const int maxgBsz = 256*1024;
639 static const int addGsz = 4096;
640 struct group *gEnt, gStruct;
641 char gBuff[1024], *gBp = gBuff;
642 int glen = 0, gBsz =
sizeof(gBuff), aOK = 1;
648 {
int n = LookUp(gidMap,
static_cast<unsigned int>(gID),gName,gNsz);
649 if (n > 0)
return (n < gNsz ? n : 0);
655 while(( retVal = getgrgid_r(gID, &gStruct, gBp, gBsz, &gEnt) ) == ERANGE)
656 {
if (gBsz >= maxgBsz) {aOK = 0;
break;}
657 if (gBsz > addGsz) free(gBp);
659 if (!(gBp = (
char *)malloc(gBsz))) {aOK = 0;
break;}
664 if (aOK && retVal == 0 && gEnt != NULL)
666 AddID(gidMap,
static_cast<unsigned int>(gID), gEnt->gr_name, keepT);
667 glen = strlen(gEnt->gr_name);
668 if (glen >= gNsz) glen = 0;
669 else strcpy(gName, gEnt->gr_name);
671 n = snprintf(gName, gNsz,
"%ud",
static_cast<unsigned int>(gID));
672 if (n >= gNsz) glen = 0;
677 if (gBsz > addGsz && gBp) free(gBp);
687 static const int maxgBsz = 256*1024;
688 static const int addGsz = 4096;
689 struct group *gEnt, gStruct;
690 char gBuff[1024], *gBp = gBuff;
691 int glen, gBsz =
sizeof(gBuff), aOK = 1;
697 while(( retVal = getgrgid_r(gID, &gStruct, gBp, gBsz, &gEnt) ) == ERANGE)
698 {
if (gBsz >= maxgBsz) {aOK = 0;
break;}
699 if (gBsz > addGsz) free(gBp);
701 if (!(gBp = (
char *)malloc(gBsz))) {aOK = 0;
break;}
706 if (aOK && retVal == 0 && gEnt != NULL)
707 {glen = strlen(gEnt->gr_name);
708 if (glen >= gNsz) glen = 0;
709 else strcpy(gName, gEnt->gr_name);
714 if (gBsz > addGsz && gBp) free(gBp);
728 {snprintf(buff, bsz,
"%zu", bytes);
734 const char *suffix =
" KMGTPEYZ";
735 double dBytes =
static_cast<double>(bytes);
737do{dBytes /= 1024.0; suffix++;
738 }
while(dBytes >= 1024.0 && *(suffix+1));
743 double whole, frac = modf(dBytes, &whole);
744 if (frac >= .005) snprintf(buff, bsz,
"%.02lf%c", dBytes, *suffix);
745 else snprintf(buff, bsz,
"%g%c", whole, *suffix);
755 char zo[2] = {
'0',
'1'};
757 if (blen < 2)
return "";
760 if (!val) buff[blen--] =
'0';
761 else while(val && blen >= 0)
762 {buff[blen--] = zo[val & 0x01];
766 if (blen >= 0 && pad)
while(blen >= 0) buff[blen--] =
'0';
768 return &buff[blen+1];
777long long genSID(
char *&urSID,
const char *iHost,
int iPort,
778 const char *iName,
const char *iProg)
781 static const uint32_t fpOffs = 2, fpSize = 6;
783 const char *iSite = getenv(
"XRDSITE");
784 unsigned char mDigest[mdLen];
786 union {uint64_t mdLL;
unsigned char mdUC[8];};
790 if (iSite) myID = iSite;
793 if (iName) myID += iName;
798 memset(mDigest, 0,
sizeof(mDigest));
808 uint64_t fpPos =
crc32c % (((uint32_t)mdLen) - fpSize);
810 memcpy(mdUC+fpOffs, mDigest+fpPos, fpSize);
811 long long fpVal =
static_cast<long long>(ntohll(mdLL));
816 snprintf(fpBuff,
sizeof(fpBuff),
"%lld", fpVal);
817 urSID = strdup(fpBuff);
823 const char *iHost,
const char *iProg,
824 const char *iName,
int iPort)
827 static long long theSID = genSID(theSIN, iHost, iPort, iName, iProg);
828 const char *sP = getenv(
"XRDSITE");
830 int myPid =
static_cast<int>(getpid());
834 if (
UserName(getuid(), uName,
sizeof(uName)))
835 sprintf(uName,
"%d",
static_cast<int>(getuid()));
839 snprintf(iBuff,iBlen,
"%s.%d:%s@%s\n&site=%s&port=%d&inst=%s&pgm=%s",
840 uName, myPid, theSIN, iHost, (sP ? sP :
""), iPort, iName, iProg);
844 h2nll(theSID, mySID);
845 return strdup(theSIN);
854 const char *iName = getenv(
"XRDNAME");
858 if (!TranOpt)
return iName;
863 if (TranOpt > 0) {
if (!iName || !*iName) iName =
"anon";}
864 else if (iName && !strcmp(iName,
"anon")) iName = 0;
870{
return (Fillit ? name && *name ? name :
"anon"
871 : name && strcmp(name,
"anon") && *name ? name : 0);
881 while(clist[i])
if (!strcmp(val, clist[i]))
return 1;
893 const char *hName, *hNend, *hPort, *hPend, *hP = path;
897 if (*path ==
'/') hP++;
898 if (*hP ==
'x') hP++;
899 if (strncmp(
"root:/", hP, 6))
return 0;
900 if (hBuff == 0 || hBLen <= 0)
return (hP - path) + 6;
904 if (*hNend ==
']') hNend++;
905 else {
if (!(*hNend) && !(hNend = index(hName,
'/')))
return 0;
906 if (!(*hPend)) hPend = hNend;
909 if (pTrim || !(*hPort)) n = hNend - hP;
911 if (n >= hBLen)
return 0;
912 strncpy(hBuff, hP, n);
916 {
if (*hNend !=
':') *port = 0;
917 else {*port = strtol(hPort, &eP, 10);
918 if (*port < 0 || *port > 65535 || eP != hPend)
return 0;
942 #define SHFT(k) if (n >= (1ULL << k)) { i += k; n >>= k; }
957 #define SHFT(k, m) if (n >= m) { i += k; n /= m; }
959 SHFT(16,10000000000000000ULL);
SHFT(8,100000000ULL);
974 if (!inst || !getcwd(buff,
sizeof(buff)))
return;
976 strcat(buff,
"/"); strcat(buff, inst);
978 {
eDest.Emsg(
"Config", errno,
"create home directory", buff);
983 eDest.Emsg(
"Config", errno,
"chdir to home directory", buff);
989 const char *path, mode_t mode)
992 const char *slash =
"", *slash2 =
"";
998 if (!path || !(n = strlen(path)))
1005 if (path[n-1] !=
'/') slash =
"/";
1006 if (!inst || !(n = strlen(inst))) inst =
"";
1008 n = snprintf(cwDir,
sizeof(cwDir),
"%s%s%s%s", path, slash, inst, slash2);
1009 if (n >= (
int)
sizeof(cwDir))
1010 {
eDest.Emsg(
"Config", ENAMETOOLONG,
"create home directory", cwDir);
1016 if ((rc =
makePath(cwDir, mode,
true)))
1017 {
eDest.Emsg(
"Config", rc,
"create home directory", cwDir);
1023 if (
chdir(cwDir) < 0)
1024 {
eDest.Emsg(
"Config", errno,
"chdir to home directory", cwDir);
1039 char *next_path = path+1;
1041 bool dochmod =
false;
1045 if (!reset && !
stat(path, &buf))
return 0;
1049 while((next_path = index(next_path,
int(
'/'))))
1052 if (errno != EEXIST)
return -errno;
1053 if (dochmod)
CHMOD(path, mode);
1056 next_path = next_path+1;
1070 mode_t mval[3] = {0}, mbit[3] = {0x04, 0x02, 0x01};
1071 const char *mok =
"rwx";
1078 mask = strtol(mode, &eP, 8);
1084 int n = strlen(mode);
1085 if (!n || n > 9 || n/3*3 != n)
return false;
1090 do {
for (
int i = 0; i < 3; i++)
1093 {
if (mlet != mok[i])
return false;
1097 }
while(++k < 3 && *mode);
1101 mask = mval[0]<<6 | mval[1]<<3 | mval[2];
1110 const char *libName,
char *&libPath,
char **libParm)
1112 char *val, parms[2048];
1116 val = Config.GetWord();
1120 if (val && !strcmp(
"++", val))
1121 {
eDest.Say(
"Config warning: stacked plugins are not supported in "
1122 "this context; directive ignored!");
1128 while(val && *val && *val ==
'+') val = Config.GetWord();
1132 if (!val || !val[0])
1133 {
eDest.Emsg(
"Config", libName,
"not specified");
return false;}
1137 if (libPath) free(libPath);
1138 libPath = strdup(val);
1142 if (!libParm)
return true;
1143 if (*libParm) free(*libParm);
1149 if (!Config.GetRest(parms,
sizeof(parms)))
1150 {
eDest.Emsg(
"Config", libName,
"parameters too long");
return false;}
1151 if (*parms) *libParm = strdup(parms);
1161 char *pval, *val, *HomePath = 0;
1165 pval = Config.GetWord();
1166 if (!pval || !pval[0])
1167 {
eDest.Emsg(
"Config",
"home path not specified");
return 0;}
1172 {
eDest.Emsg(
"Config",
"home path not absolute");
return 0;}
1176 HomePath = strdup(pval);
1181 if ((val = Config.GetWord()) && val[0])
1182 {
if (!strcmp(
"group", val)) mode |= (S_IRGRP | S_IXGRP);
1183 else {
eDest.Emsg(
"Config",
"invalid home path modifier -", val);
1198 static std::random_device rd;
1199 static std::mt19937 gen(rd());
1200 static std::uniform_int_distribution<unsigned short> dist(0, 255);
1204 std::generate(buff, buff + inblen, [&]() {
1205 return static_cast<unsigned char>(dist(gen));
1215 const mode_t AMode = S_IRWXU;
1216 char pbuff[MAXPATHLEN+64];
1222 if (n >= (
int)
sizeof(pbuff))
return ENAMETOOLONG;
1223 strcpy(pbuff, path);
1228 makePath(pbuff, (mode ? mode : AMode));
1229 if (symlink(target, path))
return errno;
1244 {
if (*str ==
'-') *str = subc;
1245 else if (*str ==
' ') *str = subc;
1246 char *blank = rindex(str,
' ');
1247 if (blank)
while(*blank ==
' ') *blank-- = 0;
1249 {
if (!isalnum(*str) && index(
"_-.", *str) == 0) *str = subc;
1261 const mode_t lfm = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH;
1262 char buff[2048], *sp;
1265 if (!inst || !*inst)
return logfn;
1266 if (!(sp = rindex(logfn,
'/'))) strcpy(buff,
"./");
1267 else {*sp =
'\0'; strcpy(buff, logfn); strcat(buff,
"/");}
1269 strcat(buff, inst); strcat(buff,
"/");
1272 {
eDest.Emsg(
"Config", rc,
"create log file path", buff);
1276 if (sp) {*sp =
'/'; strcat(buff, sp+1);}
1277 else strcat(buff, logfn);
1280 return strdup(buff);
1289 unsigned char* ustr = (
unsigned char*)str;
1293 while(*ustr) {*ustr = tolower(*ustr); ustr++;}
1302 const char *eP, *bP = *str;
1307 while(*bP && *bP == delim) bP++;
1308 if (*bP == 0) {*buff = 0;
return 0;}
1313 while(*eP && *eP != delim) eP++;
1317 if (*eP == 0) *str = eP;
1323 if (aLen >= bsz) mLen = bsz-1;
1328 strncpy(buff, bP, mLen);
1346 static const int maxFiles = 256;
1348 int myfd, logFD =
eDest.baseFD();
1352 if (noLog)
eDest.Emsg(
"Config",
"Warning! No log file specified; "
1353 "backgrounding disables all logging!");
1357 if ((mypid = fork()) < 0)
1358 {
eDest.Emsg(
"Config", errno,
"fork process 1 for backgrounding");
1372 if(
read( pipeFD[0], &status,
sizeof(status) ) !=
sizeof(status) )
1386 {
eDest.Emsg(
"Config", errno,
"doing setsid() for backgrounding");
1392 if ((mypid = fork()) < 0)
1393 {
eDest.Emsg(
"Config", errno,
"fork process 2 for backgrounding");
1396 else if (mypid) _exit(0);
1401 if ((myfd =
open(
"/dev/null", O_RDWR)) < 0)
1402 {
eDest.Emsg(
"Config", errno,
"open /dev/null for backgrounding");
1405 dup2(myfd, 0); dup2(myfd, 1); dup2(myfd, 2); dup2(myfd, logFD);
1410 for (myfd = 3; myfd < maxFiles; myfd++)
1411 if( (!pipeFD || myfd != pipeFD[1]) && myfd != logFD )
close(myfd);
1420 struct passwd *pEnt, pStruct;
1427 {
int n = LookUp(uidMap,
static_cast<unsigned int>(uID),uName,uNsz);
1428 if (n > 0)
return (n < uNsz ? n : 0);
1434 rc = getpwuid_r(uID, &pStruct, pBuff,
sizeof(pBuff), &pEnt);
1436 {n = snprintf(uName, uNsz,
"%ud",
static_cast<unsigned int>(uID));
1437 return (n >= uNsz ? 0 : n);
1443 AddID(uidMap,
static_cast<unsigned int>(uID), pEnt->pw_name, keepT);
1447 n = strlen(pEnt->pw_name);
1448 if (uNsz <= (
int)strlen(pEnt->pw_name))
return 0;
1449 strcpy(uName, pEnt->pw_name);
1459 struct passwd *pEnt, pStruct;
1466 rc = getpwuid_r(uID, &pStruct, pBuff,
sizeof(pBuff), &pEnt);
1468 if (!pEnt)
return ESRCH;
1472 if (uNsz <= (
int)strlen(pEnt->pw_name))
return ENAMETOOLONG;
1473 strcpy(uName, pEnt->pw_name);
1483 static const mode_t mMask = S_IRWXU | S_IRWXG | S_IRWXO;
1488 if (
stat(path, &buf))
1489 {
if (errno == ENOENT)
return "does not exist.";
1496 {
if (!S_ISDIR(buf.st_mode))
return "is not a directory.";
1498 if (!S_ISREG(buf.st_mode))
return "is not a file.";
1503 if ((buf.st_mode & mMask) & ~allow)
return "has excessive access rights.";
1519 if( (fd =
open( path, O_WRONLY|O_CREAT|O_TRUNC, 0644 )) < 0 )
1521 eDest.Emsg(
"Config", errno,
"create pidfile" );
1525 if(
write( fd, buff, snprintf( buff,
sizeof(buff),
"%d",
1526 static_cast<int>(getpid()) ) ) < 0 )
1528 eDest.Emsg(
"Config", errno,
"write to pidfile" );
1541 int statRet =
::stat(path,&buf);
1543 modificationTime = buf.st_mtime;
1550 while( str.size() && !isgraph(str[0]) ) str.erase(str.begin());
1554 while( str.size() && !isgraph(str[str.size()-1]) )
1555 str.resize (str.size () - 1);
1559 const auto toTrim = [](
char c) {
return !isgraph(c); };
1561 size_t end = sv.size();
1563 while (start < end && toTrim(sv[start])) ++start;
1564 while (end > start && toTrim(sv[end - 1])) --end;
1566 sv = sv.substr(start, end - start);
1571 auto [ptr,
ec] = std::from_chars(sv.data(), sv.data() + sv.size(), temp);
1573 if (
ec == std::errc::invalid_argument) {
1574 throw std::invalid_argument(
"Invalid number format");
1576 if (
ec == std::errc::result_out_of_range || temp > std::numeric_limits<uint8_t>::max()) {
1577 throw std::out_of_range(
"Value out of range for unsigned short");
1580 return static_cast<unsigned short>(temp);
1593 static constexpr char token_chars[] =
"-._~+/=:%";
1595 for (
char ch : token_chars)
1612 static const regex_t auth_regex = []() {
1613 constexpr char re[] =
1614 "(authz=|(transferheader)?(www-|proxy-)?auth(orization|enticate)[[:space:]]*:[[:space:]]*)"
1615 "(Bearer([[:space:]]|%20)?(token([[:space:]]|%20)?)?)?";
1619 if (regcomp(®ex, re, REG_EXTENDED | REG_ICASE) != 0)
1620 throw std::runtime_error(
"Failed to compile regular expression");
1627 std::string redacted;
1628 const char *
const text = input.c_str();
1630 while (regexec(&auth_regex, text + offset, 1, &match, 0) == 0) {
1631 redacted.append(text + offset, match.rm_eo).append(
"REDACTED");
1633 offset += match.rm_eo;
1639 return redacted.append(text + offset);
1644 return std::isalnum(c) || c ==
'-' || c ==
'_' || c ==
'.' || c ==
'~';
1656 static const char hex[] =
"0123456789ABCDEF";
1659 out.reserve(input.size() * 3);
1661 for (
unsigned char c: input) {
1666 out.push_back(hex[c >> 4]);
1667 out.push_back(hex[c & 0x0f]);
1675 if (c >=
'0' && c <=
'9')
return c -
'0';
1676 if (c >=
'A' && c <=
'F')
return c -
'A' + 10;
1677 if (c >=
'a' && c <=
'f')
return c -
'a' + 10;
1691 out.reserve(input.size());
1693 for (
size_t i = 0; i < input.size(); ++i) {
1694 if (input[i] ==
'%' && i + 2 < input.size() &&
1695 std::isxdigit(input[i + 1]) &&
1696 std::isxdigit(input[i + 2])) {
1697 const int hi =
from_hex(input[i + 1]);
1698 const int lo =
from_hex(input[i + 2]);
1699 out.push_back(
static_cast<char>((hi << 4) | lo));
1701 }
else if (input[i] ==
'+') {
1704 out.push_back(input[i]);
1717void stripCgi(std::string& url,
const std::unordered_set<std::string> &cgiKeys)
1719 for (
const auto &key : cgiKeys) {
1723 const std::string needle = key +
"=";
1724 size_t spos = 0, epos = 0;
1726 while ((spos = url.find(needle, spos)) != std::string::npos) {
1730 url.erase(spos, epos - spos);
1736 if ((spos = url.find(
"?&")) != std::string::npos)
1737 url.erase(spos + 1, 1);
1740 if (!url.empty() && url.back() ==
'?')
1746 std::string tmp = url.
c_str();
1754 const size_t q = target.find(
'?');
1755 if (q == std::string::npos) {host.assign(target); cgi.clear();}
1756 else {host.assign(target.data(), q);
1757 cgi.assign(target.data() + q, target.size() - q);
static XrdSysError eDest(0,"crypto_")
uint32_t crc32c(uint32_t crc, void const *buf, size_t len)
void stripCgi(std::string &url, const std::unordered_set< std::string > &cgiKeys)
static bool is_token_character(int c)
static int from_hex(char c)
void splitHostCgi(std::string_view target, std::string &host, std::string &cgi)
static bool is_rfc3986_unreserved(unsigned char c)
std::string obfuscateAuth(const std::string &input)
const char * XrdSysE2T(int errcode)
static bool Match(const char *hName, const char *pattern)
static bool Parse(const char *hSpec, const char **hName, const char **hNend, const char **hPort, const char **hPend)
static uint32_t Calc32C(const void *data, size_t count, uint32_t prevcs=0)
char * Get(const char *varname)
MDLen
SHA3 digest lengths (bits to bytes).
static void * Calc(const void *in, size_t inlen, void *md, MDLen mdlen)
int tokenize(XrdOucString &tok, int from, char del=':')
const char * c_str() const
static char * parseHome(XrdSysError &eDest, XrdOucStream &Config, int &mode)
static void Sanitize(char *instr, char subc='_')
static bool getGID(const char *gName, gid_t &gID)
static const mode_t pathMode
static const char * HSize(size_t bytes, char *buff, int bsz)
static int isFWD(const char *path, int *port=0, char *hBuff=0, int hBLen=0, bool pTrim=false)
static int UserName(uid_t uID, char *uName, int uNsz)
static char * Ident(long long &mySID, char *iBuff, int iBlen, const char *iHost, const char *iProg, const char *iName, int Port)
static bool getUID(const char *uName, uid_t &uID, gid_t *gID=0)
static int getModificationTime(const char *path, time_t &modificationTime)
static const char * ValPath(const char *path, mode_t allow, bool isdir)
static char * genPath(const char *path, const char *inst, const char *psfx=0)
static uint8_t touint8_t(const std::string_view sv)
static int Token(const char **str, char delim, char *buff, int bsz)
static void Random(unsigned char *buff, unsigned int inblen)
static int ReLink(const char *path, const char *target, mode_t mode=0)
static bool parseLib(XrdSysError &eDest, XrdOucStream &Config, const char *libName, char *&path, char **libparm)
static int hex2bin(const char *hex, char *bin, int size)
static int is1of(char *val, const char **clist)
static std::string UrlDecode(const std::string &input)
static const char * InstName(int TranOpt=0)
static std::string UrlEncode(const std::string &input)
static char * eText(int rc, char *eBuff, int eBlen)
static int argList(char *args, char **argV, int argC)
static bool mode2mask(const char *mode, mode_t &mask)
static std::string genHumanSize(size_t size, uint64_t base)
static int GidName(gid_t gID, char *gName, int gNsz, time_t keepT=0)
static int UidName(uid_t uID, char *uName, int uNsz, time_t keepT=0)
static char * bin2hex(char *inbuff, int dlen, char *buff, int blen, bool sep=true)
static int Log10(unsigned long long n)
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
static int makePath(char *path, mode_t mode, bool reset=false)
static int GroupName(gid_t gID, char *gName, int gNsz)
static void trim(std::string &str)
static bool findPgm(const char *pgm, XrdOucString &path)
static bool PidFile(XrdSysError &eDest, const char *path)
static const char * i2bstr(char *buff, int blen, int val, bool pad=false)
static void toLower(char *str)
static int fmtBytes(long long val, char *buff, int bsz)
static int Log2(unsigned long long n)
static void makeHome(XrdSysError &eDest, const char *inst)
static bool endsWith(const char *text, const char *ending, int endlen)
static void Undercover(XrdSysError &eDest, int noLog, int *pipeFD=0)
static char * getFile(const char *path, int &rc, int maxsz=10240, bool notempty=true)
static char * subLogfn(XrdSysError &eDest, const char *inst, char *logfn)