void encode_recur(DBusMessageIter *iter, int *err, const alarm_recur_t *rec) { encode_uint64 (iter, err, &rec->mask_min); encode_uint32 (iter, err, &rec->mask_hour); encode_uint32 (iter, err, &rec->mask_mday); encode_uint32 (iter, err, &rec->mask_wday); encode_uint32 (iter, err, &rec->mask_mon); encode_uint32 (iter, err, &rec->special); }
void EditorExportPlatformOSX::_make_icon(const Image& p_icon,Vector<uint8_t>& icon) { Ref<ImageTexture> it = memnew( ImageTexture ); int size=512; Vector<uint8_t> data; data.resize(8); data[0]='i'; data[1]='c'; data[2]='n'; data[3]='s'; const char *name[]={"ic09","ic08","ic07","icp6","icp5","icp4"}; int index=0; while(size>=16) { Image copy = p_icon; copy.convert(Image::FORMAT_RGBA); copy.resize(size,size); it->create_from_image(copy); String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/icon.png"; ResourceSaver::save(path,it); FileAccess *f = FileAccess::open(path,FileAccess::READ); ERR_FAIL_COND(!f); int ofs = data.size(); uint32_t len = f->get_len(); data.resize(data.size()+len+8); f->get_buffer(&data[ofs+8],len); memdelete(f); len+=8; len=BSWAP32(len); copymem(&data[ofs],name[index],4); encode_uint32(len,&data[ofs+4]); index++; size/=2; } uint32_t total_len = data.size(); total_len = BSWAP32(total_len); encode_uint32(total_len,&data[4]); icon=data; }
static int encode_string(lua_State *L) { size_t len; char *mem; const char *str; unsigned size; if (lua_isnil(L, -1)) { lua_pushinteger(L, 0); encode_uint32(L); lua_remove(L, -2); return 1; } str = lua_tostring(L, -1); len = strlen(str) + 1; size = len + sizeof(unsigned); mem = (char*)malloc(size); if (!mem) { lua_pushstring(L, "Out of memory!"); lua_error(L); } memcpy(mem, &len, sizeof(unsigned)); memcpy(mem + sizeof(unsigned), str, len); lua_pushlstring(L, mem, size); free(mem); return 1; }
static void encode_layoutstats(struct xdr_stream *xdr, struct nfs42_layoutstat_args *args, struct nfs42_layoutstat_devinfo *devinfo, struct compound_hdr *hdr) { __be32 *p; encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr); p = reserve_space(xdr, 8 + 8); p = xdr_encode_hyper(p, devinfo->offset); p = xdr_encode_hyper(p, devinfo->length); encode_nfs4_stateid(xdr, &args->stateid); p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4); p = xdr_encode_hyper(p, devinfo->read_count); p = xdr_encode_hyper(p, devinfo->read_bytes); p = xdr_encode_hyper(p, devinfo->write_count); p = xdr_encode_hyper(p, devinfo->write_bytes); p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data, NFS4_DEVICEID4_SIZE); /* Encode layoutupdate4 */ *p++ = cpu_to_be32(devinfo->layout_type); if (devinfo->layoutstats_encode != NULL) devinfo->layoutstats_encode(xdr, args, devinfo); else encode_uint32(xdr, 0); }
DVector<int> TileMap::_get_tile_data() const { DVector<int> data; data.resize(tile_map.size()*2); DVector<int>::Write w = data.write(); int idx=0; for(const Map<PosKey,Cell>::Element *E=tile_map.front();E;E=E->next()) { uint8_t *ptr = (uint8_t*)&w[idx]; encode_uint16(E->key().x,&ptr[0]); encode_uint16(E->key().y,&ptr[2]); uint32_t val = E->get().id; if (E->get().flip_h) val|=(1<<29); if (E->get().flip_v) val|=(1<<30); encode_uint32(val,&ptr[4]); idx+=2; } w = DVector<int>::Write(); return data; }
static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, const u32 length) { BUG_ON(length > NFS3_MAXPATHLEN); encode_uint32(xdr, length); xdr_write_pages(xdr, pages, 0, length); }
void FileAccessNetworkClient::put_32(int p_32) { uint8_t buf[4]; encode_uint32(p_32,buf); client->put_data(buf,4); DEBUG_PRINT("put32: "+itos(p_32)); }
static void encode_copy(struct xdr_stream *xdr, struct nfs42_copy_args *args, struct compound_hdr *hdr) { encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr); encode_nfs4_stateid(xdr, &args->src_stateid); encode_nfs4_stateid(xdr, &args->dst_stateid); encode_uint64(xdr, args->src_pos); encode_uint64(xdr, args->dst_pos); encode_uint64(xdr, args->count); encode_uint32(xdr, 1); /* consecutive = true */ encode_uint32(xdr, 1); /* synchronous = true */ encode_uint32(xdr, 0); /* src server list */ }
static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, struct xdr_stream *xdr, const struct nfs3_setaclargs *args) { unsigned int base; int error; encode_nfs_fh3(xdr, NFS_FH(args->inode)); encode_uint32(xdr, args->mask); base = req->rq_slen; if (args->npages != 0) xdr_write_pages(xdr, args->pages, 0, args->len); else xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE); error = nfsacl_encode(xdr->buf, base, args->inode, (args->mask & NFS_ACL) ? args->acl_access : NULL, 1, 0); BUG_ON(error < 0); error = nfsacl_encode(xdr->buf, base + error, args->inode, (args->mask & NFS_DFACL) ? args->acl_default : NULL, 1, NFS_ACL_DEFAULT); BUG_ON(error < 0); }
void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) { Ref<ImageTexture> it = memnew(ImageTexture); int size = 512; Vector<uint8_t> data; data.resize(8); data[0] = 'i'; data[1] = 'c'; data[2] = 'n'; data[3] = 's'; const char *name[] = { "ic09", "ic08", "ic07", "icp6", "icp5", "icp4" }; int index = 0; while (size >= 16) { Ref<Image> copy = p_icon; // does this make sense? doesn't this just increase the reference count instead of making a copy? Do we even need a copy? copy->convert(Image::FORMAT_RGBA8); copy->resize(size, size); it->create_from_image(copy); String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("icon.png"); ResourceSaver::save(path, it); FileAccess *f = FileAccess::open(path, FileAccess::READ); ERR_FAIL_COND(!f); int ofs = data.size(); uint32_t len = f->get_len(); data.resize(data.size() + len + 8); f->get_buffer(&data[ofs + 8], len); memdelete(f); len += 8; len = BSWAP32(len); copymem(&data[ofs], name[index], 4); encode_uint32(len, &data[ofs + 4]); index++; size /= 2; } uint32_t total_len = data.size(); total_len = BSWAP32(total_len); encode_uint32(total_len, &data[4]); p_data = data; }
static void encode_seek(struct xdr_stream *xdr, struct nfs42_seek_args *args, struct compound_hdr *hdr) { encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr); encode_nfs4_stateid(xdr, &args->sa_stateid); encode_uint64(xdr, args->sa_offset); encode_uint32(xdr, args->sa_what); }
void StreamPeer::put_32(int32_t p_val) { if (big_endian) { p_val = BSWAP32(p_val); } uint8_t buf[4]; encode_uint32(p_val, buf); put_data(buf, 4); }
bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { String name = p_name; if (name == "theme") { r_ret = get_theme(); } else if (name == "cell_size") { r_ret = get_cell_size(); } else if (name == "cell_octant_size") { r_ret = get_octant_size(); } else if (name == "cell_center_x") { r_ret = get_center_x(); } else if (name == "cell_center_y") { r_ret = get_center_y(); } else if (name == "cell_center_z") { r_ret = get_center_z(); } else if (name == "cell_scale") { r_ret = cell_scale; } else if (name == "data") { Dictionary d; PoolVector<int> cells; cells.resize(cell_map.size() * 3); { PoolVector<int>::Write w = cells.write(); int i = 0; for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next(), i++) { encode_uint64(E->key().key, (uint8_t *)&w[i * 3]); encode_uint32(E->get().cell, (uint8_t *)&w[i * 3 + 2]); } } d["cells"] = cells; r_ret = d; } else if (name.begins_with("areas/")) { int which = name.get_slicec('/', 1).to_int(); String what = name.get_slicec('/', 2); if (what == "bounds") r_ret = area_get_bounds(which); else if (what == "name") r_ret = area_get_name(which); else if (what == "disable_distance") r_ret = area_get_portal_disable_distance(which); else if (what == "exterior_portal") r_ret = area_is_exterior_portal(which); else return false; } else return false; return true; }
static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, struct xdr_stream *xdr, const struct nfs3_getaclargs *args) { encode_nfs_fh3(xdr, args->fh); encode_uint32(xdr, args->mask); if (args->mask & (NFS_ACL | NFS_DFACL)) prepare_reply_buffer(req, args->pages, 0, NFSACL_MAXPAGES << PAGE_SHIFT, ACL3_getaclres_sz); }
int encode_int < uint32_t > ( uint32_t val, uint8_t * start, uint8_t * end ) { int ret = encode_uint32 ( val, start, end ); if ( ret > 0 ) { uint32_t val2; int ret2 = decode_uint32 ( start, start + ret, & val2 ); assert ( ret == ret2 && val == val2 ); } return ret; }
bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target) { bool has_all_peers = true; List<int> peers_to_add; // If one is missing, take note to add it. for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) { if (p_target < 0 && E->get() == -p_target) continue; // Continue, excluded. if (p_target > 0 && E->get() != p_target) continue; // Continue, not for this peer. Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get()); if (!F || !F->get()) { // Path was not cached, or was cached but is unconfirmed. if (!F) { // Not cached at all, take note. peers_to_add.push_back(E->get()); } has_all_peers = false; } } // Those that need to be added, send a message for this. for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) { // Encode function name. CharString pname = String(p_path).utf8(); int len = encode_cstring(pname.get_data(), NULL); Vector<uint8_t> packet; packet.resize(1 + 4 + len); packet.write[0] = NETWORK_COMMAND_SIMPLIFY_PATH; encode_uint32(psc->id, &packet.write[1]); encode_cstring(pname.get_data(), &packet.write[5]); network_peer->set_target_peer(E->get()); // To all of you. network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); network_peer->put_packet(packet.ptr(), packet.size()); psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed. } return has_all_peers; }
/** The twofish packet format consists of: * * - a 8-bit twofish encoding version in clear text * - a 32-bit SA number in clear text * - ciphertext encrypted from a 32-bit nonce followed by the payload. * * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] * |<------ encrypted ------>| */ static int transop_encode_twofish( ntvl_trans_op_t * arg, uint8_t * outbuf, size_t out_len, const uint8_t * inbuf, size_t in_len ) { int len=-1; transop_tf_t * priv = (transop_tf_t *)arg->priv; uint8_t assembly[NTVL_PKT_BUF_SIZE]; uint32_t * pnonce; if ( (in_len + TRANSOP_TF_NONCE_SIZE) <= NTVL_PKT_BUF_SIZE ) { if ( (in_len + TRANSOP_TF_NONCE_SIZE + TRANSOP_TF_SA_SIZE + TRANSOP_TF_VER_SIZE) <= out_len ) { size_t idx=0; sa_twofish_t * sa; size_t tx_sa_num = 0; /* The transmit sa is periodically updated */ tx_sa_num = tf_choose_tx_sa( priv ); sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */ traceEvent( TRACE_DEBUG, "encode_twofish %lu with SA %lu.", in_len, sa->sa_id ); /* Encode the twofish format version. */ encode_uint8( outbuf, &idx, NTVL_TWOFISH_TRANSFORM_VERSION ); /* Encode the security association (SA) number */ encode_uint32( outbuf, &idx, sa->sa_id ); /* The assembly buffer is a source for encrypting data. The nonce is * written in first followed by the packet payload. The whole * contents of assembly are encrypted. */ pnonce = (uint32_t *)assembly; *pnonce = rand(); memcpy( assembly + TRANSOP_TF_NONCE_SIZE, inbuf, in_len ); /* Encrypt the assembly contents and write the ciphertext after the SA. */ len = TwoFishEncryptRaw( assembly, /* source */ outbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE, in_len + TRANSOP_TF_NONCE_SIZE, /* enc size */ sa->enc_tf); if ( len > 0 ) len += TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE; /* size of data carried in UDP. */ else traceEvent( TRACE_ERROR, "encode_twofish encryption failed." ); } else traceEvent( TRACE_ERROR, "encode_twofish outbuf too small." ); } else traceEvent( TRACE_ERROR, "encode_twofish inbuf too big to encrypt." ); return len; }
static void encode_createhow3(struct xdr_stream *xdr, const struct nfs3_createargs *args) { encode_uint32(xdr, args->createmode); switch (args->createmode) { case NFS3_CREATE_UNCHECKED: case NFS3_CREATE_GUARDED: encode_sattr3(xdr, args->sattr); break; case NFS3_CREATE_EXCLUSIVE: encode_createverf3(xdr, args->verifier); break; default: BUG(); } }
static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) { CharString utf8 = p_string.utf8(); if (buf) { encode_uint32(utf8.length(), buf); buf += 4; copymem(buf, utf8.get_data(), utf8.length()); buf += utf8.length(); } r_len += 4 + utf8.length(); while (r_len % 4) { r_len++; //pad if (buf) { buf++; } } }
bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { String name = p_name; if (name == "theme") { r_ret = get_theme(); } else if (name == "cell_size") { r_ret = get_cell_size(); } else if (name == "cell_octant_size") { r_ret = get_octant_size(); } else if (name == "cell_center_x") { r_ret = get_center_x(); } else if (name == "cell_center_y") { r_ret = get_center_y(); } else if (name == "cell_center_z") { r_ret = get_center_z(); } else if (name == "cell_scale") { r_ret = cell_scale; } else if (name == "data") { Dictionary d; PoolVector<int> cells; cells.resize(cell_map.size() * 3); { PoolVector<int>::Write w = cells.write(); int i = 0; for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next(), i++) { encode_uint64(E->key().key, (uint8_t *)&w[i * 3]); encode_uint32(E->get().cell, (uint8_t *)&w[i * 3 + 2]); } } d["cells"] = cells; r_ret = d; } else return false; return true; }
Error PacketPeerStream::put_packet(const uint8_t *p_buffer,int p_buffer_size) { ERR_FAIL_COND_V(peer.is_null(),ERR_UNCONFIGURED); Error err = _poll_buffer(); //won't hurt to poll here too if (err) return err; if (p_buffer_size==0) return OK; ERR_FAIL_COND_V( p_buffer_size<0, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V( p_buffer_size+4 > temp_buffer.size(), ERR_INVALID_PARAMETER ); encode_uint32(p_buffer_size,&temp_buffer[0]); uint8_t *dst=&temp_buffer[4]; for(int i=0;i<p_buffer_size;i++) dst[i]=p_buffer[i]; return peer->put_data(&temp_buffer[0],p_buffer_size+4); }
/* * Initialize and return open socket. */ static int init(void) { int sockfd; uint32_t lport; uint32_t rport; char lhost[NI_MAXHOST]; char rhost[NI_MAXHOST]; if (is_client()) client_get_hosts(lhost, rhost); else server_get_hosts(lhost, rhost); sockfd = rds_socket(lhost, Req.port); lport = get_socket_port(sockfd); encode_uint32(&lport, lport); send_mesg(&lport, sizeof(lport), "RDS port"); recv_mesg(&rport, sizeof(rport), "RDS port"); rport = decode_uint32(&rport); rds_makeaddr(&RAddr, &RLen, rhost, rport); return sockfd; }
/* * Have an exchange with the client over TCP/IP and get the IP of our local * host. */ static void server_get_hosts(char *lhost, char *rhost) { int fd, lfd; uint32_t port; struct sockaddr_in laddr, raddr; socklen_t rlen; lfd = socket(AF_INET, SOCK_STREAM, 0); if (lfd < 0) error(SYS, "socket failed"); setsockopt_one(lfd, SO_REUSEADDR); memset(&laddr, 0, sizeof(laddr)); laddr.sin_family = AF_INET; laddr.sin_addr.s_addr = INADDR_ANY; laddr.sin_port = htons(0); if (bind(lfd, (SA *)&laddr, sizeof(laddr)) < 0) error(SYS, "bind INET failed"); port = get_socket_port(lfd); encode_uint32(&port, port); send_mesg(&port, sizeof(port), "TCP IPv4 server port"); if (listen(lfd, 1) < 0) error(SYS, "listen failed"); rlen = sizeof(raddr); fd = accept(lfd, (SA *)&raddr, &rlen); if (fd < 0) error(SYS, "accept failed"); close(lfd); get_socket_ip((SA *)&raddr, rlen, rhost, NI_MAXHOST); send_mesg(rhost, NI_MAXHOST, "client IP"); recv_mesg(lhost, NI_MAXHOST, "server IP"); close(fd); }
void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) { if (network_peer.is_null()) { ERR_EXPLAIN("Attempt to remote call/set when networking is not active in SceneTree."); ERR_FAIL(); } if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING) { ERR_EXPLAIN("Attempt to remote call/set when networking is not connected yet in SceneTree."); ERR_FAIL(); } if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) { ERR_EXPLAIN("Attempt to remote call/set when networking is disconnected."); ERR_FAIL(); } if (p_argcount > 255) { ERR_EXPLAIN("Too many arguments >255."); ERR_FAIL(); } if (p_to != 0 && !connected_peers.has(ABS(p_to))) { if (p_to == network_peer->get_unique_id()) { ERR_EXPLAIN("Attempt to remote call/set yourself! unique ID: " + itos(network_peer->get_unique_id())); } else { ERR_EXPLAIN("Attempt to remote call unexisting ID: " + itos(p_to)); } ERR_FAIL(); } NodePath from_path = (root_node->get_path()).rel_path_to(p_from->get_path()); ERR_EXPLAIN("Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!"); ERR_FAIL_COND(from_path.is_empty()); // See if the path is cached. PathSentCache *psc = path_send_cache.getptr(from_path); if (!psc) { // Path is not cached, create. path_send_cache[from_path] = PathSentCache(); psc = path_send_cache.getptr(from_path); psc->id = last_send_cache_id++; } // Create base packet, lots of hardcode because it must be tight. int ofs = 0; #define MAKE_ROOM(m_amount) \ if (packet_cache.size() < m_amount) packet_cache.resize(m_amount); // Encode type. MAKE_ROOM(1); packet_cache.write[0] = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL; ofs += 1; // Encode ID. MAKE_ROOM(ofs + 4); encode_uint32(psc->id, &(packet_cache.write[ofs])); ofs += 4; // Encode function name. CharString name = String(p_name).utf8(); int len = encode_cstring(name.get_data(), NULL); MAKE_ROOM(ofs + len); encode_cstring(name.get_data(), &(packet_cache.write[ofs])); ofs += len; if (p_set) { // Set argument. Error err = encode_variant(*p_arg[0], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed()); ERR_EXPLAIN("Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!"); ERR_FAIL_COND(err != OK); MAKE_ROOM(ofs + len); encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed()); ofs += len; } else { // Call arguments. MAKE_ROOM(ofs + 1); packet_cache.write[ofs] = p_argcount; ofs += 1; for (int i = 0; i < p_argcount; i++) { Error err = encode_variant(*p_arg[i], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed()); ERR_EXPLAIN("Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!"); ERR_FAIL_COND(err != OK); MAKE_ROOM(ofs + len); encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed()); ofs += len; } } // See if all peers have cached path (is so, call can be fast). bool has_all_peers = _send_confirm_path(from_path, psc, p_to); // Take chance and set transfer mode, since all send methods will use it. network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); if (has_all_peers) { // They all have verified paths, so send fast. network_peer->set_target_peer(p_to); // To all of you. network_peer->put_packet(packet_cache.ptr(), ofs); // A message with love. } else { // Not all verified path, so send one by one. // Append path at the end, since we will need it for some packets. CharString pname = String(from_path).utf8(); int path_len = encode_cstring(pname.get_data(), NULL); MAKE_ROOM(ofs + path_len); encode_cstring(pname.get_data(), &(packet_cache.write[ofs])); for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) { if (p_to < 0 && E->get() == -p_to) continue; // Continue, excluded. if (p_to > 0 && E->get() != p_to) continue; // Continue, not for this peer. Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get()); ERR_CONTINUE(!F); // Should never happen. network_peer->set_target_peer(E->get()); // To this one specifically. if (F->get()) { // This one confirmed path, so use id. encode_uint32(psc->id, &(packet_cache.write[1])); network_peer->put_packet(packet_cache.ptr(), ofs); } else { // This one did not confirm path yet, so use entire path (sorry!). encode_uint32(0x80000000 | ofs, &(packet_cache.write[1])); // Offset to path and flag. network_peer->put_packet(packet_cache.ptr(), ofs + path_len); } } } }
Vector<uint8_t> GDTokenizerBuffer::parse_code_string(const String& p_code) { Vector<uint8_t> buf; Map<StringName,int> identifier_map; HashMap<Variant,int,VariantHasher> constant_map; Map<uint32_t,int> line_map; Vector<uint32_t> token_array; GDTokenizerText tt; tt.set_code(p_code); int line=-1; int col=0; while(true) { if (tt.get_token_line()!=line) { line=tt.get_token_line(); line_map[line]=token_array.size(); } uint32_t token=tt.get_token(); switch(tt.get_token()) { case TK_IDENTIFIER: { StringName id = tt.get_token_identifier(); if (!identifier_map.has(id)) { int idx = identifier_map.size(); identifier_map[id]=idx; } token|=identifier_map[id]<<TOKEN_BITS; } break; case TK_CONSTANT: { Variant c = tt.get_token_constant(); if (!constant_map.has(c)) { int idx = constant_map.size(); constant_map[c]=idx; } token|=constant_map[c]<<TOKEN_BITS; } break; case TK_BUILT_IN_TYPE: { token|=tt.get_token_type()<<TOKEN_BITS; } break; case TK_BUILT_IN_FUNC: { token|=tt.get_token_built_in_func()<<TOKEN_BITS; } break; case TK_NEWLINE: { token|=tt.get_token_line_indent()<<TOKEN_BITS; } break; case TK_ERROR: { ERR_FAIL_V(Vector<uint8_t>()); } break; default: {} }; token_array.push_back(token); if (tt.get_token()==TK_EOF) break; tt.advance(); } //reverse maps Map<int,StringName> rev_identifier_map; for(Map<StringName,int>::Element *E=identifier_map.front();E;E=E->next()) { rev_identifier_map[E->get()]=E->key(); } Map<int,Variant> rev_constant_map; const Variant *K =NULL; while((K=constant_map.next(K))) { rev_constant_map[constant_map[*K]]=*K; } Map<int,uint32_t> rev_line_map; for(Map<uint32_t,int>::Element *E=line_map.front();E;E=E->next()) { rev_line_map[E->get()]=E->key(); } //save header buf.resize(24); buf[0]='G'; buf[1]='D'; buf[2]='S'; buf[3]='C'; encode_uint32(BYTECODE_VERSION,&buf[4]); encode_uint32(identifier_map.size(),&buf[8]); encode_uint32(constant_map.size(),&buf[12]); encode_uint32(line_map.size(),&buf[16]); encode_uint32(token_array.size(),&buf[20]); //save identifiers for(Map<int,StringName>::Element *E=rev_identifier_map.front();E;E=E->next()) { CharString cs = String(E->get()).utf8(); int len = cs.length()+1; int extra = 4-(len%4); if (extra==4) extra=0; uint8_t ibuf[4]; encode_uint32(len+extra,ibuf); for(int i=0;i<4;i++) { buf.push_back(ibuf[i]); } for(int i=0;i<len;i++) { buf.push_back(cs[i]^0xb6); } for(int i=0;i<extra;i++) { buf.push_back(0^0xb6); } } for(Map<int,Variant>::Element *E=rev_constant_map.front();E;E=E->next()) { int len; Error err = encode_variant(E->get(),NULL,len); ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>()); int pos=buf.size(); buf.resize(pos+len); encode_variant(E->get(),&buf[pos],len); } for(Map<int,uint32_t>::Element *E=rev_line_map.front();E;E=E->next()) { uint8_t ibuf[8]; encode_uint32(E->key(),&ibuf[0]); encode_uint32(E->get(),&ibuf[4]); for(int i=0;i<8;i++) buf.push_back(ibuf[i]); } for(int i=0;i<token_array.size();i++) { uint32_t token = token_array[i]; if (token&~TOKEN_MASK) { uint8_t buf4[4]; encode_uint32(token_array[i]|TOKEN_BYTE_MASK,&buf4[0]); for(int j=0;j<4;j++) { buf.push_back(buf4[j]); } } else { buf.push_back(token); } } return buf; }
void NetworkedMultiplayerENet::poll(){ ERR_FAIL_COND(!active); _pop_current_packet(); ENetEvent event; /* Wait up to 1000 milliseconds for an event. */ while (true) { if (!host || !active) //might have been disconnected while emitting a notification return; int ret = enet_host_service (host, & event, 1); if (ret<0) { //error, do something? break; } else if (ret==0) { break; } switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { /* Store any relevant client information here. */ if (server && refuse_connections) { enet_peer_reset(event.peer); break; } IP_Address ip; ip.host=event.peer -> address.host; int *new_id = memnew( int ); *new_id = event.data; if (*new_id==0) { //data zero is sent by server (enet won't let you configure this). Server is always 1 *new_id=1; } event.peer->data=new_id; peer_map[*new_id]=event.peer; connection_status=CONNECTION_CONNECTED; //if connecting, this means it connected t something! emit_signal("peer_connected",*new_id); if (server) { //someone connected, let it know of all the peers available for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (E->key()==*new_id) continue; //send existing peers to new peer ENetPacket * packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_ADD_PEER,&packet->data[0]); encode_uint32(E->key(),&packet->data[4]); enet_peer_send(event.peer,1,packet); //send the new peer to existing peers packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_ADD_PEER,&packet->data[0]); encode_uint32(*new_id,&packet->data[4]); enet_peer_send(E->get(),1,packet); } } else { emit_signal("connection_succeeded"); } } break; case ENET_EVENT_TYPE_DISCONNECT: { /* Reset the peer's client information. */ int *id = (int*)event.peer -> data; if (!id) { if (!server) { emit_signal("connection_failed"); } } else { if (server) { //someone disconnected, let it know to everyone else for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (E->key()==*id) continue; //send the new peer to existing peers ENetPacket* packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_REMOVE_PEER,&packet->data[0]); encode_uint32(*id,&packet->data[4]); enet_peer_send(E->get(),1,packet); } } else if (!server) { emit_signal("server_disconnected"); close_connection(); return; } emit_signal("peer_disconnected",*id); peer_map.erase(*id); memdelete( id ); } } break; case ENET_EVENT_TYPE_RECEIVE: { if (event.channelID==1) { //some config message ERR_CONTINUE( event.packet->dataLength < 8); int msg = decode_uint32(&event.packet->data[0]); int id = decode_uint32(&event.packet->data[4]); switch(msg) { case SYSMSG_ADD_PEER: { peer_map[id]=NULL; emit_signal("peer_connected",id); } break; case SYSMSG_REMOVE_PEER: { peer_map.erase(id); emit_signal("peer_disconnected",id); } break; } enet_packet_destroy(event.packet); } else if (event.channelID==0){ Packet packet; packet.packet = event.packet; int *id = (int*)event.peer -> data; ERR_CONTINUE(event.packet->dataLength<12) uint32_t source = decode_uint32(&event.packet->data[0]); int target = decode_uint32(&event.packet->data[4]); uint32_t flags = decode_uint32(&event.packet->data[8]); packet.from=source; if (server) { packet.from=*id; if (target==0) { //re-send the everyone but sender :| incoming_packets.push_back(packet); //and make copies for sending for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (uint32_t(E->key())==source) //do not resend to self continue; ENetPacket* packet2 = enet_packet_create (packet.packet->data,packet.packet->dataLength,flags); enet_peer_send(E->get(),0,packet2); } } else if (target<0) { //to all but one //and make copies for sending for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (uint32_t(E->key())==source || E->key()==-target) //do not resend to self, also do not send to excluded continue; ENetPacket* packet2 = enet_packet_create (packet.packet->data,packet.packet->dataLength,flags); enet_peer_send(E->get(),0,packet2); } if (-target != 1) { //server is not excluded incoming_packets.push_back(packet); } else { //server is excluded, erase packet enet_packet_destroy(packet.packet); } } else if (target==1) { //to myself and only myself incoming_packets.push_back(packet); } else { //to someone else, specifically ERR_CONTINUE(!peer_map.has(target)); enet_peer_send(peer_map[target],0,packet.packet); } } else { incoming_packets.push_back(packet); } //destroy packet later.. } else { ERR_CONTINUE(true); } }break; case ENET_EVENT_TYPE_NONE: { //do nothing } break; } } }
void EditorFileServer::_subthread_start(void *s) { ClientData *cd = (ClientData *)s; cd->connection->set_nodelay(true); uint8_t buf4[8]; Error err = cd->connection->get_data(buf4, 4); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } int passlen = decode_uint32(buf4); if (passlen > 512) { _close_client(cd); ERR_FAIL_COND(passlen > 512); } else if (passlen > 0) { Vector<char> passutf8; passutf8.resize(passlen + 1); err = cd->connection->get_data((uint8_t *)passutf8.ptr(), passlen); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } passutf8[passlen] = 0; String s; s.parse_utf8(passutf8.ptr()); if (s != cd->efs->password) { encode_uint32(ERR_INVALID_DATA, buf4); cd->connection->put_data(buf4, 4); OS::get_singleton()->delay_usec(1000000); _close_client(cd); ERR_PRINT("CLIENT PASSWORD MISMATCH"); ERR_FAIL(); } } else { if (cd->efs->password != "") { encode_uint32(ERR_INVALID_DATA, buf4); cd->connection->put_data(buf4, 4); OS::get_singleton()->delay_usec(1000000); _close_client(cd); ERR_PRINT("CLIENT PASSWORD MISMATCH (should be empty!)"); ERR_FAIL(); } } encode_uint32(OK, buf4); cd->connection->put_data(buf4, 4); while (!cd->quit) { //wait for ID err = cd->connection->get_data(buf4, 4); //#define DEBUG_PRINT(m_p) print_line(m_p) DEBUG_TIME("get_data") if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } int id = decode_uint32(buf4); //wait for command err = cd->connection->get_data(buf4, 4); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } int cmd = decode_uint32(buf4); switch (cmd) { case FileAccessNetwork::COMMAND_FILE_EXISTS: case FileAccessNetwork::COMMAND_GET_MODTIME: case FileAccessNetwork::COMMAND_OPEN_FILE: { DEBUG_TIME("open_file") err = cd->connection->get_data(buf4, 4); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } int namelen = decode_uint32(buf4); Vector<char> fileutf8; fileutf8.resize(namelen + 1); err = cd->connection->get_data((uint8_t *)fileutf8.ptr(), namelen); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } fileutf8[namelen] = 0; String s; s.parse_utf8(fileutf8.ptr()); if (cmd == FileAccessNetwork::COMMAND_FILE_EXISTS) { print_line("FILE EXISTS: " + s); } if (cmd == FileAccessNetwork::COMMAND_GET_MODTIME) { print_line("MOD TIME: " + s); } if (cmd == FileAccessNetwork::COMMAND_OPEN_FILE) { print_line("OPEN: " + s); } if (!s.begins_with("res://")) { _close_client(cd); ERR_FAIL_COND(!s.begins_with("res://")); } ERR_CONTINUE(cd->files.has(id)); if (cmd == FileAccessNetwork::COMMAND_FILE_EXISTS) { encode_uint32(id, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_FILE_EXISTS, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccess::exists(s), buf4); cd->connection->put_data(buf4, 4); DEBUG_TIME("open_file_end") break; } if (cmd == FileAccessNetwork::COMMAND_GET_MODTIME) { encode_uint32(id, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_GET_MODTIME, buf4); cd->connection->put_data(buf4, 4); encode_uint64(FileAccess::get_modified_time(s), buf4); cd->connection->put_data(buf4, 8); DEBUG_TIME("open_file_end") break; } FileAccess *fa = FileAccess::open(s, FileAccess::READ); if (!fa) { //not found, continue encode_uint32(id, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_OPEN, buf4); cd->connection->put_data(buf4, 4); encode_uint32(ERR_FILE_NOT_FOUND, buf4); cd->connection->put_data(buf4, 4); DEBUG_TIME("open_file_end") break; } encode_uint32(id, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_OPEN, buf4); cd->connection->put_data(buf4, 4); encode_uint32(OK, buf4); cd->connection->put_data(buf4, 4); encode_uint64(fa->get_len(), buf4); cd->connection->put_data(buf4, 8); cd->files[id] = fa; DEBUG_TIME("open_file_end") } break;
void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest) { const int CHUNK_AXML_FILE = 0x00080003; const int CHUNK_RESOURCEIDS = 0x00080180; const int CHUNK_STRINGS = 0x001C0001; const int CHUNK_XML_END_NAMESPACE = 0x00100101; const int CHUNK_XML_END_TAG = 0x00100103; const int CHUNK_XML_START_NAMESPACE = 0x00100100; const int CHUNK_XML_START_TAG = 0x00100102; const int CHUNK_XML_TEXT = 0x00100104; const int UTF8_FLAG = 0x00000100; Vector<String> string_table; uint32_t ofs=0; uint32_t header = decode_uint32(&p_manifest[ofs]); uint32_t filesize = decode_uint32(&p_manifest[ofs+4]); ofs+=8; // print_line("FILESIZE: "+itos(filesize)+" ACTUAL: "+itos(p_manifest.size())); uint32_t string_count; uint32_t styles_count; uint32_t string_flags; uint32_t string_data_offset; uint32_t styles_offset; uint32_t string_table_begins; uint32_t string_table_ends; Vector<uint8_t> stable_extra; while(ofs < p_manifest.size()) { uint32_t chunk = decode_uint32(&p_manifest[ofs]); uint32_t size = decode_uint32(&p_manifest[ofs+4]); switch(chunk) { case CHUNK_STRINGS: { int iofs=ofs+8; uint32_t string_count=decode_uint32(&p_manifest[iofs]); uint32_t styles_count=decode_uint32(&p_manifest[iofs+4]); uint32_t string_flags=decode_uint32(&p_manifest[iofs+8]); uint32_t string_data_offset=decode_uint32(&p_manifest[iofs+12]); uint32_t styles_offset=decode_uint32(&p_manifest[iofs+16]); /* printf("string count: %i\n",string_count); printf("flags: %i\n",string_flags); printf("sdata ofs: %i\n",string_data_offset); printf("styles ofs: %i\n",styles_offset); */ uint32_t st_offset=iofs+20; string_table.resize(string_count); uint32_t string_end=0; string_table_begins=st_offset; for(int i=0;i<string_count;i++) { uint32_t string_at = decode_uint32(&p_manifest[st_offset+i*4]); string_at+=st_offset+string_count*4; ERR_EXPLAIN("Unimplemented, can't read utf8 string table."); ERR_FAIL_COND(string_flags&UTF8_FLAG); if (string_flags&UTF8_FLAG) { } else { uint32_t len = decode_uint16(&p_manifest[string_at]); Vector<CharType> ucstring; ucstring.resize(len+1); for(int j=0;j<len;j++) { uint16_t c=decode_uint16(&p_manifest[string_at+2+2*j]); ucstring[j]=c; } string_end=MAX(string_at+2+2*len,string_end); ucstring[len]=0; string_table[i]=ucstring.ptr(); } // print_line("String "+itos(i)+": "+string_table[i]); } for(int i=string_end;i<(ofs+size);i++) { stable_extra.push_back(p_manifest[i]); } // printf("stable extra: %i\n",int(stable_extra.size())); string_table_ends=ofs+size; // print_line("STABLE SIZE: "+itos(size)+" ACTUAL: "+itos(string_table_ends)); } break; case CHUNK_XML_START_TAG: { int iofs=ofs+8; uint32_t line=decode_uint32(&p_manifest[iofs]); uint32_t nspace=decode_uint32(&p_manifest[iofs+8]); uint32_t name=decode_uint32(&p_manifest[iofs+12]); uint32_t check=decode_uint32(&p_manifest[iofs+16]); String tname=string_table[name]; // printf("NSPACE: %i\n",nspace); //printf("NAME: %i (%s)\n",name,tname.utf8().get_data()); //printf("CHECK: %x\n",check); uint32_t attrcount=decode_uint32(&p_manifest[iofs+20]); iofs+=28; //printf("ATTRCOUNT: %x\n",attrcount); for(int i=0;i<attrcount;i++) { uint32_t attr_nspace=decode_uint32(&p_manifest[iofs]); uint32_t attr_name=decode_uint32(&p_manifest[iofs+4]); uint32_t attr_value=decode_uint32(&p_manifest[iofs+8]); uint32_t attr_flags=decode_uint32(&p_manifest[iofs+12]); uint32_t attr_resid=decode_uint32(&p_manifest[iofs+16]); String value; if (attr_value!=0xFFFFFFFF) value=string_table[attr_value]; else value="Res #"+itos(attr_resid); String attrname = string_table[attr_name]; String nspace; if (attr_nspace!=0xFFFFFFFF) nspace=string_table[attr_nspace]; else nspace=""; printf("ATTR %i NSPACE: %i\n",i,attr_nspace); printf("ATTR %i NAME: %i (%s)\n",i,attr_name,attrname.utf8().get_data()); printf("ATTR %i VALUE: %i (%s)\n",i,attr_value,value.utf8().get_data()); printf("ATTR %i FLAGS: %x\n",i,attr_flags); printf("ATTR %i RESID: %x\n",i,attr_resid); //replace project information if (tname=="manifest" && attrname=="package") { print_line("FOUND PACKAGE"); string_table[attr_value]=package; } //print_line("tname: "+tname); //print_line("nspace: "+nspace); //print_line("attrname: "+attrname); if (tname=="manifest" && /*nspace=="android" &&*/ attrname=="versionCode") { print_line("FOUND versioncode"); encode_uint32(version_code,&p_manifest[iofs+16]); } if (tname=="manifest" && /*nspace=="android" &&*/ attrname=="versionName") { print_line("FOUND versionname"); if (attr_value==0xFFFFFFFF) { WARN_PRINT("Version name in a resource, should be plaintext") } else string_table[attr_value]=version_name; } if (tname=="activity" && /*nspace=="android" &&*/ attrname=="screenOrientation") { print_line("FOUND screen orientation"); if (attr_value==0xFFFFFFFF) { WARN_PRINT("Version name in a resource, should be plaintext") } else { string_table[attr_value]=(orientation==0?"landscape":"portrait"); } } if (tname=="application" && /*nspace=="android" &&*/ attrname=="label") { print_line("FOUND application"); if (attr_value==0xFFFFFFFF) { WARN_PRINT("Application name in a resource, should be plaintext.") } else { String aname = get_project_name(); string_table[attr_value]=aname; } } if (tname=="activity" && /*nspace=="android" &&*/ attrname=="label") { print_line("FOUND activity name"); if (attr_value==0xFFFFFFFF) { WARN_PRINT("Activity name in a resource, should be plaintext") } else { String aname; if (this->name!="") { aname=this->name; } else { aname = Globals::get_singleton()->get("application/name"); } if (aname=="") { aname=_MKSTR(VERSION_NAME); } print_line("APP NAME IS..."+aname); string_table[attr_value]=aname; } } iofs+=20; }
void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool p_give_internet) { const int CHUNK_AXML_FILE = 0x00080003; const int CHUNK_RESOURCEIDS = 0x00080180; const int CHUNK_STRINGS = 0x001C0001; const int CHUNK_XML_END_NAMESPACE = 0x00100101; const int CHUNK_XML_END_TAG = 0x00100103; const int CHUNK_XML_START_NAMESPACE = 0x00100100; const int CHUNK_XML_START_TAG = 0x00100102; const int CHUNK_XML_TEXT = 0x00100104; const int UTF8_FLAG = 0x00000100; Vector<String> string_table; uint32_t ofs=0; uint32_t header = decode_uint32(&p_manifest[ofs]); uint32_t filesize = decode_uint32(&p_manifest[ofs+4]); ofs+=8; // print_line("FILESIZE: "+itos(filesize)+" ACTUAL: "+itos(p_manifest.size())); uint32_t string_count; uint32_t styles_count; uint32_t string_flags; uint32_t string_data_offset; uint32_t styles_offset; uint32_t string_table_begins; uint32_t string_table_ends; Vector<uint8_t> stable_extra; while(ofs < p_manifest.size()) { uint32_t chunk = decode_uint32(&p_manifest[ofs]); uint32_t size = decode_uint32(&p_manifest[ofs+4]); switch(chunk) { case CHUNK_STRINGS: { int iofs=ofs+8; string_count=decode_uint32(&p_manifest[iofs]); styles_count=decode_uint32(&p_manifest[iofs+4]); uint32_t string_flags=decode_uint32(&p_manifest[iofs+8]); string_data_offset=decode_uint32(&p_manifest[iofs+12]); styles_offset=decode_uint32(&p_manifest[iofs+16]); /* printf("string count: %i\n",string_count); printf("flags: %i\n",string_flags); printf("sdata ofs: %i\n",string_data_offset); printf("styles ofs: %i\n",styles_offset); */ uint32_t st_offset=iofs+20; string_table.resize(string_count); uint32_t string_end=0; string_table_begins=st_offset; for(int i=0;i<string_count;i++) { uint32_t string_at = decode_uint32(&p_manifest[st_offset+i*4]); string_at+=st_offset+string_count*4; ERR_EXPLAIN("Unimplemented, can't read utf8 string table."); ERR_FAIL_COND(string_flags&UTF8_FLAG); if (string_flags&UTF8_FLAG) { } else { uint32_t len = decode_uint16(&p_manifest[string_at]); Vector<CharType> ucstring; ucstring.resize(len+1); for(int j=0;j<len;j++) { uint16_t c=decode_uint16(&p_manifest[string_at+2+2*j]); ucstring[j]=c; } string_end=MAX(string_at+2+2*len,string_end); ucstring[len]=0; string_table[i]=ucstring.ptr(); } // print_line("String "+itos(i)+": "+string_table[i]); } for(int i=string_end;i<(ofs+size);i++) { stable_extra.push_back(p_manifest[i]); } // printf("stable extra: %i\n",int(stable_extra.size())); string_table_ends=ofs+size; // print_line("STABLE SIZE: "+itos(size)+" ACTUAL: "+itos(string_table_ends)); } break; case CHUNK_XML_START_TAG: { int iofs=ofs+8; uint32_t line=decode_uint32(&p_manifest[iofs]); uint32_t nspace=decode_uint32(&p_manifest[iofs+8]); uint32_t name=decode_uint32(&p_manifest[iofs+12]); uint32_t check=decode_uint32(&p_manifest[iofs+16]); String tname=string_table[name]; // printf("NSPACE: %i\n",nspace); //printf("NAME: %i (%s)\n",name,tname.utf8().get_data()); //printf("CHECK: %x\n",check); uint32_t attrcount=decode_uint32(&p_manifest[iofs+20]); iofs+=28; //printf("ATTRCOUNT: %x\n",attrcount); for(int i=0;i<attrcount;i++) { uint32_t attr_nspace=decode_uint32(&p_manifest[iofs]); uint32_t attr_name=decode_uint32(&p_manifest[iofs+4]); uint32_t attr_value=decode_uint32(&p_manifest[iofs+8]); uint32_t attr_flags=decode_uint32(&p_manifest[iofs+12]); uint32_t attr_resid=decode_uint32(&p_manifest[iofs+16]); String value; if (attr_value!=0xFFFFFFFF) value=string_table[attr_value]; else value="Res #"+itos(attr_resid); String attrname = string_table[attr_name]; String nspace; if (attr_nspace!=0xFFFFFFFF) nspace=string_table[attr_nspace]; else nspace=""; printf("ATTR %i NSPACE: %i\n",i,attr_nspace); printf("ATTR %i NAME: %i (%s)\n",i,attr_name,attrname.utf8().get_data()); printf("ATTR %i VALUE: %i (%s)\n",i,attr_value,value.utf8().get_data()); printf("ATTR %i FLAGS: %x\n",i,attr_flags); printf("ATTR %i RESID: %x\n",i,attr_resid); //replace project information if (tname=="manifest" && attrname=="package") { print_line("FOUND PACKAGE"); string_table[attr_value]=get_package_name(); } //print_line("tname: "+tname); //print_line("nspace: "+nspace); //print_line("attrname: "+attrname); if (tname=="manifest" && /*nspace=="android" &&*/ attrname=="versionCode") { print_line("FOUND versioncode"); encode_uint32(version_code,&p_manifest[iofs+16]); } if (tname=="manifest" && /*nspace=="android" &&*/ attrname=="versionName") { print_line("FOUND versionname"); if (attr_value==0xFFFFFFFF) { WARN_PRINT("Version name in a resource, should be plaintext") } else string_table[attr_value]=version_name; } if (tname=="activity" && /*nspace=="android" &&*/ attrname=="screenOrientation") { encode_uint32(orientation==0?0:1,&p_manifest[iofs+16]); /* print_line("FOUND screen orientation"); if (attr_value==0xFFFFFFFF) { WARN_PRINT("Version name in a resource, should be plaintext") } else { string_table[attr_value]=(orientation==0?"landscape":"portrait"); }*/ } if (tname=="uses-permission" && /*nspace=="android" &&*/ attrname=="name") { if (value.begins_with("godot.custom")) { int which = value.get_slice(".",2).to_int(); if (which>=0 && which<MAX_USER_PERMISSIONS && user_perms[which].strip_edges()!="") { string_table[attr_value]=user_perms[which].strip_edges(); } } else if (value.begins_with("godot.")) { String perm = value.get_slice(".",1); print_line("PERM: "+perm+" HAS: "+itos(perms.has(perm))); if (perms.has(perm) || (p_give_internet && perm=="INTERNET")) { string_table[attr_value]="android.permission."+perm; } } } if (tname=="supports-screens" ) { if (attrname=="smallScreens") { encode_uint32(screen_support[SCREEN_SMALL]?0xFFFFFFFF:0,&p_manifest[iofs+16]); } else if (attrname=="normalScreens") { encode_uint32(screen_support[SCREEN_NORMAL]?0xFFFFFFFF:0,&p_manifest[iofs+16]); } else if (attrname=="largeScreens") { encode_uint32(screen_support[SCREEN_LARGE]?0xFFFFFFFF:0,&p_manifest[iofs+16]); } else if (attrname=="xlargeScreens") { encode_uint32(screen_support[SCREEN_XLARGE]?0xFFFFFFFF:0,&p_manifest[iofs+16]); } } iofs+=20; } } break; } printf("chunk %x: size: %d\n",chunk,size); ofs+=size; }
void EditorExportPlatformAndroid::_fix_resources(Vector<uint8_t>& p_manifest) { const int UTF8_FLAG = 0x00000100; print_line("*******************GORRRGLE***********************"); uint32_t header = decode_uint32(&p_manifest[0]); uint32_t filesize = decode_uint32(&p_manifest[4]); uint32_t string_block_len = decode_uint32(&p_manifest[16]); uint32_t string_count = decode_uint32(&p_manifest[20]); uint32_t string_flags = decode_uint32(&p_manifest[28]); const uint32_t string_table_begins = 40; Vector<String> string_table; printf("stirng block len: %i\n",string_block_len); printf("stirng count: %i\n",string_count); printf("flags: %x\n",string_flags); for(int i=0;i<string_count;i++) { uint32_t offset = decode_uint32(&p_manifest[string_table_begins+i*4]); offset+=string_table_begins+string_count*4; String str = _parse_string(&p_manifest[offset],string_flags&UTF8_FLAG); if (str.begins_with("godot-project-name")) { if (str=="godot-project-name") { //project name str = get_project_name(); } else { String lang = str.substr(str.find_last("-")+1,str.length()).replace("-","_"); String prop = "application/name_"+lang; if (Globals::get_singleton()->has(prop)) { str = Globals::get_singleton()->get(prop); } else { str = get_project_name(); } } } string_table.push_back(str); } //write a new string table, but use 16 bits Vector<uint8_t> ret; ret.resize(string_table_begins+string_table.size()*4); for(int i=0;i<string_table_begins;i++) { ret[i]=p_manifest[i]; } int ofs=0; for(int i=0;i<string_table.size();i++) { encode_uint32(ofs,&ret[string_table_begins+i*4]); ofs+=string_table[i].length()*2+2+2; } ret.resize(ret.size()+ofs); uint8_t *chars=&ret[ret.size()-ofs]; for(int i=0;i<string_table.size();i++) { String s = string_table[i]; encode_uint16(s.length(),chars); chars+=2; for(int j=0;j<s.length();j++) { encode_uint16(s[j],chars); chars+=2; } encode_uint16(0,chars); chars+=2; } //pad while(ret.size()%4) ret.push_back(0); //change flags to not use utf8 encode_uint32(string_flags&~0x100,&ret[28]); //change length encode_uint32(ret.size()-12,&ret[16]); //append the rest... int rest_from = 12+string_block_len; int rest_to = ret.size(); int rest_len = (p_manifest.size() - rest_from); ret.resize(ret.size() + (p_manifest.size() - rest_from) ); for(int i=0;i<rest_len;i++) { ret[rest_to+i]=p_manifest[rest_from+i]; } //finally update the size encode_uint32(ret.size(),&ret[4]); p_manifest=ret; printf("end\n"); }