예제 #1
0
Bool HandleLookNewsgroup(char *ptr, long len)
{
   ID resource_id;
   WORD newsgroup;
   BYTE permission;
   char message[MAXMESSAGE + 1];
   char* msg = message;
   int temp_len;
   object_node obj;

   temp_len = SIZE_NEWSGROUP_ID + 1 + SIZE_ID * 4 + SIZE_ANIMATE;
   if (len < temp_len)
      return False;

   Extract(&ptr, &newsgroup, SIZE_NEWSGROUP_ID);
   Extract(&ptr, &permission, 1);

   ExtractObject(&ptr, &obj);
   Extract(&ptr, &resource_id, SIZE_ID);

   /* Remove format string id # & other ids from length */
   if (!CheckServerMessage(&msg, &ptr, len - temp_len, resource_id))
      return False;

   UserReadNews(&obj, msg, newsgroup, permission);

   return True;
}
예제 #2
0
Bool HandleMail(char *ptr, long len)
{
   long index;
   WORD num_recipients, i;
   char message[MAXMESSAGE + MAX_SUBJECT + 200];
   char* msg = message;
   char sender[MAXUSERNAME + 1];
   char recipients[MAX_RECIPIENTS][MAXUSERNAME + 1];
   ID resource_id;
   long msg_time;
   char *start = ptr;

   Extract(&ptr, &index, 4);
   len -= 4;
   len = ExtractString(&ptr, len, sender, MAXUSERNAME);
   if (len == -1)
      return False;
   Extract(&ptr, &msg_time, SIZE_TIME);
   Extract(&ptr, &num_recipients, SIZE_NUM_RECIPIENTS);
   len -= SIZE_TIME + SIZE_NUM_RECIPIENTS;

   // If somehow mail message is screwed up, delete it
   if (num_recipients > MAX_RECIPIENTS)
   {
      RequestDeleteMail(index);
      return False;
   }

   /* If no recipients, then there is no more mail */
   if (num_recipients == 0)
   {
      MailNewMessage(0, sender, 0, NULL, NULL, 0);
      return True;
   }

   for (i=0; i < num_recipients; i++)
   {
      len = ExtractString(&ptr, len, recipients[i], MAXUSERNAME);
      if (len == -1)
         return False;
   }
   
   Extract(&ptr, &resource_id, SIZE_ID);
   len -= SIZE_ID;
   
   /* Remove format string id # & other ids from length */
   if (!CheckServerMessage(&msg, &ptr, len, resource_id))
      return False;

   MailNewMessage(index, sender, num_recipients, recipients, msg, msg_time);

   return True;
}
예제 #3
0
/*
 * CheckServerMessage:  Assemble a set of printf-style strings into a resultant
 *   string.  The initial format string is given by the fmt_id resource, and the
 *   parameters are in params.  The result is placed in message.  Len is the # of bytes
 *   in params.
 *   Returns True iff len bytes of parameters are used in assembling message, otherwise
 *   False, which indicates an error in the message from the server.
 *   The allowed printf-style format characters are:
 *   %d or %i    a literal integer
 *   %q          a literal string
 *   %s          an integer which specifies a string resource.  This resource may
 *               contain other format characters.  If so, they are matched with 
 *               parameters from params AFTER the initial string's parameters.
 *   %r          specifies that the next resource in the message should be concatenated
 *               into the place of this format character (calls CheckServerMessage)
 */
