Beispiel #1
0
def createBookiGroup(groupName, groupDescription, owner):
    """
    Create Booki Group.

    @type groupName: C{string}
    @param groupName: Group name
    @type groupDescription: C{string}
    @param groupDescription: Group name
    @type owner: C{django.contrib.auth.models.User}
    @param owner: Group owner

    @rtype: C{booki.editor.models.BookiGroup}
    @return: Returns group object
    """

    import datetime

    try:
        bg = models.BookiGroup.objects.get(url_name = bookiSlugify(groupName))
    except models.BookiGroup.MultipleObjectsReturned:
        raise BookiGroupExist(groupName)
    except models.BookiGroup.DoesNotExist:
        group = models.BookiGroup(name = groupName,
                                  url_name = bookiSlugify(groupName),
                                  description = groupDescription,
                                  owner = owner,
                                  created = datetime.datetime.now())
        group.save()

        return group

    raise BookiGroupExist(groupName)
Beispiel #2
0
def createBookiGroup(groupName, groupDescription, owner):
    """
    Create Booki Group.

    @type groupName: C{string}
    @param groupName: Group name
    @type groupDescription: C{string}
    @param groupDescription: Group name
    @type owner: C{django.contrib.auth.models.User}
    @param owner: Group owner

    @rtype: C{booki.editor.models.BookiGroup}
    @return: Returns group object
    """

    import datetime

    try:
        bg = models.BookiGroup.objects.get(url_name=bookiSlugify(groupName))
    except models.BookiGroup.MultipleObjectsReturned:
        raise BookiGroupExist(groupName)
    except models.BookiGroup.DoesNotExist:
        group = models.BookiGroup(name=groupName,
                                  url_name=bookiSlugify(groupName),
                                  description=groupDescription,
                                  owner=owner,
                                  created=datetime.datetime.now())
        group.save()

        return group

    raise BookiGroupExist(groupName)
def remote_edit_discussion(request, message, bookid, version):
    """ 
    Function to edit the discussion theme in the model
    """
    import datetime
     
    discussiontheme = models.DiscussionTheme.objects.get(title = message["old_title"])
    
    discussiontheme.title = message["new_title"]
    url_title = bookiSlugify(message["new_title"])
    discussiontheme.url_title = url_title
    discussiontheme.message = message["new_message"]
    discussiontheme.labels = message["new_labels"]
    discussiontheme.access = message["new_access"]
    
    try:
      # Elgg Integration
      elgg = discussions_mysql.Update_Discussion_Theme(discussiontheme)
      #
      discussiontheme.save()
    except:
      transaction.rollback()
      return {"edited": False}
    else:
      transaction.commit()
      
    discussion = []
    discussion.append({"title": discussiontheme.title,
		 "message": discussiontheme.message,
		 "labels": discussiontheme.labels,
		 "access": discussiontheme.access,
		 "user": discussiontheme.user.username,
		 "created": discussiontheme.created.strftime("%d %b. %Y, %H:%M")})
     
    return {"edited": True, "discussion": discussion}
Beispiel #4
0
def createBookiGroup(groupName, groupDescription, request):
    """
    Create Booki Group.

    @type groupName: C{string}
    @param groupName: Group name
    @type groupDescription: C{string}
    @param groupDescription: Group name
    @type owner: C{django.contrib.auth.models.User}
    @param owner: Group owner

    @rtype: C{booki.editor.models.BookiGroup}
    @return: Returns group object
    """

    import datetime
    owner = request.user
    try:
        bg = models.BookiGroup.objects.get(url_name = bookiSlugify(groupName))
    except models.BookiGroup.MultipleObjectsReturned:
        raise BookiGroupExist(groupName)
    except models.BookiGroup.DoesNotExist:
        group = models.BookiGroup(name = groupName,
                                  url_name = bookiSlugify(groupName),
                                  description = groupDescription,
                                  owner = owner,
                                  created = datetime.datetime.now())
        group.save()

        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[-1].strip()
        else:
            ip = request.META.get('REMOTE_ADDR')
        eventlog = models.EventsLog(username = owner.username,
                       access_ip = ip,
                       event_name = "create_group",
                       event_timestamp=datetime.datetime.now(),
                       #book=0,
                       comment=group.id)

        eventlog.save()
        return group

    raise BookiGroupExist(groupName)
Beispiel #5
0
def rename_book(request, bookid):

    try:
        book = models.Book.objects.get(url_title__iexact=bookid)
    except models.Book.DoesNotExist:
        return pages.ErrorPage(request, "errors/book_does_not_exist.html", {"book_name": bookid})

    book_version = book.getVersion(None)

    if request.method == "POST":
        frm = BookRenameForm(request.POST, request.FILES)

        if request.POST["submit"] == _("Cancel"):
            return HttpResponseRedirect(reverse("control_book", args=[book.url_title]))

        if frm.is_valid():
            from booki.utils.book import renameBook
            from booki.utils.misc import bookiSlugify

            title = frm.cleaned_data["title"]
            URLTitle = frm.cleaned_data["url_title"]

            if URLTitle.strip() == "":
                URLTitle = bookiSlugify(title)

            # this is not the nice way to solve this
            if book.url_title != URLTitle:
                try:
                    b = models.Book.objects.get(url_title__iexact=URLTitle)
                except models.Book.DoesNotExist:
                    renameBook(book, title, URLTitle)
                    book.save()

                    messages.success(request, _("Successfuly renamed book."))

                    return HttpResponseRedirect(reverse("control_book", args=[book.url_title]))
            else:
                renameBook(book, title, URLTitle)
                book.save()

                messages.success(request, _("Successfuly renamed book."))

                return HttpResponseRedirect(reverse("control_book", args=[book.url_title]))

    else:
        frm = BookRenameForm(initial={"title": book.title, "url_title": book.url_title})

    return render_to_response(
        "booktypecontrol/rename_book.html",
        {"request": request, "admin_options": ADMIN_OPTIONS, "form": frm, "book": book},
        context_instance=RequestContext(request),
    )
