def post(self): if not current_user.is_authenticated: abort(HTTPStatus.FORBIDDEN, message='Not authorized') login = api.payload['login'] user = get_user(login, 'login') or get_user(login, 'email') if not user: abort(HTTPStatus.BAD_REQUEST, message="User not found") return jsonify(name=user.name, surname=user.surname, login=user.login, email=user.email, role=user.get_role_description())
def post(self): if current_user.is_authenticated: return abort(HTTPStatus.METHOD_NOT_ALLOWED, message='Already logged in') login = api.payload['login'] password = api.payload['password'] user = get_user(login, 'login') or get_user(login, 'email') if user and user.confirmed and user.check_password(password=password): login_user(user) return jsonify(result='Login successful') if user and not user.confirmed: return abort(HTTPStatus.FORBIDDEN, message='Unconfirmed account') abort(HTTPStatus.UNAUTHORIZED, message=ValidationResults.WRONG_CREDS.value)
def validate(data): error_messages = [] if not (data.get('login') and data.get('email') and data.get('password') and data.get('name') and data.get('surname')): error_messages.append(ValidationResults.EMPTY_FIELDS) if get_user(data.get('login'), 'login'): error_messages.append(ValidationResults.LOGIN_EXISTS) if get_user(data.get('email'), 'email'): error_messages.append(ValidationResults.EMAIL_EXISTS) if len(data.get('password')) < 8: error_messages.append(ValidationResults.SHORT_PASSWORD) return error_messages if error_messages else [ ValidationResults.SUCCESS ]
def password(self, request, *args, **kwargs): serializer = UserPasswordSerializer(data=request.data) serializer.is_valid(raise_exception=True) userId = get_user(request) password = hashlib.sha256( request.data.get('password').encode()).hexdigest() newPassword = hashlib.sha256( request.data.get('newPassword').encode()).hexdigest() response = Response(status=401, data='아이디 또는 패스워드를 다시 확인해주세요.') try: account = Usr.objects.raw( f'SELECT * FROM (SELECT * FROM USR WHERE USR_ID=\'{userId}\') WHERE ROWNUM=1;' )[0] except IndexError: return response if account.usr_password != password: return response with connection.cursor() as cursor: cursor.execute( f"UPDATE USR SET USR_PASSWORD = '******' " \ f"WHERE USR_ID = '{userId}';" ) return HttpResponse(status=200)
def destroy(self, request, pk, *args, **kwargs): userId = get_user(request) if not userId: return HttpResponse(status=401, content="로그인이 필요합니다.") pay_id = pk with connection.cursor() as cursor: cursor.execute( f"""SELECT P.PAY_STATE, P.PAY_TYPE, P.PAY_PRICE, T.USR_ID FROM PAY P, TICKET T WHERE P.PAY_ID={pay_id} AND P.PAY_ID=T.PAY_ID;""") payusr = cursor.fetchone() err = HttpResponse(status=404, content="결제번호가 올바르지 않습니다.") if not payusr: return err (pay_state, pay_type, money, usr_id) = payusr if usr_id != userId or pay_state > 3: return err sid = transaction.savepoint() with connection.cursor() as cursor: cursor.execute(f""" UPDATE TICKET SET TICKET_STATE=2 WHERE PAY_ID={pay_id};""") try: cancel(pay_id, pay_type, money, userId) except Exception as e: transaction.savepoint_rollback(sid) return HttpResponse(status=400, content=e) return HttpResponse(status=204)
def login(): if current_user.is_authenticated: return redirect(url_for('web.index')) login = '' if request.method == 'POST': login = request.form.get('login') password = request.form.get('password') user = get_user(login, 'login') or get_user(login, 'email') if user and user.confirmed and user.check_password(password=password): login_user(user) next_page = session.get('next_page', '/') session['next_page'] = '' return redirect(next_page or url_for('web.words')) if user and not user.confirmed: session['email_to_confirm'] = user.email return redirect(url_for('web.finish_signup')) flash(ValidationResults.WRONG_CREDS.value) return render_template('login.html', form_data=login)
def edit(request, block): model_name = request.GET.get('model', None) if request.wepo.block else request.wepo.url_parts[3] id = request.GET.get('id', None) if not request.wepo.block and len(request.wepo.url_parts) > 4: id = request.wepo.url_parts[4] if id and id == 'me': from core.user import get_user id = get_user(request).id model_obj = get_model(request, model_name) model = model_obj['model'] instance = model.objects.get(id=id) if id else None fields = get_model_fields(request, model) groups = get_model_groups(request, model) template = get_template('admin/object/edit.html') context = {'groups': groups, 'fields': fields, 'instance': instance, 'model': model} if 'attributes' in block: context['attributes'] = block['attributes'] form = AdminForm(request, model, instance) from core.form import FormItem context['form'] = form context['request_wr'] = FormItem('Hidden', request, name='wr', value="json") context['request_raw'] = FormItem('Hidden', request, name='raw', value="true") context['edit_object_instance'] = FormItem('Hidden', request, name='object_instance', value=id) context['edit_object_type'] = FormItem('Hidden', request, name='object_type', value=model_name) # # assets # from core import wepo_assets from core.asset import add_asset add_asset(request, type='script', code=wepo_assets.script.jquery_form, position='footer') add_asset(request, type='script', code=""" jQuery('#object-edit #save_object').click(function() { jQuery('#object-edit').ajaxForm({ success: function(responseText, statusText, xhr, $form) { wepo.callback_message(responseText); } }); }); jQuery('#object-edit #close_form').click(function() { wepo.redirect('/admin/object/list/' + wepo.url_part(3)); }); """, include_type='code', position="footer") return template.render(Context(context))
def confirm_email(token): try: email = s.loads(token, salt=current_app.config.get('MAIL_SALT'), max_age=3600) session['email_to_confirm'] = '' user = get_user(email, 'email') user.confirmed = True update_user(user) flash('Адрес электронной почты подтверждён успешно!') login_user(user) return redirect(url_for('web.login')) except SignatureExpired: abort(401, 'Невозможно заершить регистрацию, так как ссылка устарела.')
def navbar(request, block): template = get_template('admin/navbar.html') context = {} if 'attributes' in block: context['attributes'] = block['attributes'] context['logout_link'] = '/user/logout?destination=%s' % urllib.quote(request.wepo.url.encode('utf8'), '') from core.user import get_user context['user'] = get_user(request) context['destination'] = urllib.quote(request.wepo.url.encode('utf8'), '') context['active_language'] = get_user_language(request) context['languages'] = Language.objects.all() return template.render(Context(context))
def point(self, request, *args, **kwargs): userId = get_user(request) if not userId: return HttpResponse(status=401) try: account = Usr.objects.raw( f'SELECT * FROM (SELECT * FROM USR WHERE USR_ID=\'{userId}\') WHERE ROWNUM=1;' )[0] except IndexError: return HttpResponse(status=401) else: point = account.usr_point res = {'point': point} return JsonResponse(res, status=200)
def validation(self, request, *args, **kwargs): userId = get_user(request) response = HttpResponse(status=401) response.delete_cookie('jwt') if not userId: return response try: Usr.objects.raw( f'SELECT * FROM (SELECT * FROM USR WHERE USR_ID=\'{userId}\') WHERE ROWNUM=1;' )[0] except IndexError: return response else: return HttpResponse(status=200)
def profile(self, request, *args, **kwargs): userId = get_user(request) if not userId: return HttpResponse(status=401) try: account = Usr.objects.raw( f'SELECT * FROM (SELECT * FROM USR WHERE USR_ID=\'{userId}\') WHERE ROWNUM=1;' )[0] except IndexError: return HttpResponse(status=401) else: userName = account.usr_name email = account.usr_email res = {'userId': userId, 'username': userName, 'email': email} return JsonResponse(res, status=200)
def link_contact_to_user(self, contact, bind_user_account): if strutil.is_empty(bind_user_account): contact.bind_user_id = model.EMPTY_UID return contact query = Contact.all() usermo = user.get_user(u_account=bind_user_account) if usermo is None: raise Error("cont_error_linkusernotfound", account=bind_user_account) query.filter("bind_user_id =", usermo.key()) query.filter("creator_id =", contact.creator_id) if contact.key() != None: query.filter("uid !=", contact.key()) if query.count() > 0: raise Error("cont_error_linkuserexisted", account=bind_user_account, contactName=query.get().contact_name) contact.bind_user_id = usermo.key() return contact
def file_list(request, block): template_name = 'files/file_list_container.html' directory = request.GET.get('directory', 1) offset = int(request.GET.get('offset', 0)) if offset > 0: template_name = 'files/file_list.html' template = get_template(template_name) raw_config = request.GET.get('config', {}) config = files_config_dec(raw_config) is_private = config.get('private', False) from core.models import File filter = {'directory': directory} if is_private: filter['owner'] = get_user(request).id files = File.objects.filter(**filter).order_by('-id')[offset:offset + 20] # # generate file tags # file_tags = [] for file in files: tag = get_file_tag(file) if not tag in file_tags: file_tags.append(tag) context = { 'files': files, 'file_tags': file_tags } # # assets # from core import wepo_assets from core.asset import add_asset add_asset(request, type='style', code=wepo_assets.wepo.files.file_select, position='head') return template.render(Context(context))
def authenticated(request, attributes=None): redirect_url = attributes[0] if attributes else '/user/login' url_parameters = {} if attributes and len(attributes) > 1: url_parameters = attributes[1] url_parameters = urllib.urlencode(url_parameters) if url_parameters: redirect_url = '%s?%s' % (redirect_url, url_parameters) # # redirect user to login if not logged in # user = get_user(request) if not user: return False, redirect(redirect_url) else: return True, None
def file_select(request, block): template = get_template('files/index.html') raw_config = request.GET.get('config', '') config = files_config_dec(raw_config if raw_config else {}) # crop, height, width, prefix, name image_scales = config.get('scales', {}) is_private = config.get('private', False) preview = config.get('preview', 'prws') # # get directories # directories = get_directory_tree() from core.models import File filter = {'directory': 1} if is_private: filter['owner'] = get_user(request).id files = File.objects.filter(**filter).order_by('-id')[:20] from core.form import FormItem new_directory_input = FormItem('Text', request, name='new_directory', id='new_directory', **{'class': 'col-lg-12'}) form_file_id = FormItem('Hidden', request, name='file_id', id='file_id', **{'class': 'col-lg-12'}) form_file_title = FormItem('Text', request, name='file_title', id='file_title', **{'class': 'col-lg-12'}) form_file_description = FormItem('Textarea', request, name='file_description', id='file_description', rows=10, **{'class': 'col-lg-12'}) form_file_author = FormItem('Text', request, name='file_author', id='file_author', **{'class': 'col-lg-12'}) # # generate initial file tags # file_tags = [] for file in files: tag = get_file_tag(file) if not tag in file_tags: file_tags.append(tag) context = { 'directories': directories, 'new_directory_input': new_directory_input, 'files': files, 'form_file_id': form_file_id, 'form_file_title': form_file_title, 'form_file_description': form_file_description, 'form_file_author': form_file_author, 'file_tags': file_tags, 'scales': image_scales, 'preview': preview } # # assets # from core import wepo_assets from core.asset import add_asset add_asset(request, type='script', code=wepo_assets.script.nested_sort, position='footer') add_asset(request, type='script', code=wepo_assets.script.smooth_zoom, position='footer') add_asset(request, type='style', code=wepo_assets.wepo.files.directory_tree, position='head') add_asset(request, type='style', code=wepo_assets.wepo.files.file_select, position='head') add_asset(request, type='script', code=""" wepo.files.image_scales=%s; wepo.files.widget_config='%s'; """ % (json.dumps(image_scales), raw_config), include_type='code', position="footer") return template.render(Context(context))
def create(self, request, *args, **kwargs): serializer = TicketingSerializer(data=request.data) serializer.is_valid(raise_exception=True) userId = get_user(request) email = request.data.get('email') password = hashlib.sha256( request.data.get('password', '000000').encode()).hexdigest() member = userId is not None show_id = int(self.kwargs.get('show_id')) pay_type = request.data.get('payType') ticket_amount = request.data.get('ticketAmount') seat_ids = request.data.get('seatIds') try: show = Show.objects.raw( f"SELECT * FROM SHOW WHERE SHOW_ID={show_id};")[0] except IndexError: return HttpResponse(status=404) with connection.cursor() as cursor: cursor.execute("SELECT CUSTOMER_TYPE_ID, MOVIE_FEE FROM FEE " \ f"WHERE THEATER_TYPE_ID={show.theater.theater_type.theater_type_id} " \ "ORDER BY CUSTOMER_TYPE_ID;") fee = {f[0]: f[1] for f in cursor.fetchall()} money = 0 for cus in ticket_amount: if cus['customerTypeId'] not in fee: return HttpResponse( status=400, content= f"customerType: {cus['customerTypeId']} 은(는) 올바르지 않은 값입니다." ) else: money += fee[cus['customerTypeId']] * cus['amount'] sid = transaction.savepoint() if not userId: if not email: return HttpResponse(status=400, content="비회원 예매는 이메일을 입력해야 합니다.") with connection.cursor() as cursor: cursor.execute( f"""INSERT INTO USR (USR_ID, USR_NAME, USR_EMAIL, USR_PASSWORD, USR_TYPE) VALUES ('$'||USR_SEQ.NEXTVAL, 'GUEST', '{email}', '{password}', 2);""" ) cursor.execute("SELECT '$'||USR_SEQ.CURRVAL FROM DUAL;") userId = cursor.fetchone()[0] try: pay_id = pay(pay_type, money, userId, member) except Exception as e: transaction.savepoint_rollback(sid) return HttpResponse(status=400, content=e) with connection.cursor() as cursor: cursor.execute(f"""SELECT S.SEAT_ID, S.SEAT_TYPE, T.TICKET_STATE FROM (SELECT * FROM TICKET WHERE SHOW_ID={show_id} AND (TICKET_STATE=1 OR TICKET_STATE IS NULL) ) T, SEAT S WHERE T.SEAT_ID(+)=S.SEAT_ID AND S.THEATER_ID={show.theater.theater_id};""" ) e_seats = { seat[0]: (seat[1], seat[2]) for seat in cursor.fetchall() } typeslist = [[c["customerTypeId"]] * c["amount"] for c in ticket_amount] types = list(itertools.chain(*typeslist)) with connection.cursor() as cursor: money = 0 for i in range(len(seat_ids)): seat_id = seat_ids[i] customer_type_id = types[i] try: # e_seats = { SEAT_ID: (SEAT_TYPE, TICKET_STATE) } seat = e_seats[seat_id] except KeyError: transaction.savepoint_rollback(sid) return HttpResponse( status=404, content=f"'seatNo: {seat_id}'는 존재하지 않습니다.") if not seat[0] or (seat[1] and seat[1] == 1): transaction.savepoint_rollback(sid) return HttpResponse( status=400, content=f"'seatNo: {seat_id}'는 예매할 수 없는 자리입니다.") cursor.execute( f"INSERT INTO TICKET VALUES (TICKET_SEQ.NEXTVAL, 1, {pay_id}, " \ f"{seat_id}, '{userId}', {show_id}, {customer_type_id});") return HttpResponse(status=201)
def load_user(user_id): if user_id: return get_user(ObjectId(user_id)) return None
def list(self, request, *args, **kwargs): count = request.GET.get('count') email = request.GET.get('email') userId = get_user(request) if not userId and not email: return HttpResponse(status=400, content="비회원은 이메일을 입력해야 합니다.") if count is not None: with connection.cursor() as cursor: if userId: cursor.execute(f""" SELECT COUNT(*) FROM (SELECT P.PAY_ID FROM TICKET T, PAY P WHERE P.PAY_ID=T.PAY_ID AND T.USR_ID='{userId}' AND P.PAY_STATE<=3 GROUP BY P.PAY_ID);""") else: cursor.execute(f""" SELECT COUNT(*) FROM (SELECT P.PAY_ID FROM TICKET T, PAY P WHERE P.PAY_ID=T.PAY_ID AND T.USR_ID IN (SELECT USR_ID FROM USR WHERE USR_EMAIL='{email}') AND P.PAY_STATE<=3 GROUP BY P.PAY_ID);""") count = cursor.fetchone()[0] return JsonResponse({"count": count}, status=200) res = {} with connection.cursor() as cursor: if userId: cursor.execute(f""" SELECT P.PAY_ID, P.PAY_STATE, TH.THEATER_NAME, M.MOVIE_NAME, S.SHOW_START_TIME, S.SHOW_COUNT, ST.SEAT_ROW, ST.SEAT_COL, T.CUSTOMER_TYPE_ID, P.PAY_DATE, P.PAY_PRICE FROM TICKET T, PAY P, SEAT ST, SHOW S, THEATER TH, MOVIE M WHERE T.USR_ID='{userId}' AND T.PAY_ID=P.PAY_ID AND T.SEAT_ID=ST.SEAT_ID AND T.SHOW_ID=S.SHOW_ID AND S.THEATER_ID=TH.THEATER_ID AND S.MOVIE_ID=M.MOVIE_ID ORDER BY PAY_ID;""") else: cursor.execute(f""" SELECT P.PAY_ID, P.PAY_STATE, TH.THEATER_NAME, M.MOVIE_NAME, S.SHOW_START_TIME, S.SHOW_COUNT, ST.SEAT_ROW, ST.SEAT_COL, T.CUSTOMER_TYPE_ID, P.PAY_DATE, P.PAY_PRICE FROM TICKET T, PAY P, SEAT ST, SHOW S, THEATER TH, MOVIE M WHERE T.USR_ID IN (SELECT USR_ID FROM USR WHERE USR_EMAIL='{email}') AND T.PAY_ID=P.PAY_ID AND T.SEAT_ID=ST.SEAT_ID AND T.SHOW_ID=S.SHOW_ID AND S.THEATER_ID=TH.THEATER_ID AND S.MOVIE_ID=M.MOVIE_ID ORDER BY PAY_ID;""") fetched = cursor.fetchall() tickets = filter(lambda x: x[1] <= 3, fetched) canceled = filter(lambda x: x[1] >= 4, fetched) def rows_to_pay(rows): arr = list(rows) pay = arr[0] return { "payId": pay[0], "payState": pay[1], "theaterName": pay[2], "movieName": pay[3], "showStartTime": pay[4].strftime("%Y-%m-%d %H:%M:%S"), "showCount": pay[5], "seatsList": [{ "seatRow": row[6], "seatCol": row[7], "customerType": row[8], } for row in arr], "payDate": pay[9].strftime("%Y-%m-%d %H:%M:%S"), "payPrice": pay[10] } res['tickets'] = [ rows_to_pay(rows) for _, rows in itertools.groupby(tickets, lambda x: x[0]) ] res['canceled'] = [ rows_to_pay(rows) for _, rows in itertools.groupby(canceled, lambda x: x[0]) ] return JsonResponse(res, status=200)
def list(request, block): model_name = None if hasattr(block, 'model_name'): model_name = block.model_name else: model_name = request.GET.get('model', None) if request.wepo.block else request.wepo.url_parts[3] model_name = model_name.replace('-', '_') model_obj = get_model(request, model_name) model = model_obj['model'] restricted_content = hasattr(model, 'restricted_content') template = get_template('admin/object/list.html') fields = get_model_fields(request, model) per_page = int(request.GET.get('_per_page', block.limit if hasattr(block, 'limit') else 10)) page = int(request.GET.get('_page', 0)) offset = page * per_page # sort by ... default_sort = [block.order] if hasattr(block, 'order') else model.default_sort if hasattr(model, 'default_sort') else ['id'] objects = [] if restricted_content and model.restricted_content: permissions_to_check = model.grant_permission if hasattr(model, 'grant_permission') else ['admin.superuser_access'] from core.permission import check_permissions from core.user import get_user status, action = check_permissions(request, permissions_to_check) if status: # ok has permission to list all objects = model.objects.all().order_by(*default_sort) else: # list only owners items and to those who are granted to see from django.db.models import Q user = get_user(request) query = None # grant only to those who can access this content grant_access = model.grant_access if hasattr(model, 'grant_access') else None if grant_access: for access in grant_access: if not query: query = Q(**{'%s' % access.replace('.', '__'): user}) else: query |= Q(**{'%s' % access.replace('.', '__'): user}) # grant to this content if some parameters are not yet set grant_access_empty = model.grant_access_empty if hasattr(model, 'grant_access_empty') else None if grant_access_empty: for access in grant_access_empty: if not query: query = Q(**{'%s__isnull' % access.replace('.', '__'): True}) else: query |= Q(**{'%s__isnull' % access.replace('.', '__'): True}) if not grant_access: return '' objects = model.objects.filter(query).order_by(*default_sort).distinct() else: objects = model.objects.all().order_by(*default_sort) # count objects count = objects.count() objects = objects[offset:offset + per_page] # generate pagination list_last = int(count / per_page) first = max(page - 5, 0) last = min(page + 5, list_last) pagination = [a for a in range(first, last)] show_pagination = True if hasattr(block, 'pagination'): show_pagination = block.pagination context = { 'objects': objects, 'fields': fields, 'list_first': 0, 'list_page': page, 'list_last': list_last, 'pagination': pagination, 'show_pagination': show_pagination, 'url': request.wepo.url, 'query': request.wepo.query, 'model_name': model_name, 'page': page, 'widget_size': block.widget_size if hasattr(block, 'widget_size') else 12, 'start_row': block.start_row if hasattr(block, 'start_row') else True, 'end_row': block.end_row if hasattr(block, 'end_row') else True, 'add_new_button': _(request, 'Add new %s' % model_name.title()) } return template.render(Context(context))
setattr(through_instance, object_type, instance) through_instance.save() else: tdata = {object_type:instance, through_to_model._meta.db_table:new_object} through_instance = through_model.objects.get(**tdata) through_instance.enabled = True through_instance.save() parent_model_name = post.get('parent_model_name', None) parent_id = int(post.get('parent_id', -1)) parent_field = post.get('parent_field', None) if hasattr(model, 'user'): if not instance.user: from core.user import get_user instance.user = get_user(request) instance.save() # # link new object with it's parent # if parent_model_name and parent_field and parent_id != -1: parent_model = get_model(request, parent_model_name) parent_model = parent_model['model'] parent_instance = parent_model.objects.get(id=parent_id) through = getattr(parent_model, parent_field).through through_instance = through() setattr(through_instance, parent_model_name, parent_instance) setattr(through_instance, object_type, instance)
def to_dict(self): self.bind_user_account = user.get_user(user_id=self.bind_user_id).u_account if self.bind_user_id != None and self.bind_user_id != model.EMPTY_UID else "" self.creatorDisplayName = user.get_user_display_name(self.creator_id) from contact.contactservice import ContactService self.groupKeys = list(set(map(lambda x: x.group_id, ContactService.get_instance().fetch_contactgroups(contact_id=self.key())))) return Model.to_dict(self)
def upload(request, block): # # file info # file_id = request.META.get('HTTP_X_FILE_ID', None) chunk = int(request.META.get('HTTP_X_FILE_CHUNK', 0)) file_size = int(request.META.get('HTTP_X_FILE_SIZE', 0)) selected_directory = int(request.META.get('HTTP_X_FILE_DIRECTORY', 1)) file_name = request.META.get('HTTP_X_FILE_NAME', '') mime_type = request.META.get('HTTP_X_FILE_TYPE', '') if file_id is None: return dict(status=False, message='No file defined') if file_size == 0: return dict(status=False, message='File size is 0') if file_name == '': return dict(status=False, message='No file name defined') # # Get current file chunk data # bin = request.body # # save file to temporary file # f = open('/tmp/%s' % file_id, 'a') f.write(bin) f.close() # # move uploaded file when completely uploaded # if chunk == file_size: path = datetime.datetime.now().strftime("%Y/%m/%d") file_path = '%s/%s' % (MEDIA_ROOT, path) # do not override existing images full_file_path = '%s/%s' % (file_path, file_name) if os.path.exists(full_file_path): n = datetime.datetime.now() unix_time = time.mktime(n.timetuple()) file_name = '%d%d_%s' % (unix_time, random.randint(10, 100), file_name) full_file_path = '%s/%s' % (file_path, file_name) if not os.path.exists(file_path): os.makedirs(file_path) shutil.move('/tmp/%s' % file_id, full_file_path) from core.models import File, Directory directory = Directory.objects.get(id=selected_directory) created = datetime.datetime.now() file, created = File.objects.get_or_create(file_name=file_name, directory=directory, path=path, size=file_size, created=created) file.title = ' '.join(part.upper() for part in file_name.split('.')[:-1]) file.data = {} file.mime_type = mime_type user = get_user(request) if user: file.owner = user file.save() for scale in DEFAULT_IMAGE_SCALES: scale_image(file, scale) return dict(status=True, message='File uploaded (real size: %d)' % len(bin), file_name=file.file_name, file_path=file.path, file_id=file.id, file_mime_type=file.mime_type, file_rough_mime_type=get_file_rough_mime_type(file)) return dict(status=True, message='Chunk %d uploaded (real size: %d)' % (chunk, len(bin)))