Bool CheckServerMessage(char** msg, char **params, long *len, ID fmt_id)
{
   char *fmt, *next_ptr; /* next_ptr points into format string fmt */
   char tempfmt[MAXMESSAGE], format[MAXMESSAGE], *param_ptr = *params;
   char* message;
   char message2[MAXMESSAGE];
   char* msg2 = message2; /* Pointer to message2 */
   char *rsc, type_char, *orig_message;
   DWORD field, num_chars;
   WORD string_len;
   Bool done = False;

   /* qparams are %q parameters; we need to save their positions and replace them last, 
    * even after %s (in case replacement %q string contains a literal %s) */
   /* Each element of the qparams array points to the place in params where the string
      for to replace the corresponding %q begins */
   char *qparams[MAXQPARAMS + 1];
   int num_qparams = 1;  /* Start counting at 1 to avoid null character */

   /* Get the buffer to send back the message.
    * If it turns out we have no formatting to do, then we'll send back
    * the resource string itself instead of filling the caller's limited buffer.
    */
   if (!msg || !*msg)
      return False;

   // Set the first character of msg to null terminator, so we can check
   // the length of msg.
   *msg[0] = '\0';

   message = *msg;

   /* Get format string from resources */
   fmt = LookupRsc(fmt_id);
   if (fmt == NULL)
      return False;

   /* Is there anything to format at all?
    * Or can we return the "format" resource as-is?
    */
   rsc = fmt;
   while (*rsc)
   {
      if (rsc[0] == '%')
      {
         if (rsc[1] == '%')
            rsc++;
         else
            break;
      }

      rsc++;
   }

   if (!*rsc)
   {
      *msg = fmt;

      return True;
   }

   /* Prepare to format into the caller's message buffer. */
   orig_message = message;

   /* Keep looping through string until there's nothing left to replace */
   while (!done)
   {
      done = True;  /* We'll be done if we don't find any %s's */

      /* Find first format field */
      next_ptr = strchr(fmt, '%');
      
      /* Invariant:  len is # of bytes remaining in params */
      while (next_ptr != NULL)
      {
         next_ptr++;  /* Move to type character */

         type_char = *next_ptr;
         /* If string ends with %, done */
         if (type_char == '\0')
            break;

         /* Skip marked %q parameters */
         if (type_char <= MAXQPARAMS)
         {
            next_ptr = strchr(next_ptr, '%');

            continue;
         }

         next_ptr++;  /* Move past field specification char */

         /* Make temporary buffer for this section of format string */
         strncpy(tempfmt, fmt, next_ptr - fmt);
         tempfmt[next_ptr - fmt] = '\0';

         switch (type_char)
         {
         case '%':              /* %% ==> % */
            *message++ = '%';
            break;
         case 'r':
            if (*len < SIZE_ID)
            {
               PostMessage(hMain, BK_NORESOURCE, 0, 0);
               return False;
            }
            // Get the next resource in the server message, increment param_ptr.
            memcpy(&field, param_ptr, SIZE_ID);
            param_ptr += SIZE_ID;
            *len -= SIZE_ID;

            // Process the next resource as if it were a complete message.
            if (!CheckServerMessage(&msg2, &param_ptr, len, field))
               return False;

            // Check if we're going to write outside the bounds of msg.
            if (strlen(*msg) + strlen(msg2) >= MAXMESSAGE)
            {
               PostMessage(hMain, BK_NORESOURCE, 0, 0);
               return False;
            }

            // This block of code adds the current message 'part' into message,
            // but we have to remove the 'r' and add %s as %r isn't a valid
            // sprintf formatter, while %s is.
            // Copy the part before the %r modifier into message.
            num_chars = sprintf(message, tempfmt);
            // Increment message, but remove the 'r' character.
            message += (num_chars - 1);
            // Copy the msg2 string into message.
            num_chars = sprintf(message, "%s", msg2);
            message += num_chars;

            // Reset message2 and msg2.
            message2[MAXMESSAGE];
            msg2 = message2;

            // Get rid of any numbered parameter formatters.
            if (*next_ptr == '$')
            {
               next_ptr++;
               if (*next_ptr != '$')
               {
                  next_ptr++;
               }
            }
            break;
         case 'd':
         case 'i':
         case 's':
            /* See if there are enough bytes left */
            if (*len < SIZE_ID)
               return False;

            /* Interpret next field as an integer */
            memcpy(&field, param_ptr, SIZE_ID);
            param_ptr += SIZE_ID;
            *len -= SIZE_ID;

            /* Look up resource strings; use integers immediately */
            if (type_char == 's')
            {
               done = False;
               if ((rsc = LookupRsc(field)) == NULL)
                  return False;

               num_chars = sprintf(message, tempfmt, rsc);
            }
            else
            {
               num_chars = sprintf(message, tempfmt, field);
            }

            // Get rid of any numbered parameter formatters.
            if (*next_ptr == '$')
            {
               next_ptr++;
               if (*next_ptr != '$')
               {
                  next_ptr++;
               }
            }

            message += num_chars;  /* Overwrite null char next time */
            break;
         case 'q':     /* Literal string from server */
            /* Store location; we will perform replacement later */	    
            if (*len < SIZE_STRING_LEN)
               return False;

            /* We can only hold a certain # of qparams */
            if (num_qparams <= MAXQPARAMS)
            {
               /* Save current location in parameters */
               qparams[num_qparams] = param_ptr;
            }
            memcpy(&string_len, param_ptr, SIZE_STRING_LEN);
            param_ptr += SIZE_STRING_LEN;
            *len -= SIZE_STRING_LEN;
            if (*len < string_len)
               return False;

            /* Mark this position with qparam # */
            if (num_qparams <= MAXQPARAMS)
            {
               tempfmt[(next_ptr - fmt) - 1] = (char) num_qparams;
               num_qparams++;
            }

            /* Copy this section of format string */
            strncpy(message, tempfmt, (next_ptr - fmt));
            message += (next_ptr - fmt);
            // Add a null terminator here so we can check length of string
            // if there is an %r formatter next.
            *message = '\0';

            /* Skip string */
            param_ptr += string_len;
            *len -= string_len;

            // Get rid of any numbered parameter formatters.
            if (*next_ptr == '$')
            {
               next_ptr++;
               if (*next_ptr != '$')
               {
                  next_ptr++;
               }
            }
            break;
         }

         /* Find next format field */
         fmt = next_ptr;
         next_ptr = strchr(fmt, '%');
      }
      
      /* Copy over last part of string */
      strcpy(message, fmt);

      /* Prepare for next pass */
      message = orig_message;
      strcpy(format, message);
      fmt = format;
   }

   // Set params to remainder of server message
   *params = param_ptr;

   /* Now fill in marked %q fields.  Note that format cotains copy of message */
   fmt = format;
   next_ptr = strchr(format, '%');
   while (next_ptr != NULL)
   {
      next_ptr++;  /* Move to type character */

      type_char = *next_ptr;
      /* If string ends with %, done */
      if (type_char == '\0')
         break;

      /* See if this is a marked %q field */
      if (type_char > MAXQPARAMS)
      {
         next_ptr = strchr(next_ptr, '%');

         continue;
      }

      next_ptr++;  /* Move past field specification char */

      /* Make temporary buffer for this section of format string */
      strncpy(tempfmt, fmt, next_ptr - fmt);
      tempfmt[next_ptr - fmt] = '\0';

      /* Get length of string */
      param_ptr = qparams[type_char];
      memcpy(&string_len, param_ptr, SIZE_STRING_LEN);
      param_ptr += SIZE_STRING_LEN;

      /* Hack off %q from format string */
      tempfmt[(next_ptr - fmt) - 2] = '\0';

      /* Add tempfmt and then literal string to end of message */
      strcpy(message, tempfmt);
      message += strlen(tempfmt);

      strncpy(message, param_ptr, string_len);
      message += string_len;

      fmt = next_ptr;
      next_ptr = strchr(fmt, '%');
   }

   /* Copy over last part of string */
   strcpy(message, fmt);

   return True;
}