Beispiel #6
0
def makeTitleUnique(requestedTitle):
    """If <requestedTitle> is unused, return that. Otherwise,
    return a title in the form `u'%s - %d' % (requestedTitle, n)`
    where n is the lowest non-clashing positive integer.
    """
    n = 0
    name = requestedTitle
    while True:
        titles = models.Book.objects.filter(title=name).count()
        urls = models.Book.objects.filter(url_title=bookiSlugify(name)).count()
        if not titles and not urls:
            return name
        n += 1
        name = u"%s - %d" % (requestedTitle, n)
Beispiel #7
0
def makeTitleUnique(requestedTitle):
    """If <requestedTitle> is unused, return that. Otherwise,
    return a title in the form `u'%s - %d' % (requestedTitle, n)`
    where n is the lowest non-clashing positive integer.
    """
    n = 0
    name = requestedTitle
    while True:
        titles = models.Book.objects.filter(title=name).count()
        urls = models.Book.objects.filter(url_title=bookiSlugify(name)).count()
        if not titles and not urls:
            return name
        n += 1
        name = u'%s - %d' % (requestedTitle, n)
def remote_create_discussion(request, message, bookid, version):
    """ 
    Function to create the discussion theme in the model
    """
    import datetime
    book = models.Book.objects.get(id=bookid)
    user = request.user
    url_title = bookiSlugify(message["discussion"])
    title = message["discussion"]
    lmessage = message["message"]
    state = "1"
    labels = message["labels"]
    access = message["access"]
    
    try:
      # Elgg Integration
      guid = discussions_mysql.Get_Object_Entity()
      #
      discussiontheme = models.DiscussionTheme(id = int(guid),
			      book = book,
			      user = user,
			      url_title = url_title,
			      title = title,
			      message = lmessage,
			      state = state,
			      labels = labels,
			      access = access,
			      created = datetime.datetime.now())

      discussiontheme.save()
      # Elgg Integration
      elgg = discussions_mysql.Save_Discussion_Theme(discussiontheme)
    except:
      transaction.rollback()
      return {"created": False}
    else:
      transaction.commit()
    
    
    
    discussion = []
    discussion.append({"title": discussiontheme.title,
		 "message": discussiontheme.message,
		 "user": discussiontheme.user.username,
		 "created": discussiontheme.created.strftime("%d %b. %Y, %H:%M")})
     
    return {"created": True, "discussion": discussion}
Beispiel #9
0
def checkBookAvailability(bookTitle):
    """
    Checks if the book name is available or not.

    @type bookTitle: C{string}
    @param bookTitle: Title for the book.

    @rtype: C{bool}
    @return: Returns true or false
    """

    url_title = bookiSlugify(bookTitle)

    if url_title == '':
        return False

    try:
        book = models.Book.objects.get(Q(title=bookTitle) | Q(url_title = url_title))
    except models.Book.DoesNotExist:
        return True

    return False
Beispiel #10
0
def checkBookAvailability(bookTitle):
    """
    Checks if the book name is available or not.

    @type bookTitle: C{string}
    @param bookTitle: Title for the book.

    @rtype: C{bool}
    @return: Returns true or false
    """

    url_title = bookiSlugify(bookTitle)

    if url_title == '':
        return False

    try:
        book = models.Book.objects.get(Q(title=bookTitle) | Q(url_title = url_title))
    except models.Book.DoesNotExist:
        return True

    return False
Beispiel #11
0
def checkGroupAvailability(groupName):
    """
    Checks if the group name is available or not.

    @type bookName: C{string}
    @param bookName: Name of the group.

    @rtype: C{bool}
    @return: Returns true or false
    """

    url_name = bookiSlugify(groupName)

    if url_name == '':
        return False

    try:
        group = models.BookiGroup.objects.get(Q(name=groupName) | Q(url_name = url_name))
    except models.BookiGroup.DoesNotExist:
        return True

    return False
