struct dirent *subdirfile_ent;
DIR *subDIR;
- if (((strcmp(file, GRST_ACL_FILE) != 0) && !GRSTgaclPermHasWrite(perm)) ||
+ if ((file[0] == '\0') ||
+ ((strcmp(file, GRST_ACL_FILE) != 0) && !GRSTgaclPermHasWrite(perm)) ||
((strcmp(file, GRST_ACL_FILE) == 0) && !GRSTgaclPermHasAdmin(perm)))
GRSThttpError("403 Forbidden");
FILE *fp;
GRSThttpBody bp;
- if (!GRSTgaclPermHasWrite(perm) || (strcmp(file, GRST_ACL_FILE) == 0))
- GRSThttpError("403 Forbidden");
+ if ((file[0] == '\0') ||
+ !GRSTgaclPermHasWrite(perm) ||
+ (strcmp(file, GRST_ACL_FILE) == 0)) GRSThttpError("403 Forbidden");
dnlistsuri = getenv("GRST_DN_LISTS_URI");
if (dnlistsuri == NULL) dnlistsuri = getenv("REDIRECT_GRST_DN_LISTS_URI");
if (!GRSTgaclPermHasWrite(perm) || (strcmp(file, GRST_ACL_FILE) == 0))
GRSThttpError("403 Forbidden");
- if (index(file, '/') != NULL) GRSThttpError("403 Forbidden");
+ if (file[0] == '\0') GRSThttpError("403 Forbidden");
dir_path_file = malloc(strlen(dir_path) + strlen(file) + 2);
strcpy(dir_path_file, dir_path);
if (stat(dir_path_file, &statbuf) != 0) GRSThttpError("404 Not Found");
newfile = GRSThttpGetCGI("newfile");
-
- if ((strcmp(newfile, GRST_ACL_FILE) == 0) ||
+ if ((index(newfile, '/') != NULL) ||
+ (index(newfile, '<') != NULL) ||
+ (index(newfile, '>') != NULL) ||
+ (index(newfile, '&') != NULL) ||
+ (index(newfile, '"') != NULL)) newfile[0] = '\0';
+
+ if ((newfile[0] == '\0') ||
+ (strcmp(newfile, GRST_ACL_FILE) == 0) ||
(strcmp(newfile, file) == 0)) GRSThttpError("403 Forbidden");
dir_path_newfile = malloc(strlen(dir_path) + strlen(newfile) + 2);
if (!GRSTgaclPermHasRead(perm)) GRSThttpError("403 Forbidden");
- if (index(file, '/') != NULL) GRSThttpError("403 Forbidden");
+ if (file[0] == '\0') GRSThttpError("403 Forbidden");
dir_path_file = malloc(strlen(dir_path) + strlen(file) + 2);
if (!GRSTgaclPermHasRead(perm)) GRSThttpError("403 Forbidden");
- if (index(file, '/') != NULL) GRSThttpError("403 Forbidden");
+ if (file[0] == '\0') GRSThttpError("403 Forbidden");
puts("Status: 200 OK\nContent-Type: text/html");
if (!GRSTgaclPermHasRead(perm)) GRSThttpError("403 Forbidden");
- if (index(file, '/') != NULL) GRSThttpError("403 Forbidden");
+ if (file[0] == '\0') GRSThttpError("403 Forbidden");
puts("Status: 200 OK\nContent-Type: text/html");
if (!GRSTgaclPermHasWrite(perm)) GRSThttpError("403 Forbidden");
- if (index(file, '/') != NULL) GRSThttpError("403 Forbidden");
+ if (file[0] == '\0') GRSThttpError("403 Forbidden");
puts("Status: 200 OK\nContent-Type: text/html");
if (!GRSTgaclPermHasWrite(perm)) GRSThttpError("403 Forbidden");
- if (index(file, '/') != NULL) GRSThttpError("403 Forbidden");
+ if (file[0] == '\0') GRSThttpError("403 Forbidden");
dir_path_file = malloc(strlen(dir_path) + strlen(file) + 2);
dnlistsuri = getenv("GRST_DN_LISTS_URI");
if (dnlistsuri == NULL) dnlistsuri = getenv("REDIRECT_GRST_DN_LISTS_URI");
- if (!GRSTgaclPermHasWrite(perm) ||
+ if ((file[0] == '\0') ||
+ !GRSTgaclPermHasWrite(perm) ||
(dnlistsuri == NULL) ||
(strncmp(dnlistsuri, dir_uri, strlen(dnlistsuri)) != 0))
GRSThttpError("403 Forbidden");
return 1;
}
+char *html_escape(apr_pool_t *pool, char *s)
+{
+ int htmlspecials, i;
+ char *escaped, *p;
+
+ for (htmlspecials=0,p=s; *p != '\0'; ++p)
+ if ((*p == '<') || (*p == '>') || (*p == '&') || (*p == '"'))
+ ++htmlspecials;
+
+ escaped = apr_palloc(pool, strlen(s) + htmlspecials * 6);
+
+ for (i=0,p=s; *p != '\0'; ++p)
+ {
+ if (*p == '<')
+ {
+ strcpy(&escaped[i], "<");
+ i += 4;
+ }
+ else if (*p == '>')
+ {
+ strcpy(&escaped[i], ">");
+ i += 4;
+ }
+ else if (*p == '&')
+ {
+ strcpy(&escaped[i], "&");
+ i += 5;
+ }
+ else if (*p == '"')
+ {
+ strcpy(&escaped[i], """);
+ i += 6;
+ }
+ else
+ {
+ escaped[i] = *p;
+ ++i;
+ }
+ }
+
+ escaped[i] = '\0';
+
+ return escaped;
+}
+
char *make_admin_footer(request_rec *r, mod_gridsite_dir_cfg *conf,
int isdirectory)
/*
(strncmp(grst_cred_auri_0, "dn:", 3) == 0))
{
dn = &grst_cred_auri_0[3];
- if (dn[0] == '\0') dn = NULL;
+ if (dn[0] == '\0') dn = NULL;
}
if (dn != NULL)
{
- temp = apr_psprintf(r->pool, "You are %s<br>\n", dn);
+ temp = apr_psprintf(r->pool,
+ "You are %s<br>\n", html_escape(r->pool,dn));
out = apr_pstrcat(r->pool, out, temp, NULL);
if (r->notes != NULL)
return out;
}
-void delegation_header(request_rec *r, mod_gridsite_dir_cfg *conf){
-
+void delegation_header(request_rec *r, mod_gridsite_dir_cfg *conf)
+{
apr_table_add(r->headers_out,
apr_pstrdup(r->pool, "Proxy-Delegation-Service"),
apr_psprintf(r->pool,"https://%s%s", r->hostname, conf->delegationuri));
int i, fd, n, nn;
char *buf, *p, *s, *head_formatted, *header_formatted,
*body_formatted, *admin_formatted, *footer_formatted, *temp,
- modified[99], *d_namepath, *indexheaderpath, *indexheadertext;
+ modified[99], *d_namepath, *indexheaderpath, *indexheadertext,
+ *encoded, *escaped;
size_t length;
struct stat statbuf;
struct tm mtime_tm;
strftime(modified, sizeof(modified),
"<td align=right>%R</td><td align=right>%e %b %y</td>",
&mtime_tm);
-
+
+ encoded = GRSThttpUrlMildencode(namelist[n]->d_name);
+ escaped = html_escape(r->pool, namelist[n]->d_name);
+
if (S_ISDIR(statbuf.st_mode))
temp = apr_psprintf(r->pool,
"<tr><td><a href=\"%s/\" content-length=\"%ld\" "
"last-modified=\"%ld\">"
"%s/</a></td>"
"<td align=right>%ld</td>%s</tr>\n",
- namelist[n]->d_name, statbuf.st_size, statbuf.st_mtime,
- namelist[n]->d_name,
+ encoded, statbuf.st_size, statbuf.st_mtime,
+ escaped,
statbuf.st_size, modified);
else temp = apr_psprintf(r->pool,
"<tr><td><a href=\"%s\" content-length=\"%ld\" "
"last-modified=\"%ld\">"
"%s</a></td>"
"<td align=right>%ld</td>%s</tr>\n",
- namelist[n]->d_name, statbuf.st_size, statbuf.st_mtime,
- namelist[n]->d_name,
+ encoded, statbuf.st_size, statbuf.st_mtime,
+ escaped,
statbuf.st_size, modified);
+
+ free(encoded);
+ /* escaped done with pool so no free() */
body_formatted = apr_pstrcat(r->pool,body_formatted,temp,NULL);
}
/* try to find DN Lists in dir[] and its subdirs that match the fulluri[]
prefix. add blobs of HTML to body as they are found. */
{
- char *unencname, modified[99], *oneline, *d_namepath;
+ char *unencname, modified[99], *oneline, *d_namepath,
+ *mildencoded;
DIR *oneDIR;
struct dirent *onedirent;
struct tm mtime_tm;
strftime(modified, sizeof(modified),
"<td align=right>%R</td><td align=right>%e %b %y</td>",
&mtime_tm);
-
+
+ mildencoded = GRSThttpUrlMildencode(&unencname[fullurilen]);
+
oneline = apr_psprintf(pool,
"<tr><td><a href=\"%s\" "
"content-length=\"%ld\" "
"last-modified=\"%ld\">"
"%s</a></td>"
"<td align=right>%ld</td>%s</tr>\n",
- &unencname[fullurilen], statbuf.st_size,
- statbuf.st_mtime, unencname,
+ mildencoded, statbuf.st_size,
+ statbuf.st_mtime,
+ html_escape(pool, unencname),
statbuf.st_size, modified);
+ free(mildencoded);
+
*body = apr_pstrcat(pool, *body, oneline, NULL);
}
char *capath;
time_t last_used;
} handles[GRST_SLASH_MAX_HANDLES];
+
+pthread_mutex_t cache_mutex;
int debugmode = 0;
int number_of_tries = 1, sitecast_domain_len = 0;
if (asprintf(&s, "%s/%s", currentdirname, ent->d_name) == -1) continue;
- syslog(LOG_DEBUG, "cleanup_thread() stat(%s)", s);
+ if (debugmode) syslog(LOG_DEBUG, "cleanup_thread() stat(%s)", s);
+ pthread_mutex_lock(&cache_mutex);
if (stat(s, &ent_stat) == 0) /* ignore if gone already! */
{
if (S_ISDIR(ent_stat.st_mode))
{
- if ((cleanup_recurse(s) == 0) &&
- (ent_stat.st_mtime < now - GRST_SLASH_CACHE_EXPIRE))
+ pthread_mutex_unlock(&cache_mutex); /* unlock during recurse */
+
+ if (cleanup_recurse(s) == 0) /* directory is now empty */
{
- syslog(LOG_DEBUG, "cleanup_thread() rmdir(%s)", s);
- rmdir(s);
+ pthread_mutex_lock(&cache_mutex); /* lock for stat/rmdir */
+
+ if ((stat(s, &ent_stat) == 0) &&
+ (S_ISDIR(ent_stat.st_mode)) &&
+ (ent_stat.st_mtime < now - GRST_SLASH_CACHE_EXPIRE))
+ rmdir(s);
+ else ++num_left_here;
+
+ pthread_mutex_unlock(&cache_mutex);
+
+ if (debugmode) syslog(LOG_DEBUG, "cleanup_thread() rmdir(%s)", s);
}
else ++num_left_here;
}
{
if (ent_stat.st_mtime < now - GRST_SLASH_CACHE_EXPIRE)
{
- syslog(LOG_DEBUG, "cleanup_thread() unlink(%s)", s);
+ if (debugmode) syslog(LOG_DEBUG, "cleanup_thread() unlink(%s)", s);
unlink(s);
}
else ++num_left_here;
+
+ pthread_mutex_unlock(&cache_mutex);
}
}
+ else pthread_mutex_unlock(&cache_mutex);
free(s);
}
{
while (1)
{
- syslog(LOG_DEBUG, "cleanup_thread() scan starts");
-
cleanup_recurse(GRST_SLASH_HEADERS);
cleanup_recurse(GRST_SLASH_BLOCKS);
cleanup_recurse(GRST_SLASH_TMP);
- syslog(LOG_DEBUG, "cleanup_thread() scan completes");
-
sleep(GRST_SLASH_CACHE_EXPIRE / 2);
}
}
if (strptime(&s[15], "%a, %d %b %Y %T GMT", &modified_tm) != NULL)
{
- request_data->modified = mktime(&modified_tm);
+ modified_tm.tm_isdst = 0;
+ request_data->modified = timegm(&modified_tm);
request_data->modified_set = 1;
}
else if (strptime(&s[15], "%a, %d-%b-%y %T GMT", &modified_tm) != NULL)
{
- request_data->modified = mktime(&modified_tm);
+ modified_tm.tm_isdst = 0;
+ request_data->modified = timegm(&modified_tm);
request_data->modified_set = 1;
}
else if (strptime(&s[15], "%a %b %d %T %Y", &modified_tm) != NULL)
{
- request_data->modified = mktime(&modified_tm);
+ modified_tm.tm_isdst = 0;
+ request_data->modified = timegm(&modified_tm);
request_data->modified_set = 1;
}
}
mesg[n] = '\0';
- syslog(LOG_DEBUG, "%d %s%s%s%s",
+ if (debugmode) syslog(LOG_DEBUG, "%d %s%s%s%s",
*((int *) i),
(infotype == CURLINFO_HEADER_IN ) ? "<<" : "",
(infotype == CURLINFO_HEADER_OUT) ? ">>" : "",
for (i=0; i <= igroup; ++i)
{
- if (debugmode)
- syslog(LOG_DEBUG, "Querying multicast group %d.%d.%d.%d:%d:%d:%d\n",
+ if (debugmode) syslog(LOG_DEBUG, "Querying multicast group %d.%d.%d.%d:%d:%d:%d\n",
groups[i].quad1, groups[i].quad2,
groups[i].quad3, groups[i].quad4,
groups[i].port, groups[i].ttl,
off_t *length, time_t *modified)
{
char *encoded_filename, *disk_filename;
- int len;
+ int len, fd;
long content_length, last_modified;
FILE *fp;
struct stat statbuf;
if (encoded_filename[len - 1] == '/') /* a directory */
asprintf(&disk_filename, "%s/%d%s%s",
GRST_SLASH_HEADERS, fuse_ctx->uid, encoded_filename, GRST_SLASH_DIRFILE);
- else asprintf(&disk_filename, "%s/%d%s%s",
+ else asprintf(&disk_filename, "%s/%d%s",
GRST_SLASH_HEADERS, fuse_ctx->uid, encoded_filename);
free(encoded_filename);
-// Change to fstat for the benefit of multiple threads:
+ if ((fd = open(disk_filename, O_RDONLY)) == -1)
+ {
+ if (debugmode) syslog(LOG_DEBUG, "open(%s) in cache fails", disk_filename);
+ free(disk_filename);
+ return 0;
+ }
- if (stat(disk_filename, &statbuf) != 0) /* no cache file to read */
+ if (fstat(fd, &statbuf) != 0) /* no cache file to read */
{
+ close(fd);
+ if (debugmode) syslog(LOG_DEBUG, "fstat(%s) in cache fails", disk_filename);
free(disk_filename);
return 0;
}
if (statbuf.st_mtime < now - GRST_SLASH_CACHE_EXPIRE)
{
+ close(fd);
+ if (debugmode) syslog(LOG_DEBUG, "%s in cache has expired", disk_filename);
unlink(disk_filename); /* tidy up expired cache file */
free(disk_filename);
return 0;
if (debugmode) syslog(LOG_DEBUG, "Opening %s from cache", disk_filename);
- fp = fopen(disk_filename, "r");
free(disk_filename);
- if (fp != NULL)
+ if ((fp = fdopen(fd, "r")) != NULL)
{
fscanf(fp, "content-length=%ld last-modified=%ld ",
&content_length, &last_modified);
return 1;
}
+ close(fd);
+
return 0;
}
int write_headers_to_cache(struct fuse_context *fuse_ctx, char *filename,
off_t length, time_t modified)
{
- int fd, len;
+ int fd, len, ret;
char *tempfile, *headline, *encoded_filename, *p, *newdir,
*new_filename;
struct stat statbuf;
{
if (!S_ISDIR(statbuf.st_mode)) /* exists already - not a directory! */
{
+ pthread_mutex_lock(&cache_mutex);
unlink(newdir);
mkdir(newdir, S_IRUSR | S_IWUSR | S_IXUSR);
+ pthread_mutex_unlock(&cache_mutex);
}
/* else it already exists as a directory - so ok */
}
rmdir(new_filename);
}
- rename(tempfile, new_filename);
+ pthread_mutex_lock(&cache_mutex);
+ ret = rename(tempfile, new_filename);
+ pthread_mutex_unlock(&cache_mutex);
- if (debugmode) syslog(LOG_DEBUG, "Added %s to cache (%ld %ld)\n",
- new_filename, length, modified);
+ if (debugmode) syslog(LOG_DEBUG, "Move %s to %s in cache (%d;%ld,%ld)\n",
+ tempfile, new_filename, ret, length, modified);
free(tempfile);
free(new_filename);
memset(stbuf, 0, sizeof(struct stat));
stbuf->st_mode = S_IFREG | 0755;
stbuf->st_nlink = 1;
+ stbuf->st_uid = fuse_ctx.uid;
+ stbuf->st_gid = fuse_ctx.gid;
if ((strcmp(rawpath, "/") == 0) ||
(strcmp(rawpath, "/http") == 0) ||
else if (ret == 0)
{
stbuf->st_nlink = 1;
- stbuf->st_uid = fuse_ctx.uid;
- stbuf->st_gid = fuse_ctx.gid;
stbuf->st_size = stat_tmp.st_size;
stbuf->st_blksize = stat_tmp.st_blksize;
stbuf->st_blocks = stat_tmp.st_blocks;
free(path);
return 0;
}
-
+ else if (debugmode) syslog(LOG_DEBUG,
+ "Headers for %s not found in cache at %s\n", url, path);
+
if (debugmode) syslog(LOG_DEBUG, "Get details for %s over network\n", url);
bzero(&request_data, sizeof(struct grst_request));
free(encoded_filename);
+ pthread_mutex_lock(&cache_mutex);
rename(tempfile, new_filename);
+ pthread_mutex_unlock(&cache_mutex);
if (debugmode) syslog(LOG_DEBUG, "Added %s to block cache", new_filename);
return 0;
}
-int drop_cache_blocks(struct fuse_context *fuse_ctx, char *filename)
-/* drop ALL the blocks cached for this file, and delete the directory in
- the blocks cache for this file */
+void drop_cache_blocks(struct fuse_context *fuse_ctx, char *filename)
+/*
+ Drop ALL the blocks cached for this file by moving the whole directory
+ to GRST_SLASH_TMP and letting the cleanup thread deal with them when
+ it has time; and then remove the headers cached for this file.
+*/
{
- int ret;
- char *encoded_filename, *dirname, *blockname;
- DIR *blocksDIR;
- struct dirent *blocks_ent;
+ char *encoded_filename, *dirname, *headersname;
+// DIR *blocksDIR;
+// struct dirent *blocks_ent;
encoded_filename = GRSThttpUrlMildencode(filename);
- asprintf(&dirname, "%s/%d%s",
+ /* move blocks directory */
+
+ asprintf(&dirname, "%s/%d%s",
GRST_SLASH_BLOCKS, fuse_ctx->uid, encoded_filename);
- free(encoded_filename);
+ rename(dirname, GRST_SLASH_TMP);
+ free(dirname);
+
+ /* remove headers file */
+
+ asprintf(&headersname, "%s/%d%s",
+ GRST_SLASH_HEADERS, fuse_ctx->uid, encoded_filename);
+
+ unlink(headersname);
+ free(headersname);
+ /* finish */
+
+ free(encoded_filename);
+ return;
+
+#if 0
blocksDIR = opendir(dirname);
if (blocksDIR == NULL) /* no directory to delete (probably) */
free(dirname);
return ret ? 1 : 0; /* return 1 on error, 0 on rmdir() success */
+#endif
}
static int slashgrid_read(const char *path, char *buf,
if (debugmode) syslog(LOG_DEBUG, "disk_filename=%s", disk_filename);
- if ((stat(disk_filename, &statbuf) != 0) ||
+ fd = open(disk_filename, O_RDONLY);
+
+ if ((fd == -1) ||
+ (fstat(fd, &statbuf) != 0) ||
(statbuf.st_mtime < now - GRST_SLASH_CACHE_EXPIRE))
{
+ if (fd != -1) close(fd);
+
write_block_to_cache(&fuse_ctx, (char *) path,
block_i, block_i + blocksize - 1);
+
+ fd = open(disk_filename, O_RDONLY);
}
-// need to worry about cached copy being deleted (invalidated by a writing
-// thread?) between write_block_to_cache() and these reads?
-// maybe return fd from write_block_to_cache() itself???
-// the initial stat() needs to be part of this too
+ /* even if another thread deletes disk_filename between
+ open and read, we've still got it open so can carry on */
- if ((fd = open(disk_filename, O_RDONLY)) != -1)
+ if (fd != -1)
{
if (block_i == block_start)
{
handles[i].last_used = 0;
}
+ pthread_mutex_init(&cache_mutex, NULL);
+
// GRSTerrorLogFunc = slashgrid_logfunc;
GRSTgaclInit();