Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rayer4u committed Feb 16, 2015
1 parent 0ff6656 commit 00d9533
Show file tree
Hide file tree
Showing 14 changed files with 547 additions and 0 deletions.
19 changes: 19 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ios的应用自动签名、发布工具,基于django app
1、签名相关的证书和描述文件位于/media/profiles/按照以下目录规则,某个证书下的某个项目的描述文件
证书1/
cert.cfg
id1/
描述文件1
描述文件2
......
证书2/
2、其中证书和描述文件在ipaauto的auto.cfg里配置,其中
证书在[sign] certification字段定义
值为“证书1:类型”形式,类型字段在cert.cfg里定义,形式为“类型=xxx”
描述文件在[sign] prifile字段定义
值为描述文件名,位于在id目录里,id是项目的id

3、因为发布的plist链接必须在https保护,服务器需要配置https,而且经过确认,需要使用自CA发布的证书,ios设备安装根证书后才能正常安装
centos或者基于openssl的linux/unix可以参见以下配置https
https://jamielinux.com/articles/2013/08/act-as-your-own-certificate-authority/
https://jamielinux.com/articles/2013/08/create-and-sign-ssl-certificates-certificate-authority/
29 changes: 29 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#coding:utf-8
from django.conf import settings
from os.path import splitext,join,dirname
import os
import ConfigParser

PACKAGE_DIR="package"
UPLOAD_DIR="upload"
PROFILES_DIR=join(settings.MEDIA_ROOT, "profiles")
CERTS={}

for root, dirs, files in os.walk(PROFILES_DIR):
if root == PROFILES_DIR:
for dir in dirs:
CERTS[dir] = ''
else:
root = root[len(PROFILES_DIR)+1:]
if root not in CERTS:
continue
if 'cert.cfg' not in files:
continue

cf = ConfigParser.SafeConfigParser()
cf.read(join(PROFILES_DIR, root, 'cert.cfg'))
if 'certification' in cf.sections():
CERTS[root] = dict(cf.items('certification'))

print('certifications')
print(CERTS)
9 changes: 9 additions & 0 deletions admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.contrib import admin
from .models import UpFile

class UpFileAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields':['path', 'status', 'user']}),
('Upload date infomation', {'fields':['up_date'], 'classes':['collapse']}),
]
admin.site.register(UpFile)
43 changes: 43 additions & 0 deletions contenttyperestrictedfilefield.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#http://bixly.com/blog/accept-only-specific-file-types-in-django-file-upload/
from django.db.models import FileField
from django.forms import forms
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _

class ContentTypeRestrictedFileField(FileField):
"""
Same as FileField, but you can specify:
* content_types - list containing allowed content_types.
Example: ['application/pdf', 'image/jpeg']
* max_upload_size - a number indicating the maximum file
size allowed for upload.
2.5MB - 2621440
5MB - 5242880
10MB - 10485760
20MB - 20971520
50MB - 5242880
100MB 104857600
250MB - 214958080
500MB - 429916160
"""
def __init__(self, content_types=[], max_upload_size=429916160, **kwargs):
self.content_types = content_types
self.max_upload_size = max_upload_size

super(ContentTypeRestrictedFileField, self).__init__(**kwargs)

def clean(self, *args, **kwargs):
data = super(ContentTypeRestrictedFileField, self).clean(*args, **kwargs)
file = data.file
try:
content_type = file.content_type
if self.content_types == [] or content_type in self.content_types:
if file.size > self.max_upload_size:
raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s')
% (filesizeformat(self.max_upload_size), filesizeformat(file._size)))
else:
raise forms.ValidationError(_('Filetype %s not supported.'%content_type))
except AttributeError:
pass

return data
11 changes: 11 additions & 0 deletions forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django import forms
from models import UpFile

class UploadModelFileForm(forms.ModelForm):
class Meta:
model = UpFile
exclude = ('pub', 'plist', 'status', 'up_date', 'from_ip')

class ModelFileForm(forms.ModelForm):
class Meta:
model = UpFile
109 changes: 109 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-

import os,ipapub

from django.db import models
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
from uuid import uuid4
from contenttyperestrictedfilefield import ContentTypeRestrictedFileField


def random_path(path):
def wrapper(instance, filename):
ext = ".".join(filename.split('.')[1:])
# get filename
if instance.pk:
filename = '{0}.{1}'.format(instance.pk, ext)
else:
# set filename as random string
filename = '{0}.{1}'.format(uuid4().hex, ext)
# return the whole path to the file
return os.path.join(path, filename)
return wrapper

def icon_path(path):
def wrapper(instance, filename):
# get filename
if instance.pk:
ext = filename.split('.')[-1]
filename = '{0}.{1}'.format(instance.pk, ext)
else:
# set filename with path
filename = os.path.join(os.path.dirname(instance.path), filename)
# return the whole path to the file
return os.path.join(path, filename)
return wrapper