Beispiel #12
0
def checkGroupAvailability(groupName):
    """
    Checks if the group name is available or not.

    @type bookName: C{string}
    @param bookName: Name of the group.

    @rtype: C{bool}
    @return: Returns true or false
    """

    url_name = bookiSlugify(groupName)

    if url_name == '':
        return False

    try:
        group = models.BookiGroup.objects.get(Q(name=groupName) | Q(url_name = url_name))
    except models.BookiGroup.DoesNotExist:
        return True

    return False
        parser.error("You must specify a file name for Wordpress export")

    # parse the export file
    # don't really care about validation

    document = feedparser.parse(args[0])

    try:
        user = User.objects.get(username=options.owner)
    except User.DoesNotExist:
        print "No such user %s" % options.owner
        sys.exit(-1)

    if options.title:
        bookTitle = options.title
        bookTitleURL = bookiSlugify(options.title)
    else:
        bookTitle = document["feed"]["title"]

    if options.url:
        bookTitleURL = options.url
    elif not options.title:
        bookTitleURL = bookiSlugify(document["feed"]["title"])

    # So we don't spend best years of our lives waiting

    import socket

    socket.setdefaulttimeout(10)

    # Import the feed
Beispiel #14
0
def createBook(user, bookTitle, status="imported", bookURL=None):
    """
    Creates book.

    @todo: Do something about status.

    @type user: C{django.contrib.auth.models.User}
    @param user: Booki user who will be book owner
    @type bookTitle: C{string}
    @param bookTitle: Title for the book. If bookURL is omitted it will slugify title for the url version
    @type status: C{string} 
    @param status: String name for the status (optional)
    @type bookURL: C{string}
    @param bookURL: URL title for the book (optional)

    @rtype: C{booki.editor.models.Book}
    @return: Returns book object
    """

    if bookURL:
        url_title = bookURL
    else:
        url_title = bookiSlugify(bookTitle)

    book = models.Book(url_title=url_title,
                       title=bookTitle,
                       owner=user,
                       published=datetime.datetime.now())

    book.save()

    # put this in settings file
    status_default = ["published", "not published", "imported"]
    n = len(status_default)

    for statusName in status_default:
        status = models.BookStatus(book=book, name=statusName, weight=n)
        status.save()
        n -= 1

    # not use "not published" but first in the list maybe, or just status
    book.status = models.BookStatus.objects.get(book=book,
                                                name="not published")
    book.save()

    version = models.BookVersion(book=book,
                                 major=1,
                                 minor=0,
                                 name='initial',
                                 description='')
    version.save()

    book.version = version
    book.save()

    logBookHistory(book=book, version=version, user=user, kind='book_create')

    import booki.editor.signals
    booki.editor.signals.book_created.send(sender=user, book=book)

    return book
def importFeed(document, conf):
    """
    Imports content of Wordpress export into Booktype.
    """

    # To create a book we use "createBook" function. It will do good part of magic for us in the background.
    # We have to provide:
    #   - owner of the book; every book must have an owner
    #   - book title; this is full book name
    #   - book status; every book has a status, let us just use "new" for now
    #   - book url; book must have unique name and in Booktype world it is book url name

    from booki.utils.book import createBook

    book = createBook(conf["user"], conf["bookTitle"], status="new", bookURL=conf["bookTitleURL"])

    # We use config API to check if books are by default visible or not
    isVisible = config.getConfiguration("CREATE_BOOK_VISIBLE", True)
    book.hidden = not isVisible

    book.save()

    # "createBook" function has already created default list of statuses. Let's just fetch "new" status because
    # we will need it for Chapters later
    stat = models.BookStatus.objects.filter(book=book, name="new")[0]

    # What is default URL for Wordpress blog
    wpLink = document["feed"]["link"]

    attachments = []

    for item in document["items"]:
        # We only care about posts which have "publish" status. Ignore everything else for now.
        if item["wp_status"] != u"publish":
            continue

        chapterTitle = item["title"]
        print ">> ", chapterTitle

        # So... let's clean our Wordpress post a bit. Here we ASSUME that empty line is used to separate paragraphs in Wordpress post.
        content = item["content"][0]["value"].replace("\r\n", "\n")
        content = "\n".join(["<p>%s</p>" % p for p in content.split("\n\n") if p.strip() != ""])

        # Every Booktype chapter starts with Chapter title embded in H2 tag.
        content = u"<h2>%s</h2>%s" % (chapterTitle, content)

        tree = html.document_fromstring(content)

        for e in tree.iter():

            # We only care about images now
            if e.tag == "img":
                src = e.get("src")

                if src:
                    if src.startswith("/"):
                        src = wpLink + src

                    # We don't need to download picture if it was already downloaed
                    if not src in attachments:
                        attachments.append(src)

                        u = urlparse.urlsplit(src)

                        # Get the file name and take care of funny stuff like %20 in file names
                        fileName = os.path.basename(urllib.unquote(u.path))

                        print "      >> ", fileName

                        # Download image
                        data = downloadFile(src)

                        # Let us create this attachment if we managed to download something
                        if data:
                            # Create new Attachment. "book" argument is part of legacy here, we really should care only about "version".
                            # Expect this to be removed in the future. Also, every Attachment can have different status. Not that it is
                            # used anywhere at the moment, but it has to be here.

                            att = models.Attachment(book=book, version=book.version, status=stat)

                            # We use standard method for saving the data.
                            f2 = File(StringIO(data))
                            f2.size = len(data)
                            att.attachment.save(fileName, f2, save=True)

                            # If filename with the same name already exists then Django will add prefix to the name.
                            # For instance: Image.jpg would become Image_1.jpg. That is why we check the new name.

                            fileName = os.path.basename(att.attachment.path)

                            # Set whatever we got as a new attachment name. Also notice all images are referenced as
                            # "static/image.jpg" in Booktype so we have to change the source also.
                            e.set("src", "static/%s" % fileName)

        content = etree.tostring(tree, encoding="UTF-8", method="html")

        # Create new chapter. New chapter will be in "Hold chapters". If you want it to be in "Table of contents" you would
        # need to do some extra magic. But we don't care about it now. We also don't really care about writing anything to
        # log files...

        now = datetime.datetime.now()
        chapter = models.Chapter(
            book=book,
            version=book.version,
            url_title=bookiSlugify(chapterTitle),
            title=chapterTitle,
            status=stat,
            content=content,
            created=now,
            modified=now,
        )
        chapter.save()
