Esempio n. 1
0
/*
* LookupNameRsc: Return the string associated with the given resource id #, or 
*   "<Unknown>" if it's not in the table.  Bring up redownload dialog if not in table.
*/
char *LookupNameRsc(ID idnum)
{
	char *name = LookupRsc(idnum); 
	if (name == NULL)
		name = GetString(hInst, IDS_UNKNOWN);
	return name;
}
Esempio n. 2
0
/*
 * FindPlayerByName:  Return the object id of the logged-on player whose name
 *   best matches name.  Return 0 if no one matches, -1 if more than one
 *   player matches equally well.
 */
ID FindPlayerByName(char *name)
{
   list_type l;
   char *player, *ptr;
   int match, max_match;
   ID best_player;
   Bool tied;            // True if a different player matches as well as best_player

   max_match = 0;
   tied = False;
   for (l = *(cinfo->current_users); l != NULL; l = l->next)
   {
      object_node *obj = (object_node *) (l->data);

      player = LookupRsc(obj->name_res);
      if (player == NULL)
	 continue;

      ptr = name;
      match = 0;
      while (*ptr != 0 && *player != 0)
      {
	 if (toupper(*ptr) != toupper(*player))
	 {
	    match = 0;
	    break;
	 }
	 match++;
	 ptr++;
	 player++;
      }

      // Check for exact match, or extra characters in search string
      if (*player == 0)
      {
	 if (*ptr == 0)
	    return obj->id;
	 else
	    continue;
      }

      if (match > max_match)
      {
	 max_match = match;
	 best_player = obj->id;
	 tied = False;
      }
      else if (match == max_match)
	 tied = True;
   }
   
   if (max_match == 0)
      return 0;

   if (tied)
      return INVALID_ID;

   return best_player;
}
Esempio n. 3
0
/*
 * FindPlayerByNameExact:  Return the object id of the logged-on player whose name
 *   exactly matches name.  The comparison is case insensitive.
 *   Return 0 if no one matches.
 */
ID FindPlayerByNameExact(char *name)
{
  list_type l;
  char *player;

  for (l = *(cinfo->current_users); l != NULL; l = l->next)
  {
    object_node *obj = (object_node *) (l->data);
    
    player = LookupRsc(obj->name_res);
    if (player == NULL)
      continue;

    if (!stricmp(name, player))
      return obj->id;
   }
   return 0;
}
Esempio n. 4
0
Bool HandleGameStart(char *ptr, long len)
{
   char *start = ptr;
   BYTE player_num;
   
   // If we've already received our game object number, skip
   if (game_obj != 0)
      return False;

   Extract(&ptr, &game_obj, SIZE_ID);
   Extract(&ptr, &player_num, 1);
   // debug(("Chess got game start, object = %d, player # = %d\n", game_obj, player_num));

   len -= (ptr - start);
   if (len != 0)
      return False;

   switch (player_num)
   {
   case 1:
      b.color = WHITE;
      if (hChessDlg != NULL)
	 EnableWindow(GetDlgItem(hChessDlg, IDC_RESIGN), TRUE);
      break;
   case 2:
      b.color = BLACK;
      if (hChessDlg != NULL)
	 EnableWindow(GetDlgItem(hChessDlg, IDC_RESIGN), TRUE);
      break;
   default:
      b.color = OBSERVER;
      break;
   }

   // Display player's name in dialog
   ChessGotPlayerName(player_num, LookupRsc(c->player->name_res));
   
   return True;
}
Esempio n. 5
0
/*
 * CheckMessageOrder:  Loops through the resource specified by fmt_id, and
 *                     checks for "numbered parameters", indicated by a
 *                     $ and a number present after a string formatter such
 *                     as %s, %i, %q or %r (e.g. %s$2 %i$1). The message
 *                     sent by the server is reordered so that these numbers
 *                     are in order, and the parameters attached to them are
 *                     reordered accordingly. This function recurses if it
 *                     encounters a %r formatter, and reorders that resource
 *                     if needed. CheckMessageOrder should be called before
 *                     CheckServerMessage if the message could possibly
 *                     contain $number formatters. Maximum 25 formatters.
 *                     Returns the length of any fields referenced by the
 *                     resource if successful, -1 if the resource wasn't found.
 */
