+
+Author & Maintainer
+-------------------
+
+This module is maintained by the `MuK IT GmbH `_.
+
+MuK IT is an Austrian company specialized in customizing and extending Odoo.
+We develop custom solutions for your individual needs to help you focus on
+your strength and expertise to grow your business.
+
+If you want to get in touch please contact us via mail
+(sale@mukit.at) or visit our website (https://mukit.at).
diff --git a/muk_fields_lobject/fields.py b/muk_fields_lobject/fields.py
index fd937c6..e470b14 100644
--- a/muk_fields_lobject/fields.py
+++ b/muk_fields_lobject/fields.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
###################################################################################
#
# Copyright (C) 2018 MuK IT GmbH
@@ -19,15 +17,14 @@
#
###################################################################################
-import re
+import base64
import hashlib
import logging
-import psycopg2
+import binascii
import tempfile
-from odoo import _
-from odoo import models, api, fields
-from odoo.tools import ustr, pycompat, human_size
+from odoo import fields
+from odoo.tools import human_size
_logger = logging.getLogger(__name__)
@@ -48,7 +45,15 @@ class LargeObject(fields.Field):
return None
lobject = record.env.cr._cnx.lobject(0, 'wb')
if isinstance(value, bytes):
- lobject.write(value)
+ try:
+ if base64.b64encode(base64.b64decode(value)) == value:
+ lobject.write(base64.b64decode(value))
+ else:
+ lobject.write(value)
+ except binascii.Error:
+ lobject.write(value)
+ elif isinstance(value, str):
+ lobject.write(base64.b64decode(value.encode('ascii')))
else:
while True:
chunk = value.read(4096)
@@ -66,6 +71,8 @@ class LargeObject(fields.Field):
return lobject.seek(0, 2)
elif record._context.get('oid'):
return lobject.oid
+ elif record._context.get('base64'):
+ return base64.b64encode(lobject.read())
elif record._context.get('stream'):
file = tempfile.TemporaryFile()
while True:
@@ -74,6 +81,13 @@ class LargeObject(fields.Field):
file.seek(0)
return file
file.write(chunk)
+ elif record._context.get('checksum'):
+ checksum = hashlib.md5()
+ while True:
+ chunk = lobject.read(4096)
+ if not chunk:
+ return checksum.hexdigest()
+ checksum.update(chunk)
else:
return lobject.read()
return value
diff --git a/muk_fields_lobject/models.py b/muk_fields_lobject/models.py
index 03fd99e..fd340db 100644
--- a/muk_fields_lobject/models.py
+++ b/muk_fields_lobject/models.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
###################################################################################
#
# Copyright (C) 2018 MuK IT GmbH
@@ -19,18 +17,12 @@
#
###################################################################################
-import re
-import hashlib
import logging
-import psycopg2
-from odoo import _
-from odoo import models, api, fields
-from odoo.tools import ustr, pycompat, human_size
+from odoo import models
_logger = logging.getLogger(__name__)
-
unlink = models.BaseModel.unlink
def large_object_unlink(self):
@@ -44,6 +36,6 @@ def large_object_unlink(self):
oids.append(oid)
unlink(self)
for oid in oids:
- lobject = self.env.cr._cnx.lobject(oid, 'rb').unlink()
+ self.env.cr._cnx.lobject(oid, 'rb').unlink()
models.BaseModel.unlink = large_object_unlink
\ No newline at end of file
diff --git a/muk_fields_lobject/models/__init__.py b/muk_fields_lobject/models/__init__.py
new file mode 100644
index 0000000..5313b03
--- /dev/null
+++ b/muk_fields_lobject/models/__init__.py
@@ -0,0 +1,20 @@
+###################################################################################
+#
+# Copyright (C) 2018 MuK IT GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+###################################################################################
+
+from . import ir_http
diff --git a/muk_fields_lobject/models/ir_http.py b/muk_fields_lobject/models/ir_http.py
new file mode 100644
index 0000000..3341230
--- /dev/null
+++ b/muk_fields_lobject/models/ir_http.py
@@ -0,0 +1,69 @@
+###################################################################################
+#
+# Copyright (C) 2018 MuK IT GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+###################################################################################
+
+import logging
+import mimetypes
+
+from odoo import models
+from odoo.http import request, STATIC_CACHE
+from odoo.exceptions import AccessError
+
+_logger = logging.getLogger(__name__)
+
+class LargeObjectControllerIrHttp(models.AbstractModel):
+
+ _inherit = 'ir.http'
+
+ @classmethod
+ def lobject_content(self, xmlid=None, model=None, id=None, field='content', unique=False,
+ filename=None, filename_field='content_fname', download=False, mimetype=None,
+ default_mimetype='application/octet-stream', access_token=None, env=None):
+ obj = None
+ env = env or request.env
+ if xmlid:
+ obj = env.ref(xmlid, False)
+ elif id and model in env.registry:
+ obj = env[model].browse(int(id))
+ if not obj or not obj.exists() or field not in obj:
+ return (404, [], None)
+ try:
+ last_update = obj['__last_update']
+ except AccessError:
+ return (403, [], None)
+ status, headers, content = None, [], None
+ content = obj.with_context({'stream': True})[field] or b''
+ if not filename:
+ if filename_field in obj:
+ filename = obj[filename_field]
+ else:
+ filename = "%s-%s-%s" % (obj._name, obj.id, field)
+ mimetype = 'mimetype' in obj and obj.mimetype or False
+ if not mimetype and filename:
+ mimetype = mimetypes.guess_type(filename)[0]
+ if not mimetype:
+ mimetype = default_mimetype
+ headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]
+ etag = bool(request) and request.httprequest.headers.get('If-None-Match')
+ retag = '"%s"' % obj.with_context({'checksum': True})[field] if content else ""
+ status = status or (304 if etag == retag else 200)
+ headers.append(('ETag', retag))
+ headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0)))
+ if download:
+ headers.append(('Content-Disposition', self.content_disposition(filename)))
+ return (status, headers, content)
\ No newline at end of file
diff --git a/muk_fields_lobject/static/description/index.html b/muk_fields_lobject/static/description/index.html
index 6d9a572..68fa4b5 100644
--- a/muk_fields_lobject/static/description/index.html
+++ b/muk_fields_lobject/static/description/index.html
@@ -55,11 +55,11 @@
-from odoo.addons.muk_fields_lobject import fields as lobject_fields
+from odoo.addons.muk_fields_lobject.fields import LargeObject
class LargeObjectModel(models.Model):
- data_content = lobject_fields.LargeObject(string="Data")
+ data_content = LargeObject(string="Data")
@api.multi
def data(self):
diff --git a/muk_fields_lobject/tests/__init__.py b/muk_fields_lobject/tests/__init__.py
new file mode 100644
index 0000000..609d308
--- /dev/null
+++ b/muk_fields_lobject/tests/__init__.py
@@ -0,0 +1,20 @@
+###################################################################################
+#
+# Copyright (C) 2017 MuK IT GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+###################################################################################
+
+from . import test_lobject
diff --git a/muk_fields_lobject/tests/test_lobject.py b/muk_fields_lobject/tests/test_lobject.py
new file mode 100644
index 0000000..de1e6d7
--- /dev/null
+++ b/muk_fields_lobject/tests/test_lobject.py
@@ -0,0 +1,40 @@
+###################################################################################
+#
+# Copyright (C) 2017 MuK IT GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+###################################################################################
+
+import os
+import logging
+
+from odoo.tests import common
+
+from odoo.addons.muk_fields_lobject.fields import LargeObject
+
+_path = os.path.dirname(os.path.dirname(__file__))
+_logger = logging.getLogger(__name__)
+
+class LargeObjectTestCase(common.TransactionCase):
+
+ def setUp(self):
+ super(LargeObjectTestCase, self).setUp()
+
+ def tearDown(self):
+ super(LargeObjectTestCase, self).tearDown()
+
+ def test_import(self):
+ self.assertEqual(LargeObject.type, "lobject")
+
\ No newline at end of file