Beispiel #16
0
def exportBook(book_version):
    from booki import bookizip
    import time

    starttime = time.time()

    (zfile, zname) = tempfile.mkstemp()

    spine = []
    toc_top = []
    toc_current = toc_top
    waiting_for_url = []

    info = {
        "version": 1,
        "TOC": toc_top,
        "spine": spine,
        "metadata": _format_metadata(book_version.book),
        "manifest": {},
    }

    bzip = bookizip.BookiZip(zname, info=info)
    chapter_n = 1

    for i, chapter in enumerate(models.BookToc.objects.filter(version=book_version).order_by("-weight")):
        if chapter.chapter:
            # It's a real chapter! With content!
            try:
                content = _fix_content(book_version.book, chapter, chapter_n)
            except:
                continue

            chapter_n += 1
            ID = "ch%03d_%s" % (i, chapter.chapter.url_title.encode("utf-8"))
            filename = ID + ".html"

            toc_current.append({"title": chapter.chapter.title, "url": filename, "type": "chapter", "role": "text"})

            # If this is the first chapter in a section, lend our url
            # to the section, which has no content and thus no url of
            # its own.  If this section was preceded by an empty
            # section, it will be waiting too, hence "while" rather
            # than "if".
            while waiting_for_url:
                section = waiting_for_url.pop()
                section["url"] = filename

            bzip.add_to_package(ID, filename, content, "text/html")
            spine.append(ID)

        else:
            # A new top level section.
            title = chapter.name.encode("utf-8")
            ID = "s%03d_%s" % (i, bookiSlugify(title))

            toc_current = []
            section = {"title": title, "url": "", "type": "booki-section", "children": toc_current}

            toc_top.append(section)
            waiting_for_url.append(section)

    # Attachments are images (and perhaps more).  They do not know
    # whether they are currently in use, or what chapter they belong
    # to, so we add them all.
    # XXX scan for img links while adding chapters, and only add those.

    for i, attachment in enumerate(models.Attachment.objects.filter(version=book_version)):
        try:
            f = open(attachment.attachment.name, "rb")
            blob = f.read()
            f.close()
        except (IOError, OSError), e:
            msg = "couldn't read attachment %s" % e
            logWarning(msg)
            continue

        fn = os.path.basename(attachment.attachment.name.encode("utf-8"))

        ID = "att%03d_%s" % (i, bookiSlugify(fn))
        if "." in fn:
            _, ext = fn.rsplit(".", 1)
            mediatype = bookizip.MEDIATYPES.get(ext.lower(), bookizip.MEDIATYPES[None])
        else:
            mediatype = bookizip.MEDIATYPES[None]

        bzip.add_to_package(ID, "static/%s" % fn, blob, mediatype)