class UpFile(models.Model):
path = models.CharField(max_length=200) #上传路径
# file = models.FileField(upload_to=path_and_rename(ipapub.UPLOAD_DIR))
file = ContentTypeRestrictedFileField(content_types=['application/x-gtar'],
max_upload_size=104857600,
upload_to=random_path(ipapub.UPLOAD_DIR), blank=True, null=True) #上传的文件
icons = ContentTypeRestrictedFileField(content_types=['image/png'],
max_upload_size=2621440,
upload_to=icon_path(ipapub.PACKAGE_DIR)) #小图标
iconb = ContentTypeRestrictedFileField(content_types=['image/png'],
max_upload_size=2621440,
upload_to=icon_path(ipapub.PACKAGE_DIR)) #大图标
plist = models.FileField(upload_to=ipapub.PACKAGE_DIR) #plist文件
pub = models.FileField(upload_to=ipapub.PACKAGE_DIR) #发布的文件压缩包集合
signed = ContentTypeRestrictedFileField(content_types=['application/iphone'],
max_upload_size=104857600,
upload_to=icon_path(ipapub.PACKAGE_DIR), blank=True, null=True) #签名好的文件
status = models.CharField(max_length=10, blank=True) #状态,uploaded,。。。
user = models.CharField(max_length=10, blank=False) #上传的svn用户名
label = models.CharField(max_length=200, blank=True) #标签
up_date = models.DateTimeField('upload date', auto_now_add=True) #上传的时间
from_ip = models.GenericIPAddressField(blank=True, null=True) #上传的ip

def __unicode__(self):
return self.path

# These two auto-delete files from filesystem when they are unneeded:
@receiver(models.signals.post_delete, sender=UpFile)
def auto_delete_file_on_delete(sender, instance, **kwargs):
"""Deletes file from filesystem
when corresponding `UpFile` object is deleted.
"""
if instance.file:
if os.path.isfile(instance.file.path):
os.remove(instance.file.path)
if instance.signed:
if os.path.isfile(instance.signed.path):
os.remove(instance.signed.path)

# @receiver(models.signals.pre_save, sender=UpFile)
# def auto_delete_file_on_change(sender, instance, **kwargs):
# """Deletes file from filesystem
# when corresponding `UpFile` object is changed.
# """
# if not instance.pk:
# return False
#
# while True:
# try:
# old_file = UpFile.objects.get(pk=instance.pk).file
# except UpFile.DoesNotExist:
# break;
#
# new_file = instance.file
# if not old_file == new_file:
# if os.path.isfile(old_file.path):
# os.remove(old_file.path)
#
# break
#
# while True:
# try:
# old_file = UpFile.objects.get(pk=instance.pk).signed
# except UpFile.DoesNotExist:
# break;
#
# new_file = instance.signed
# if not old_file == new_file:
# if os.path.isfile(old_file.path):
# os.remove(old_file.path)
#
# break
4 changes: 4 additions & 0 deletions static/js/jquery-2.1.1.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions static/js/jquery-2.1.1.min.map

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions templates/ipapub/upfile_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<h1>{{ object.label }}&nbsp;</h1>
<p>install:<a href="itms-services://?action=download-manifest&url={{ basedir }}{{ object.plist.url }}" type="text/plain">{{ upfile.path }}</a></p>
{% if object.pub %}
<p>downlaod:<a href="{{ object.pub.url }}"">{{ object.pub.name }}</a></p>
{% endif %}
<p>ipa:<a href="{{ object.signed.url }}" type="application/iphone">{{ object.signed }}</a></p>
<p>from: {{ object.user }}</p>
<p>up_date: {{ object.up_date }}</p>
53 changes: 53 additions & 0 deletions templates/ipapub/upfile_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@

<h3>Up Ipas</h3>
<p></p>
{% if object_list %}
<table id="ipas">
<tr>
<th>Url</th>
<th>状态</th>
<th>标签</th>
<th>用户</th>
<th>时间</th>
<th>发布包</th>
</tr>
{% for upfile in object_list %}
<tr>
<td>
{% if upfile.signed and upfile.plist %}
<a href="{{ upfile.path }}" type="text/plain">{{ upfile.path }}</a>
{% endif %}
</td>
<td>{{ upfile.status }}</td>
<td>{{ upfile.label }}</td>
<td>{{ upfile.user }}</td>
<td>{{ upfile.up_date }}</td>
<td>
{% if upfile.pub %}
<a href="{{ upfile.pub.url }}"">{{ upfile.pub.name }}</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{# .... **Now the pagination section** .... #}
{% if is_paginated %}
<p></p>
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="{% url 'all' %}?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="{% url 'all' %}?page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
{% endif %}
{% else %}

<p>No ipas found!!! :(</p>
{% endif %}
49 changes: 49 additions & 0 deletions templates/upload.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{% load progress_bar %}
{% load staticfiles %}

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="{% static "js/jquery-2.1.1.min.js" %}"></script>
{% progress_bar_media %}
</head>

<body>

<form id="abc" action="" enctype="multipart/form-data" method="post" >
{{ form }}
{% progress_bar %}
<input type="submit" />
<div id="result"></div>
</form>

<script type='text/javascript'>
$("#abc").on('submit', function(event) {
event.preventDefault();

var formData = new FormData(document.forms.namedItem("abc"));
var url = $(this).attr('action');

console.log("submit start"+formData);

$.ajax({
url: url,
type: 'POST',
data: formData,
processData: false,
async: true,
xhr: xhr_progress,
success: function (data) {
alert(JSON.stringify(data));
// $('#result').html(data);
},
cache: false,
contentType: false
});

});

</script>
</body>

</html>
3 changes: 3 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
10 changes: 10 additions & 0 deletions urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.conf.urls import patterns, include, url
from django.views.generic import FormView
from views import upload, AllView, OneView
from forms import UploadModelFileForm

urlpatterns = patterns('',
url(r'^$', upload, name='upload'),
url(r'^all', AllView.as_view(), name='all'),
url(r'^(?P<path>.*)$', OneView.as_view(), name='one'),
)
Loading

0 comments on commit 00d9533

Please sign in to comment.