com_jmp(): Handle negative values gracefully.
[paraslash.git] / command.c
index 67f6bf3c713b5de3d542d96f63848cb0014326dc..0a76f68ee03dfeadf2d48e0b5065594caecbfef0 100644 (file)
--- a/command.c
+++ b/command.c
@@ -457,6 +457,7 @@ EXPORT_SERVER_CMD_HANDLER(version);
        ITEM(chunk_time) \
        ITEM(num_chunks) \
        ITEM(amplification) \
+       ITEM(play_time) \
 
 /*
  * Create a set of audio-file related status items with empty values. These are
@@ -663,8 +664,7 @@ EXPORT_SERVER_CMD_HANDLER(nomore);
 static int com_ff(struct command_context *cc, struct lls_parse_result *lpr)
 {
        long promille;
-       int ret, backwards = 0;
-       unsigned i;
+       int i, ret;
        char c, *errctx;
 
        ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx));
@@ -672,20 +672,33 @@ static int com_ff(struct command_context *cc, struct lls_parse_result *lpr)
                send_errctx(cc, errctx);
                return ret;
        }
-       if (!(ret = sscanf(lls_input(0, lpr), "%u%c", &i, &c)))
-               return -E_COMMAND_SYNTAX;
-       if (ret > 1 && c == '-')
-               backwards = 1; /* jmp backwards */
+       ret = para_atoi32(lls_input(0, lpr), &i);
+       if (ret < 0) {
+               if (ret != -E_ATOI_JUNK_AT_END)
+                       return ret;
+               /*
+                * Compatibility code to keep the historic syntax (ff 30-)
+                * working. This can be removed after 0.7.0.
+                */
+               ret = sscanf(lls_input(0, lpr), "%i%c", &i, &c);
+               if (ret <= 0)
+                       return -E_COMMAND_SYNTAX;
+               if (ret > 1 && c == '-') {
+                       PARA_WARNING_LOG("use of obsolete syntax\n");
+                       i = -i;
+               }
+       }
        mutex_lock(mmd_mutex);
        ret = -E_NO_AUDIO_FILE;
        if (!mmd->afd.afhi.chunks_total || !mmd->afd.afhi.seconds_total)
                goto out;
        ret = 1;
        promille = (1000 * mmd->current_chunk) / mmd->afd.afhi.chunks_total;
-       if (backwards)
-               promille -= 1000 * i / mmd->afd.afhi.seconds_total;
-       else
-               promille += 1000 * i / mmd->afd.afhi.seconds_total;
+       /*
+        * We need this cast because without it the expression on the right
+        * hand side is of unsigned type.
+        */
+       promille += 1000 * i / (int)mmd->afd.afhi.seconds_total;
        if (promille < 0)
                promille = 0;
        if (promille > 1000) {
@@ -704,8 +717,7 @@ EXPORT_SERVER_CMD_HANDLER(ff);
 
 static int com_jmp(struct command_context *cc, struct lls_parse_result *lpr)
 {
-       long unsigned int i;
-       int ret;
+       int i, ret;
        char *errctx;
 
        ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx));
@@ -713,18 +725,16 @@ static int com_jmp(struct command_context *cc, struct lls_parse_result *lpr)
                send_errctx(cc, errctx);
                return ret;
        }
-       if (sscanf(lls_input(0, lpr), "%lu", &i) <= 0)
+       if (sscanf(lls_input(0, lpr), "%d", &i) <= 0)
+               return -ERRNO_TO_PARA_ERROR(EINVAL);
+       if (i < 0 || i > 100)
                return -ERRNO_TO_PARA_ERROR(EINVAL);
        mutex_lock(mmd_mutex);
        ret = -E_NO_AUDIO_FILE;
        if (!mmd->afd.afhi.chunks_total)
                goto out;
-       if (i > 100)
-               i = 100;
-       PARA_INFO_LOG("jumping to %lu%%\n", i);
+       PARA_INFO_LOG("jumping to %d%%\n", i);
        mmd->repos_request = (mmd->afd.afhi.chunks_total * i + 50) / 100;
-       PARA_INFO_LOG("sent: %lu, offset before jmp: %li\n",
-               mmd->chunks_sent, mmd->offset);
        mmd->new_vss_status_flags |= VSS_REPOS;
        mmd->new_vss_status_flags &= ~VSS_NEXT;
        ret = 1;
@@ -857,19 +867,19 @@ static int run_command(struct command_context *cc, struct iovec *iov)
  * Whenever para_server accepts an incoming tcp connection on the port it
  * listens on, it forks and the resulting child calls this function.
  *
- * An RSA-based challenge/response is used to authenticate the peer. It that
+ * An RSA-based challenge/response is used to authenticate the peer. If the
  * authentication succeeds, a random session key is generated and sent back to
  * the peer, encrypted with its RSA public key. From this point on, all
- * transfers are crypted with this session key.
+ * transfers are encrypted with this session key using a stream cipher.
  *
  * Next it is checked if the peer supplied a valid server command or a command
  * for the audio file selector. If yes, and if the user has sufficient
- * permissions to execute that command, the function calls the corresponding
- * command handler which does argument checking and further processing.
+ * permissions to execute this command, the function calls the corresponding
+ * command handler which performs argument checking and further processing.
  *
- * In order to cope with DOS attacks, a timeout is set up which terminates
- * the function if the connection was not authenticated when the timeout
- * expires.
+ * To cope with DOS attacks, a timer is set up right after the fork. If the
+ * connection was still not authenticated when the timeout expires, the child
+ * process is terminated.
  *
  * \return Standard.
  *