Beispiel #17
0
def importBookFromFile(user, zname, createTOC=False, **extraOptions):
    """Create a new book from a bookizip filename"""

    from booki.utils.log import logChapterHistory

    # unzip it
    zf = zipfile.ZipFile(zname)
    # load info.json
    info = json.loads(zf.read("info.json"))
    logWarning("Loaded json file %r" % info)

    metadata = info["metadata"]
    manifest = info["manifest"]
    TOC = info["TOC"]

    if extraOptions.get("book_title", None):
        bookTitle = extraOptions["book_title"]
    else:
        bookTitle = get_metadata(metadata, "title", ns=DC)[0]

    bookTitle = makeTitleUnique(bookTitle)
    logWarning("Chose unique book title %r" % bookTitle)

    if extraOptions.get("book_url", None):
        bookURL = extraOptions["book_url"]
    else:
        bookURL = None

    book = createBook(user, bookTitle, status="new", bookURL=bookURL)

    if extraOptions.get("hidden"):
        book.hidden = True
        book.save()

    # this is for Table of Contents
    p = re.compile('\ssrc="(.*)"')

    # what if it does not have status "new"
    stat = models.BookStatus.objects.filter(book=book, name="new")[0]

    chapters = getChaptersFromTOC(TOC)
    n = len(chapters) + 1  # is +1 necessary?
    now = datetime.datetime.now()

    for chapterName, chapterFile, is_section in chapters:
        urlName = bookiSlugify(chapterName)

        if is_section:  # create section
            if createTOC:
                c = models.BookToc(book=book, version=book.version, name=chapterName, chapter=None, weight=n, typeof=2)
                c.save()
                n -= 1
        else:  # create chapter
            # check if i can open this file at all
            content = zf.read(chapterFile)

            # content = p.sub(r' src="../\1"', content)

            chapter = models.Chapter(
                book=book,
                version=book.version,
                url_title=urlName,
                title=chapterName,
                status=stat,
                content=content,
                created=now,
                modified=now,
            )
            chapter.save()

            history = logChapterHistory(
                chapter=chapter, content=content, user=user, comment="", revision=chapter.revision
            )

            if createTOC:
                c = models.BookToc(
                    book=book, version=book.version, name=chapterName, chapter=chapter, weight=n, typeof=1
                )
                c.save()
                n -= 1

    stat = models.BookStatus.objects.filter(book=book, name="new")[0]

    from django.core.files import File

    for item in manifest.values():
        if item["mimetype"] != "text/html":
            attachmentName = item["url"]

            if attachmentName.startswith("static/"):
                att = models.Attachment(book=book, version=book.version, status=stat)

                s = zf.read(attachmentName)
                f = StringIO(s)
                f2 = File(f)
                f2.size = len(s)
                att.attachment.save(os.path.basename(attachmentName), f2, save=False)
                att.save()
                f.close()

    # metadata
    for namespace in metadata:
        # namespace is something like "http://purl.org/dc/elements/1.1/" or ""
        # in the former case, preepend it to the name, in {}.
        ns = "{%s}" % namespace if namespace else ""
        for keyword, schemes in metadata[namespace].iteritems():
            for scheme, values in schemes.iteritems():
                # schema, if it is set, describes the value's format.
                # for example, an identifier might be an ISBN.
                sc = "{%s}" % scheme if scheme else ""
                key = "%s%s%s" % (ns, keyword, sc)
                for v in values:
                    if not v:
                        continue
                    try:
                        info = models.Info(book=book, name=key)
                        if len(v) >= 2500:
                            info.value_text = v
                            info.kind = 2
                        else:
                            info.value_string = v
                            info.kind = 0
                        info.save()
                    except:
                        # For now just ignore any kind of error here.
                        # Considering we don't handle metadata as we
                        # should it is not such a problem.
                        pass

    zf.close()

    return book
Beispiel #18
0
def create_book(request, username):
    """
    Django View. Show content for Create Book dialog and creates book.

    @type request: C{django.http.HttpRequest}
    @param request: Django Request
    @type username: C{string}
    @param username: Username.
    """

    import os
    from glob import glob
    import datetime
    from xml.dom import minidom
    from django.contrib.auth.models import User
    from booki.utils.misc import isBookLimitReached

    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        try:
            resp = pages.ErrorPage(request, "errors/user_does_not_exist.html", {"username": username})
        except:
            transaction.rollback()
            raise
        else:
            transaction.commit()    

        return resp

    if isBookLimitReached() or not request.user.is_authenticated():
        try:
            resp = pages.ErrorPage(request, "errors/no_permissions.html")
        except:
            transaction.rollback()
            raise
        else:
            transaction.commit()    

        return resp

    from booki.utils.book import checkBookAvailability, createBook
    from booki.editor import models

    book_visible = config.getConfiguration('CREATE_BOOK_VISIBLE')
    book_license = config.getConfiguration('CREATE_BOOK_LICENSE')
    admin_create = config.getConfiguration('ADMIN_CREATE_BOOKS')
    templates_source = config.getConfiguration('BOOK_TYPES_DIR')

    if request.user.is_superuser:
        admin_create = False


    if request.GET.get("q", "") == "check":
        from booki.utils.json_wrapper import json

        data = {"available": checkBookAvailability(request.GET.get('bookname', '').strip())}

        try:
            resp = HttpResponse(json.dumps(data), "text/plain")
        except:
            transaction.rollback()
            raise
        else:
            transaction.commit()    

        return resp

    if request.method == 'POST' and admin_create == False:
        book = None
        try:
            # hidden on
            # description
            # license
            # title
            # cover
            x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
            if x_forwarded_for:
                ip = x_forwarded_for.split(',')[-1].strip()
            else:
                ip = request.META.get('REMOTE_ADDR')
            book = createBook(request.user, request.POST.get('title'), ip)

            lic = models.License.objects.get(abbrevation=request.POST.get('license'))
            book.license = lic
            book.description = request.POST.get('description', '')

            if request.POST.get("hidden", "") == "on":
                is_hidden = True
            else:
                is_hidden = False
            book.hidden = is_hidden
            
            from django.core.files import File

            if request.FILES.has_key('cover'):
                # TODO: Show some kind of error message to the user
                from booki.utils import misc
                import os

                try:
                    fh, fname = misc.saveUploadedAsFile(request.FILES['cover'])
                    book.setCover(fname)
                    os.unlink(fname)
                except:
                    pass

            book.save()
            book_version = book.getVersion()
            tf = request.POST.get('template', '')
            try:
                xmldoc = minidom.parse(tf)
                chapters = xmldoc.getElementsByTagName('chapter')
            except:
                chapters = []
            for chapter in chapters:
                chapter_title = chapter.attributes['title'].value
                chapter_content = u'<h1>{}</h1>'.format(chapter.attributes['content'].value)
                url_title = bookiSlugify(chapter_title)
                status = models.BookStatus.objects.filter(book=book).order_by("-weight")[0]
                chapter_o = models.Chapter(book=book,
                                 version = book_version,
                                 url_title = url_title,
                                 title = chapter_title,
                                 status = status,
                                 content = chapter_content,
                                 created = datetime.datetime.now(),
                                 modified = datetime.datetime.now())
                chapter_o.save()

                toc_items = len(book_version.getTOC()) + 1
                for itm in models.BookToc.objects.filter(version=book_version, book=book).order_by("-weight"):
                    itm.weight = toc_items
                    itm.save()
                toc_items -= 1
                tc = models.BookToc(version=book_version,
                                book = book,
                                name = chapter_title,
                                chapter = chapter_o,
                                weight = 1,
                                typeof = 1)
                tc.save()

        except:
            lines = traceback.format_exc().split('\n')
            for line in lines:
                print line
            transaction.rollback()
        else:
            transaction.commit()


        try:
            resp = render_to_response('account/create_book_redirect.html', {"request": request,
                                                                            "user": user,
                                                                            "book": book})
        except:
            transaction.rollback()
            raise
        else:
            transaction.commit()    

        return resp
        
    from booki.editor.models import License
    
    licenses = License.objects.all().order_by('name')

    try:
        template_files = glob(os.path.join(templates_source, '*.xml'))
    except:
        template_files = []
    templates = [{'name': 'Vac\xc3\xado', 'file': '/'}]
    for tf in template_files:
        print 'parse ' + tf
        xmldoc = minidom.parse(tf)
        print 'ok'
        tpltag = xmldoc.getElementsByTagName('template')[0]
        template = {}
        template['name'] = tpltag.attributes['title'].value
        template['file'] = tf
        templates.append(template)

    try:
        resp = render_to_response('account/create_book.html', {"request": request,
                                                               "book_visible": book_visible,
                                                               "book_license": book_license,
                                                               "admin_create": admin_create,
                                                               "licenses": licenses,
                                                               'templates': templates,
                                                               "user": user})
    except:
        transaction.rollback()
        raise
    else:
        transaction.commit()    

    return resp
