+
+
+/**
+ * Determine if a symlink points outside the current directory tree.
+ * This is considered "unsafe" because e.g. when mirroring somebody
+ * else's machine it might allow them to establish a symlink to
+ * /etc/passwd, and then read it through a web server.
+ *
+ * Null symlinks and absolute symlinks are always unsafe.
+ *
+ * Basically here we are concerned with symlinks whose target contains
+ * "..", because this might cause us to walk back up out of the
+ * transferred directory. We are not allowed to go back up and
+ * reenter.
+ *
+ * @param dest Target of the symlink in question.
+ *
+ * @param src Top source directory currently applicable. Basically this
+ * is the first parameter to rsync in a simple invocation, but it's
+ * modified by flist.c in slightly complex ways.
+ *
+ * @retval True if unsafe
+ * @retval False is unsafe
+ *
+ * @sa t_unsafe.c
+ **/
+int unsafe_symlink(const char *dest_path, const char *src_path)
+{
+ char *tok, *src, *dest;
+ int depth = 0;
+
+ /* all absolute and null symlinks are unsafe */
+ if (!dest_path || !*dest_path || *dest_path == '/') return 1;
+
+ src = strdup(src_path);
+ if (!src) out_of_memory("unsafe_symlink");
+
+ /* find out what our safety margin is */
+ for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
+ if (strcmp(tok,"..") == 0) {
+ depth=0;
+ } else if (strcmp(tok,".") == 0) {
+ /* nothing */
+ } else {
+ depth++;
+ }
+ }
+ free(src);
+
+ /* drop by one to account for the filename portion */
+ depth--;
+
+ dest = strdup(dest_path);
+ if (!dest) out_of_memory("unsafe_symlink");
+
+ for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
+ if (strcmp(tok,"..") == 0) {
+ depth--;
+ } else if (strcmp(tok,".") == 0) {
+ /* nothing */
+ } else {
+ depth++;
+ }
+ /* if at any point we go outside the current directory then
+ stop - it is unsafe */
+ if (depth < 0) break;
+ }
+
+ free(dest);
+ return (depth < 0);
+}
+
+
+/**
+ * Return the date and time as a string
+ **/
+char *timestring(time_t t)
+{
+ static char TimeBuf[200];
+ struct tm *tm = localtime(&t);
+
+#ifdef HAVE_STRFTIME
+ strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
+#else
+ strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));