Example #1
0
static int
rd_factor (const char **p, int *valid, int level, int *check, int print_errors)
{
  /* read a factor of an expression */
  int result;
  if (verbose >= 6)
    fprintf (stderr, "%5d (0x%04x): Starting to read factor (string=%s).\n",
	     stack[sp].line, addr, *p);
  result = rd_value (p, valid, level, check, print_errors);
  *p = delspc (*p);
  while (**p == '*' || **p == '/')
    {
      *check = 0;
      if (**p == '*')
	{
	  (*p)++;
	  result *= rd_value (p, valid, level, check, print_errors);
	}
      else if (**p == '/')
	{
	  (*p)++;
	  result /= rd_value (p, valid, level, check, print_errors);
	}
      *p = delspc (*p);
    }
  if (verbose >= 7)
    fprintf (stderr, "%5d (0x%04x): rd_factor returned %d (%04x).\n",
	     stack[sp].line, addr, result, result);
  return result;
}
Status BinCommon::rd_parms_vlst(CommandInitiator* thread, uint offset, va_list parms)
{
  const Field* b = m_fields;
  uchar token = 0;
  uint  tag = 0;
  uint  prev_tag = 0;
  bool  peek = true;
  uint  unkown_tags_limit = 30; 
  if (m_depth++ > DEPTH_LIMIT) return ERR_DECODE;
  const Field* f = &b[offset];
  const Field* e = &b[f->get_end()];     // message descriptor ended
  while (f != e) {
    if (peek) { 
      if (rd_uchar(thread, token) != OK) return ERR_DECODE;
      if (token != 'z') {
        if (token == 'N') { 
          if (rd_uchar(thread, token) != OK && token != 'z') return ERR_DECODE;
          return ERR_CALL;
        }
        if (rd_value(thread, tag) != OK || tag < prev_tag) return ERR_DECODE;
        prev_tag = tag;
      }
    }
    if (token == 'z') {
      // we shall reset all remaining fields
      f->set_field_to_default(va_arg(parms, void*));
      peek = false; // no more to read...
    } else if (tag == f->get_tag()) {  
Status BinCommon::rd_value(CommandInitiator* thread, int& val)
{
  uint uval;
  Status status = rd_value(thread, uval);
  if (status == OK) 
    val = (uval >> 1) ^ -static_cast<int>(uval & 1);
  return status;
}
Status BinCommon::rd_value(CommandInitiator* thread, Binary& value)
{
  uint size;
  Status status = rd_value(thread, size);
  if (status == OK) {
    if (size > 0) { // protect from unrealistic size?
      value.reserve(size);
      status = rd_bytes(thread, size, (char*) value.data());
    }
  }
  return status;
}
 Status BinCommon::rd_value(CommandInitiator* thread, String& value)  
 {
   uint size;
   Status status = rd_value(thread, size);
   if (status == OK && size > 0) {
     value = String(size+1);
     if ((status = rd_bytes(thread, size, (char*)value.data())) != OK) return status;
     ((char*)value.data())[size]=0;
   } else {
     value = String();
   }
   return status;   
 }
Status BinCommon::rd_list(CommandInitiator* thread, void* dst_value, uint offset) 
{
  const Field* b = m_fields;
  const Field* f = b+offset;
  uint size = 0;
  // currently the protocol doesn't provide list size
  f->set_field_to_default(dst_value);  
  //f->reserve(dst_value, size);
  char kind = (char)f->kind();
  void* elem;
  uchar token;
  while (rd_uchar(thread, token) == OK) {
    if (token == ']') return OK;
    if (token == kind || (kind == 'b' && (token == 'T' || token == 'F'))) {
      f->append(dst_value, size++, elem);
      if (rd_value(token, thread, elem, offset) != OK) return ERR_DECODE;
    } else break;
  }
  return ERR_DECODE;
}
Status BinCommon::rd_property(CommandInitiator* thread, uint& mid, uint& oid, uint& property, uchar& kind)
{
        uchar token;
//         printf("m_begin_property %d\n", m_begin_property);
        
        if (!m_begin_property) {
                if (rd_value(thread, m_mod_property) != Protocol::OK) goto lost_connection;  
                if (rd_value(thread, m_obj_property) != Protocol::OK) goto lost_connection;  
                if (rd_uchar(thread, kind) != Protocol::OK) goto lost_connection;
                if (rd_value(thread, property) != Protocol::OK) goto lost_connection; 
        } else {
                if (rd_uchar(thread, token) != Protocol::OK) goto lost_connection; 
                if (token == ']') {
                        if (rd_uchar(thread, token) != Protocol::OK) goto lost_connection;
                        if (token == ',') { //continue
                                if (rd_value(thread, m_obj_property) != Protocol::OK) goto lost_connection;    
                                if (rd_uchar(thread, kind) != Protocol::OK) goto lost_connection;
                                if (rd_value(thread, property) != Protocol::OK) goto lost_connection;                     
                        } else if (token == ']') {
                                m_begin_property = 0;
                                if (rd_uchar(thread, token) != Protocol::OK) goto lost_connection;
                                if (token == ']') {
                                        rd_uchar(thread, token); //z
                                
                                        if (m_buffering < 0) m_buffering = 0;
                                        m_transport->end_decoding(thread);
                                
                                        return Protocol::COMPLETED;
                                } else if (token == ',') {
                                        return rd_property(thread, mid, oid, property, kind);
                                }        
                        }
                        goto lost_connection;                       
                } else {
                        kind = token;
                        if (rd_value(thread, property) != Protocol::OK) goto lost_connection;
                }
        }
        
        m_begin_property++;
        mid = m_mod_property;
        oid = m_obj_property;
        
        return Protocol::OK;
        
lost_connection:
        m_begin_property = 0;
        return Protocol::ERR_DECODE;      
}
Status BinCommon::rd_uint(CommandInitiator* thread, void* val, uint)
{
  return rd_value(thread, *static_cast<uint*>(val));
}
Status BinCommon::rd_binary(CommandInitiator* thread, void* value, uint)
{
  return rd_value(thread, *static_cast<Binary*>(value));
}
Status BinCommon::rd_string(CommandInitiator* thread, void* value, uint)  
{ 
  return rd_value(thread, *static_cast<String*>(value));
}
Status BinCommon::rd_filename(CommandInitiator* thread, void* value, uint) 
{
  return rd_value(thread, *static_cast<Filename*>(value));
}
Status BinCommon::rd_message(CommandInitiator* thread, void* message_received, uint offset)
{
  uchar token = 0;
  uint  tag = 0;
  uint  prev_tag = 0;
  bool  peek = true;
  uint  unkown_tags_limit = 30; 
  if (m_depth++ > DEPTH_LIMIT) return ERR_DECODE;
  const Field* b = m_fields;
  const Field* f = &b[offset];
  const Field* e = &b[f->get_end()];     // message descriptor ended
  while (f != e) {
    if (peek) { 
      if (rd_uchar(thread, token) != OK) return ERR_DECODE;
      if (token != 'z') {
        if (token == 'N') { 
          if (rd_uchar(thread, token) != OK && token != 'z') return ERR_DECODE;
          return ERR_CALL;
        }
        if (rd_value(thread, tag) != OK || tag < prev_tag) return ERR_DECODE;
        prev_tag = tag;
      }
    }
    if (token == 'z') {
      // we shall reset all remaining fields
      f->set_to_default(message_received);
      peek = false; // no more to read...
    } else if (tag == f->get_tag()) {  
      // check that type in message matches the field type flag
      // (except for boolean, as no type flag is given but value is immediately given)
      if (!(token == f->kind() 
            || (f->kind() == 'b' && (token == 'F' || token == 'T')) 
            || (f->is_list() && token == '[')
            )
          )
        return ERR_DECODE;
      if (rd_value(token, thread, f->offset(message_received), f-m_fields) != OK) return ERR_DECODE;
      peek = true;
    } else {
      // tag is unknown: skip the value
      peek = tag < f->get_tag();
      if (peek) {
        if (unkown_tags_limit-- == 0 || sk_value(token, thread) != OK) return ERR_DECODE;
        continue; // keep current field
      }
      f->set_to_default(message_received);
    }
    // goto next field...
    f = f->next(); 
  }
  while (token != 'z') {
    if (rd_uchar(thread, token) != OK) return ERR_DECODE;
    if (token != 'z') {
      if (token == 'N') { 
        if (rd_uchar(thread, token) != OK && token != 'z') return ERR_DECODE;
        return ERR_CALL;
      }
      if (rd_value(thread, tag) != OK || tag < prev_tag) return ERR_DECODE;
      prev_tag = tag;
      if (unkown_tags_limit-- == 0 || sk_value(token, thread) != OK) return ERR_DECODE;
    }
  }
  m_depth--;
  return OK;
}