Beispiel #19
0
def importFeed(document, conf):
    """
    Imports content of Wordpress export into Booktype.
    """

    # To create a book we use "createBook" function. It will do good part of magic for us in the background.
    # We have to provide:
    #   - owner of the book; every book must have an owner
    #   - book title; this is full book name
    #   - book status; every book has a status, let us just use "new" for now
    #   - book url; book must have unique name and in Booktype world it is book url name

    from booki.utils.book import createBook

    book = createBook(conf['user'],
                      conf['bookTitle'],
                      status="new",
                      bookURL=conf['bookTitleURL'])

    # We use config API to check if books are by default visible or not
    isVisible = config.getConfiguration('CREATE_BOOK_VISIBLE', True)
    book.hidden = not isVisible

    book.save()

    # "createBook" function has already created default list of statuses. Let's just fetch "new" status because
    # we will need it for Chapters later
    stat = models.BookStatus.objects.filter(book=book, name="new")[0]

    # What is default URL for Wordpress blog
    wpLink = document['feed']['link']

    attachments = []

    for item in document['items']:
        # We only care about posts which have "publish" status. Ignore everything else for now.
        if item['wp_status'] != u'publish':
            continue

        chapterTitle = item['title']
        print '>> ', chapterTitle

        # So... let's clean our Wordpress post a bit. Here we ASSUME that empty line is used to separate paragraphs in Wordpress post.
        content = item['content'][0]['value'].replace('\r\n', '\n')
        content = '\n'.join([
            '<p>%s</p>' % p for p in content.split('\n\n') if p.strip() != ''
        ])

        # Every Booktype chapter starts with Chapter title embded in H2 tag.
        content = u'<h2>%s</h2>%s' % (chapterTitle, content)

        tree = html.document_fromstring(content)

        for e in tree.iter():

            # We only care about images now
            if e.tag == 'img':
                src = e.get('src')

                if src:
                    if src.startswith('/'):
                        src = wpLink + src

                    # We don't need to download picture if it was already downloaed
                    if not src in attachments:
                        attachments.append(src)

                        u = urlparse.urlsplit(src)

                        # Get the file name and take care of funny stuff like %20 in file names
                        fileName = os.path.basename(urllib.unquote(u.path))

                        print '      >> ', fileName

                        # Download image
                        data = downloadFile(src)

                        # Let us create this attachment if we managed to download something
                        if data:
                            # Create new Attachment. "book" argument is part of legacy here, we really should care only about "version".
                            # Expect this to be removed in the future. Also, every Attachment can have different status. Not that it is
                            # used anywhere at the moment, but it has to be here.

                            att = models.Attachment(book=book,
                                                    version=book.version,
                                                    status=stat)

                            # We use standard method for saving the data.
                            f2 = File(StringIO(data))
                            f2.size = len(data)
                            att.attachment.save(fileName, f2, save=True)

                            # If filename with the same name already exists then Django will add prefix to the name.
                            # For instance: Image.jpg would become Image_1.jpg. That is why we check the new name.

                            fileName = os.path.basename(att.attachment.path)

                            # Set whatever we got as a new attachment name. Also notice all images are referenced as
                            # "static/image.jpg" in Booktype so we have to change the source also.
                            e.set('src', 'static/%s' % fileName)

        content = etree.tostring(tree, encoding='UTF-8', method='html')

        # Create new chapter. New chapter will be in "Hold chapters". If you want it to be in "Table of contents" you would
        # need to do some extra magic. But we don't care about it now. We also don't really care about writing anything to
        # log files...

        now = datetime.datetime.now()
        chapter = models.Chapter(book=book,
                                 version=book.version,
                                 url_title=bookiSlugify(chapterTitle),
                                 title=chapterTitle,
                                 status=stat,
                                 content=content,
                                 created=now,
                                 modified=now)
        chapter.save()