int CheckMessageOrder(char **params, long *len, ID fmt_id)
{
   char *new_param_ptr, *param_ptr = *params, *rsc;
   WORD string_len;
   DWORD field;
   int fieldPos = 0, currentPos = 0, tempLen = 0;
   char digit[1];
   PosArray posArray;

   // If there's nothing to reorder (i.e. no $ modifiers) don't perform
   // unnecessary work at the end.
   Bool reorder = False;

   /* Get format string from resource */
   rsc = LookupRsc(fmt_id);
   if (rsc == NULL)
   {
      PostMessage(hMain, BK_NORESOURCE, 0, 0);
      return -1;
   }

   // Zero the position array.
   memset(&posArray, 0, sizeof posArray);

   // TODO: not sure if allocating memory is the best way to do this.
   new_param_ptr = (char*)SafeMalloc(*len);
   // Copy the parameter pointer into the new memory.
   memcpy(new_param_ptr, param_ptr, *len);

   // Iterate over the resource.
   while (*rsc)
   {
      if (rsc[0] == '%')
      {
         if (rsc[1] != '\0' && rsc[2] == '$' && rsc[3] != '\0' && rsc[3] != '$')
         {
            // At least one reordering necessary, so set reorder to true.
            reorder = True;
            // Get the numbers for field position.
            if (rsc[3] >= '0' && rsc[3] <= '9')
               digit[0] = rsc[3];
            // Check for a second number.
            if (rsc[4] != '\0' && rsc[4] >= '0' && rsc[4] <= '9')
               digit[1] = rsc[4];
            // Take one, because arrays are 0-indexed.
            fieldPos = atoi(digit) - 1;
         }
         else
         {
            // No $ modifier. Use currentPos (i.e. don't move the field) in case
            // some fields do have them.
            fieldPos = currentPos;
         }

         // Don't allow defining two fields in the same place. This would
         // have unintended consequences - it isn't clear whether we should
         // swap the parameter positions or shift everything forward one place.
         for (int i = 0; i < currentPos; i++)
         {
            if (i != currentPos && posArray.fieldPos[i] == fieldPos)
            {
               PostMessage(hMain, BK_NORESOURCE, 0, 0);
               return -1;
            }
         }

         switch (rsc[1])
         {
         case 'r':
            // Get the next resource in the server message, increment
            // new_param_ptr past the resource..
            memcpy(&field, new_param_ptr, SIZE_ID);
            new_param_ptr += SIZE_ID;
            // By calling CheckMessageOrder again, we get the length of
            // anything referenced by string formatters in the next resource.
            // This section of new_param_ptr is reordered if necessary.
            tempLen = CheckMessageOrder(&new_param_ptr, len, field);
            // If we got less than 0 bytes, return -1 (fail).
            if (tempLen < 0)
            {
               PostMessage(hMain, BK_NORESOURCE, 0, 0);
               return -1;
            }
            // Increment new_param_ptr past this section.
            new_param_ptr += tempLen;
            // Add the size of the resource itself to tempLen before using it.
            tempLen += SIZE_ID;
            /* This is the new location of the field, not the old one.
               Offset by 1 position (because pos2 starts at end of pos1, etc). */
            for (int i = fieldPos + 1; i < MAXQPARAMS; i++)
               posArray.bytePos[i] += tempLen;
            posArray.fieldPos[currentPos] = fieldPos;
            posArray.size[currentPos] = tempLen;
            break;
         case 'i':
         case 's':
         case 'd':
            // Increment new_param_ptr to the next field.
            new_param_ptr += SIZE_ID;
            // Store the new position for this formatter.
            posArray.fieldPos[currentPos] = fieldPos;
            // Store the size of the current field.
            posArray.size[currentPos] = SIZE_ID;
            /* This is the new location of the field, not the old one.
               Offset by 1 position (because pos2 starts at end of pos1, etc). */
            for (int i = fieldPos + 1; i < MAXQPARAMS; i++)
               posArray.bytePos[i] += SIZE_ID;
            break;
         case 'q':
            // Get the length of the string.
            memcpy(&string_len, new_param_ptr, SIZE_STRING_LEN);
            // Increment new_param_ptr to the next field.
            new_param_ptr += string_len + SIZE_STRING_LEN;
            // Store the new position for this formatter.
            posArray.fieldPos[currentPos] = fieldPos;
            // Store the size of the current field.
            posArray.size[currentPos] = string_len + SIZE_STRING_LEN;
            /* This is the new location of the field, not the old one.
               Offset by 1 position (because pos2 starts at end of pos1, etc). */
            for (int i = fieldPos + 1; i < MAXQPARAMS; i++)
               posArray.bytePos[i] += string_len + SIZE_STRING_LEN;
            break;
         case '%':
            // To skip both %, increment rsc here.
            rsc++;
         default:
            break;
         }
         currentPos++;
      }
      rsc++;
   }

   if (reorder && currentPos > 0)
   {
      // Decrement new_param_ptr back to the start before copying to param_ptr.
      new_param_ptr -= posArray.bytePos[currentPos];
      for (int i = 0; i < currentPos; i++)
      {
         // Copy the data at the current position to the requested field position,
         // using the byte position stored at that field position. Use two ptrs
         // here because there's no guarantee that fields are all the same size.
         memcpy(param_ptr + posArray.bytePos[posArray.fieldPos[i]], new_param_ptr, posArray.size[i]);
         new_param_ptr += posArray.size[i];
      }
   }
   // Decrement new_param_ptr back to the start before clearing memory.
   new_param_ptr -= posArray.bytePos[currentPos];
   SafeFree(new_param_ptr);

   return posArray.bytePos[currentPos];
}
Esempio n. 6
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;
}