Beispiel #20
0
def importBookFromFile(user, zname, createTOC=False, **extraOptions):
    """Create a new book from a bookizip filename"""

    from booki.utils.log import logChapterHistory

    # unzip it
    zf = zipfile.ZipFile(zname)
    # load info.json
    info = json.loads(zf.read('info.json'))
    logWarning("Loaded json file %r" % info)

    metadata = info['metadata']
    manifest = info['manifest']
    TOC = info['TOC']

    if extraOptions.get('book_title', None):
        bookTitle = extraOptions['book_title']
    else:
        bookTitle = get_metadata(metadata, 'title', ns=DC)[0]

    bookTitle = makeTitleUnique(bookTitle)
    logWarning("Chose unique book title %r" % bookTitle)

    if extraOptions.get('book_url', None):
        bookURL = extraOptions['book_url']
    else:
        bookURL = None

    book = createBook(user, bookTitle, status="new", bookURL=bookURL)

    if extraOptions.get("hidden"):
        book.hidden = True
        book.save()

    # this is for Table of Contents
    p = re.compile('\ssrc="(.*)"')

    # what if it does not have status "new"
    stat = models.BookStatus.objects.filter(book=book, name="new")[0]

    chapters = getChaptersFromTOC(TOC)
    n = len(chapters) + 1  #is +1 necessary?
    now = datetime.datetime.now()

    for chapterName, chapterFile, is_section in chapters:
        urlName = bookiSlugify(chapterName)

        if is_section:  # create section
            if createTOC:
                c = models.BookToc(book=book,
                                   version=book.version,
                                   name=chapterName,
                                   chapter=None,
                                   weight=n,
                                   typeof=2)
                c.save()
                n -= 1
        else:  # create chapter
            # check if i can open this file at all
            content = zf.read(chapterFile)

            #content = p.sub(r' src="../\1"', content)

            chapter = models.Chapter(book=book,
                                     version=book.version,
                                     url_title=urlName,
                                     title=chapterName,
                                     status=stat,
                                     content=content,
                                     created=now,
                                     modified=now)
            chapter.save()

            history = logChapterHistory(chapter=chapter,
                                        content=content,
                                        user=user,
                                        comment="",
                                        revision=chapter.revision)

            if createTOC:
                c = models.BookToc(book=book,
                                   version=book.version,
                                   name=chapterName,
                                   chapter=chapter,
                                   weight=n,
                                   typeof=1)
                c.save()
                n -= 1

    stat = models.BookStatus.objects.filter(book=book, name="new")[0]

    from django.core.files import File

    for item in manifest.values():
        if item["mimetype"] != 'text/html':
            attachmentName = item['url']

            if attachmentName.startswith("static/"):
                att = models.Attachment(book=book,
                                        version=book.version,
                                        status=stat)

                s = zf.read(attachmentName)
                f = StringIO(s)
                f2 = File(f)
                f2.size = len(s)
                att.attachment.save(os.path.basename(attachmentName),
                                    f2,
                                    save=False)
                att.save()
                f.close()

    # metadata
    for namespace in metadata:
        # namespace is something like "http://purl.org/dc/elements/1.1/" or ""
        # in the former case, preepend it to the name, in {}.
        ns = ('{%s}' % namespace if namespace else '')
        for keyword, schemes in metadata[namespace].iteritems():
            for scheme, values in schemes.iteritems():
                #schema, if it is set, describes the value's format.
                #for example, an identifier might be an ISBN.
                sc = ('{%s}' % scheme if scheme else '')
                key = "%s%s%s" % (ns, keyword, sc)
                for v in values:
                    if not v: continue
                    try:
                        info = models.Info(book=book, name=key)
                        if len(v) >= 2500:
                            info.value_text = v
                            info.kind = 2
                        else:
                            info.value_string = v
                            info.kind = 0
                        info.save()
                    except:
                        # For now just ignore any kind of error here.
                        # Considering we don't handle metadata as we
                        # should it is not such a problem.
                        pass

    zf.close()

    return book
Beispiel #21
0
def exportBook(book_version):
    from booki import bookizip
    import time
    starttime = time.time()

    (zfile, zname) = tempfile.mkstemp()

    spine = []
    toc_top = []
    toc_current = toc_top
    waiting_for_url = []

    info = {
        "version": 1,
        "TOC": toc_top,
        "spine": spine,
        "metadata": _format_metadata(book_version.book),
        "manifest": {}
    }

    bzip = bookizip.BookiZip(zname, info=info)
    chapter_n = 1

    for i, chapter in enumerate(
            models.BookToc.objects.filter(
                version=book_version).order_by("-weight")):
        if chapter.chapter:
            # It's a real chapter! With content!
            try:
                content = _fix_content(book_version.book, chapter, chapter_n)
            except:
                continue

            chapter_n += 1
            ID = "ch%03d_%s" % (i, chapter.chapter.url_title.encode('utf-8'))
            filename = ID + '.html'

            toc_current.append({
                "title": chapter.chapter.title,
                "url": filename,
                "type": "chapter",
                "role": "text"
            })

            # If this is the first chapter in a section, lend our url
            # to the section, which has no content and thus no url of
            # its own.  If this section was preceded by an empty
            # section, it will be waiting too, hence "while" rather
            # than "if".
            while waiting_for_url:
                section = waiting_for_url.pop()
                section["url"] = filename

            bzip.add_to_package(ID, filename, content, "text/html")
            spine.append(ID)

        else:
            #A new top level section.
            title = chapter.name.encode("utf-8")
            ID = "s%03d_%s" % (i, bookiSlugify(title))

            toc_current = []
            section = {
                "title": title,
                "url": '',
                "type": "booki-section",
                "children": toc_current
            }

            toc_top.append(section)
            waiting_for_url.append(section)

    #Attachments are images (and perhaps more).  They do not know
    #whether they are currently in use, or what chapter they belong
    #to, so we add them all.
    #XXX scan for img links while adding chapters, and only add those.

    for i, attachment in enumerate(
            models.Attachment.objects.filter(version=book_version)):
        try:
            f = open(attachment.attachment.name, "rb")
            blob = f.read()
            f.close()
        except (IOError, OSError), e:
            msg = "couldn't read attachment %s" % e
            logWarning(msg)
            continue

        fn = os.path.basename(attachment.attachment.name.encode("utf-8"))

        ID = "att%03d_%s" % (i, bookiSlugify(fn))
        if '.' in fn:
            _, ext = fn.rsplit('.', 1)
            mediatype = bookizip.MEDIATYPES.get(ext.lower(),
                                                bookizip.MEDIATYPES[None])
        else:
            mediatype = bookizip.MEDIATYPES[None]

        bzip.add_to_package(ID, "static/%s" % fn, blob, mediatype)
Beispiel #22
0
def createBook(user, bookTitle, userip = "", status = "new", bookURL = None):
    """
    Creates book.

    @todo: Do something about status.

    @type user: C{django.contrib.auth.models.User}
    @param user: Booki user who will be book owner
    @type bookTitle: C{string}
    @param bookTitle: Title for the book. If bookURL is omitted it will slugify title for the url version
    @type status: C{string} 
    @param status: String name for the status (optional)
    @type bookURL: C{string}
    @param bookURL: URL title for the book (optional)

    @rtype: C{booki.editor.models.Book}
    @return: Returns book object
    """
    import datetime

    if bookURL:
        url_title = bookURL
    else:
        url_title = bookiSlugify(bookTitle)

    book = models.Book(url_title = url_title,
                       title = bookTitle,
                       owner = user, 
                       created = datetime.datetime.now(),
                       published = datetime.datetime.now())

    book.save()

    # put this in settings file
    status_default = ["new", "needs content", "completed", "to be proofed"]
    n = len(status_default)

    for statusName in status_default:
        status = models.BookStatus(book=book, name=statusName, weight=n)
        status.save()
        n -= 1

    # not use "not published" but first in the list maybe, or just status
    book.status = models.BookStatus.objects.get(book=book, name="new")
    book.save()
    
    
    version = models.BookVersion(book = book,
                                 major = 1,
                                 minor = 0,
                                 name = 'initial',
                                 description = '',
                                 created=datetime.datetime.now())
    version.save()

    book.version = version
    book.save()



    logBookHistory(book = book, 
                   version = version,
                   user = user,
                   kind = 'book_create')

    eventlog = models.EventsLog(username = user.username,
                       access_ip = userip,
                       event_name = "create_book",
                       event_timestamp=datetime.datetime.now(),
                       book=book,
                       comment=bookTitle)

    eventlog.save()


    import booki.editor.signals    
    booki.editor.signals.book_created.send(sender = user, book = book)

    return book
Beispiel #23
0
        parser.error("You must specify a file name for Wordpress export")

    # parse the export file
    # don't really care about validation

    document = feedparser.parse(args[0])

    try:
        user = User.objects.get(username=options.owner)
    except User.DoesNotExist:
        print 'No such user %s' % options.owner
        sys.exit(-1)

    if options.title:
        bookTitle = options.title
        bookTitleURL = bookiSlugify(options.title)
    else:
        bookTitle = document['feed']['title']

    if options.url:
        bookTitleURL = options.url
    elif not options.title:
        bookTitleURL = bookiSlugify(document['feed']['title'])

    # So we don't spend best years of our lives waiting

    import socket
    socket.setdefaulttimeout(10)

    # Import the feed