cloudnoteslib 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudnoteslib/__init__.py +128 -0
- cloudnoteslib/analyzers/__init__.py +14 -0
- cloudnoteslib/analyzers/content_analyzer.py +180 -0
- cloudnoteslib/analyzers/search.py +143 -0
- cloudnoteslib/analyzers/statistics.py +88 -0
- cloudnoteslib/config.py +28 -0
- cloudnoteslib/exceptions.py +19 -0
- cloudnoteslib/exporters/__init__.py +11 -0
- cloudnoteslib/exporters/base.py +31 -0
- cloudnoteslib/exporters/json_exporter.py +19 -0
- cloudnoteslib/exporters/markdown_exporter.py +28 -0
- cloudnoteslib/models/__init__.py +18 -0
- cloudnoteslib/models/note.py +323 -0
- cloudnoteslib/models/note_collection.py +233 -0
- cloudnoteslib/models/tag.py +129 -0
- cloudnoteslib/processors/__init__.py +36 -0
- cloudnoteslib/processors/base.py +157 -0
- cloudnoteslib/processors/markdown_processor.py +157 -0
- cloudnoteslib/processors/plaintext_processor.py +103 -0
- cloudnoteslib/processors/richtext_processor.py +122 -0
- cloudnoteslib/security/__init__.py +12 -0
- cloudnoteslib/security/encryptor.py +81 -0
- cloudnoteslib/security/sanitizer.py +56 -0
- cloudnoteslib-0.1.0.dist-info/METADATA +37 -0
- cloudnoteslib-0.1.0.dist-info/RECORD +27 -0
- cloudnoteslib-0.1.0.dist-info/WHEEL +5 -0
- cloudnoteslib-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cloudnoteslib.security — Note Security Tools.
|
|
3
|
+
|
|
4
|
+
Exports:
|
|
5
|
+
NoteEncryptor: AES encryption/decryption for sensitive notes.
|
|
6
|
+
ContentSanitizer: XSS prevention and HTML sanitization.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .encryptor import NoteEncryptor
|
|
10
|
+
from .sanitizer import ContentSanitizer
|
|
11
|
+
|
|
12
|
+
__all__ = ["NoteEncryptor", "ContentSanitizer"]
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cloudnoteslib.security.encryptor — Note Encryption Engine.
|
|
3
|
+
|
|
4
|
+
Provides simple AES-inspired (using Fernet) encryption for securing
|
|
5
|
+
highly sensitive note content before database storage.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import base64
|
|
9
|
+
try:
|
|
10
|
+
from cryptography.fernet import Fernet
|
|
11
|
+
from cryptography.hazmat.primitives import hashes
|
|
12
|
+
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
13
|
+
CRYPTO_AVAILABLE = True
|
|
14
|
+
except ImportError:
|
|
15
|
+
CRYPTO_AVAILABLE = False
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NoteEncryptor:
|
|
19
|
+
"""
|
|
20
|
+
Encrypts and decrypts note content.
|
|
21
|
+
|
|
22
|
+
Uses Fernet (symmetric encryption verified with a MAC).
|
|
23
|
+
Keys are derived from a password using PBKDF2.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, salt: bytes = b'cloudnotes_salt_123'):
|
|
27
|
+
if not CRYPTO_AVAILABLE:
|
|
28
|
+
raise ImportError(
|
|
29
|
+
"cryptography package is required for NoteEncryptor. "
|
|
30
|
+
"Install with: pip install cryptography"
|
|
31
|
+
)
|
|
32
|
+
self._salt = salt
|
|
33
|
+
|
|
34
|
+
def _get_key(self, password: str) -> bytes:
|
|
35
|
+
"""Derive a secure encryption key from a password."""
|
|
36
|
+
kdf = PBKDF2HMAC(
|
|
37
|
+
algorithm=hashes.SHA256(),
|
|
38
|
+
length=32,
|
|
39
|
+
salt=self._salt,
|
|
40
|
+
iterations=100000,
|
|
41
|
+
)
|
|
42
|
+
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
|
|
43
|
+
return key
|
|
44
|
+
|
|
45
|
+
def encrypt(self, plain_text: str, password: str) -> str:
|
|
46
|
+
"""
|
|
47
|
+
Encrypt plain text using the password.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
plain_text: Text to encrypt.
|
|
51
|
+
password: Password to derive key from.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Encrypted URL-safe base64 string.
|
|
55
|
+
"""
|
|
56
|
+
key = self._get_key(password)
|
|
57
|
+
f = Fernet(key)
|
|
58
|
+
encrypted = f.encrypt(plain_text.encode('utf-8'))
|
|
59
|
+
return encrypted.decode('utf-8')
|
|
60
|
+
|
|
61
|
+
def decrypt(self, encrypted_text: str, password: str) -> str:
|
|
62
|
+
"""
|
|
63
|
+
Decrypt text using the password.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
encrypted_text: Encrypted string.
|
|
67
|
+
password: Password to derive key from.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Decrypted plain text.
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
ValueError: If decryption fails (wrong password or corrupted data).
|
|
74
|
+
"""
|
|
75
|
+
try:
|
|
76
|
+
key = self._get_key(password)
|
|
77
|
+
f = Fernet(key)
|
|
78
|
+
decrypted = f.decrypt(encrypted_text.encode('utf-8'))
|
|
79
|
+
return decrypted.decode('utf-8')
|
|
80
|
+
except Exception as e:
|
|
81
|
+
raise ValueError(f"Decryption failed: {str(e)}")
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cloudnoteslib.security.sanitizer — Content Sanitizer.
|
|
3
|
+
|
|
4
|
+
Prevents XSS (Cross-Site Scripting) by stripping malicious tags
|
|
5
|
+
from HTML/Rich text content.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import re
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ContentSanitizer:
|
|
12
|
+
"""
|
|
13
|
+
Sanitizes note content to prevent XSS attacks.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
# Tags that are always stripped, along with their contents
|
|
17
|
+
DANGEROUS_TAGS = ['script', 'style', 'iframe', 'object', 'embed', 'applet']
|
|
18
|
+
|
|
19
|
+
def sanitize(self, content: str) -> str:
|
|
20
|
+
"""
|
|
21
|
+
Remove dangerous HTML tags and attributes from content.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
content: Raw user input.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Sanitized content safe for rendering.
|
|
28
|
+
"""
|
|
29
|
+
if not content:
|
|
30
|
+
return ""
|
|
31
|
+
|
|
32
|
+
clean = content
|
|
33
|
+
|
|
34
|
+
# 1. Remove dangerous tags and their contents entirely
|
|
35
|
+
for tag in self.DANGEROUS_TAGS:
|
|
36
|
+
pattern = f"<{tag}[^>]*>.*?</{tag}>"
|
|
37
|
+
clean = re.sub(pattern, "", clean, flags=re.IGNORECASE | re.DOTALL)
|
|
38
|
+
|
|
39
|
+
# 2. Remove inline event handlers (onclick, onload, etc)
|
|
40
|
+
# Matches any attribute starting with 'on' followed by =
|
|
41
|
+
clean = re.sub(
|
|
42
|
+
r'(<[^>]+)(\son[a-z]+\s*=\s*(["\']).*?\3)([^>]*>)',
|
|
43
|
+
r'\1\4',
|
|
44
|
+
clean,
|
|
45
|
+
flags=re.IGNORECASE
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# 3. Remove javascript: URIs in href or src attributes
|
|
49
|
+
clean = re.sub(
|
|
50
|
+
r'((?:href|src)\s*=\s*["\'])\s*javascript:[^"\']*["\']',
|
|
51
|
+
r'\1#"',
|
|
52
|
+
clean,
|
|
53
|
+
flags=re.IGNORECASE
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return clean
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cloudnoteslib
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A reusable Object-Oriented generic library for note processing, analysis, and security.
|
|
5
|
+
Home-page: https://github.com/Kavyavegunta04/Cloudnote
|
|
6
|
+
Author: Kavya
|
|
7
|
+
Author-email: Kavya <kavyavegunta27@gmail.com>
|
|
8
|
+
Project-URL: Homepage, https://github.com/Kavyavegunta04/Cloudnote
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: cryptography>=41.0.0
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: home-page
|
|
18
|
+
Dynamic: requires-python
|
|
19
|
+
|
|
20
|
+
# cloudnoteslib
|
|
21
|
+
|
|
22
|
+
A comprehensive, reusable Python Object-Oriented Programming (OOP) library designed for text note processing, content analysis, security, and exports.
|
|
23
|
+
|
|
24
|
+
## Features & OOP Principles
|
|
25
|
+
- **Encapsulation:** Strongly typed `Note` and `Tag` models with data validation via `@property`.
|
|
26
|
+
- **Abstraction:** Abstract `NoteProcessor` base class guaranteeing unified interfaces.
|
|
27
|
+
- **Inheritance & Polymorphism:** `MarkdownProcessor`, `PlainTextProcessor`, and `RichTextProcessor` implementations sharing the same contract.
|
|
28
|
+
- **Design Patterns:**
|
|
29
|
+
- **Facade Pattern:** `CloudNotesClient` acts as the single point of entry.
|
|
30
|
+
- **Strategy Pattern:** Interchangeable search algorithms (`search.py`).
|
|
31
|
+
- **Template Method Pattern:** Processors share generic steps while overriding specific details.
|
|
32
|
+
- **Singleton Pattern:** Global configuration management.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
```bash
|
|
36
|
+
pip install cloudnoteslib
|
|
37
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
cloudnoteslib/__init__.py,sha256=BI7teGxZtwtvwHsX7zj32YQ_LCv_lOgYIo4Rv70t77k,4845
|
|
2
|
+
cloudnoteslib/config.py,sha256=PwdMoQQYsCPmlQeokcgYAhIH_9UuawEj_Cnbq5EkFMg,739
|
|
3
|
+
cloudnoteslib/exceptions.py,sha256=tzYoc0dIcJqnSLbAXJkDj8p4eA0zhXUB-CyJZOgFFgw,518
|
|
4
|
+
cloudnoteslib/analyzers/__init__.py,sha256=R2_eWlhZga4bKHvyd4_2NdVOwf0KqcoKV2UsuxNoESo,418
|
|
5
|
+
cloudnoteslib/analyzers/content_analyzer.py,sha256=2x79GKkxrian3dO8wuM0h5aWXTBDGptWe6_u_JklQpw,6604
|
|
6
|
+
cloudnoteslib/analyzers/search.py,sha256=f-NWgXW3-KACGv1OJlCB26VWTYGaeAe0YUxpomOImkY,4331
|
|
7
|
+
cloudnoteslib/analyzers/statistics.py,sha256=RJwW5I8MZm2wlW_EtS6VTIYzqbwAH0SFz5O20e1ZBrI,2847
|
|
8
|
+
cloudnoteslib/exporters/__init__.py,sha256=Zytx7kmSeJb-FmE2XIsStcdaaDcxI6fO6xGoHw8t8Lw,306
|
|
9
|
+
cloudnoteslib/exporters/base.py,sha256=ezVSVArNqfY0QRQZEhJE4-VhylZ3SxGLM0JTWZTavKY,765
|
|
10
|
+
cloudnoteslib/exporters/json_exporter.py,sha256=ARErXtoO8e4Op6lj8rWxjZmyoox_ZxkiDEFdLhs2-Gg,486
|
|
11
|
+
cloudnoteslib/exporters/markdown_exporter.py,sha256=R7u-fxLv8SOZ-lDbo8KjQuQF82cgI77zRTimbV290hU,850
|
|
12
|
+
cloudnoteslib/models/__init__.py,sha256=AGCPwqAXvycac6i1IhN1Q1Y59Y2WOZWICtW9_NxYtMY,588
|
|
13
|
+
cloudnoteslib/models/note.py,sha256=TlvZZI1BcVrp9VUDWkH2-vJZhwyYAL2b09eQjpIsNSo,10916
|
|
14
|
+
cloudnoteslib/models/note_collection.py,sha256=u-9FoBwHh-_zXDNRGoQcCRur5oTO3pMCmCgVj62JCEo,7521
|
|
15
|
+
cloudnoteslib/models/tag.py,sha256=R0rx6jmUkNohoMb8DsII7B9Ub8Xk7jvyzg0YHFq__HQ,3705
|
|
16
|
+
cloudnoteslib/processors/__init__.py,sha256=Rpm76ePqP8q9DBHCQU7c4ctB1-kVh0LG2Q_uvl8x_oE,1148
|
|
17
|
+
cloudnoteslib/processors/base.py,sha256=YNYW8IYpMp6QNGbJtrhy3reZkEUExHcvw2Pl20tU0ho,5078
|
|
18
|
+
cloudnoteslib/processors/markdown_processor.py,sha256=V02L8cyR_QiLrSMwNbalZ52a_GFJiVoNsu5AxMKWywY,5106
|
|
19
|
+
cloudnoteslib/processors/plaintext_processor.py,sha256=B97gj5coKT26u7E7IT2QorU5Rw741p0dSzEUmXY2aVE,2979
|
|
20
|
+
cloudnoteslib/processors/richtext_processor.py,sha256=Cn4iMS3xd61cSVJErKCUlJadou_ZP5YrGi2hBCObFdo,3530
|
|
21
|
+
cloudnoteslib/security/__init__.py,sha256=Yy1lk1Ll_ROAqYNqE24kavtVn02hPWX2xbDPrrcUAwY,319
|
|
22
|
+
cloudnoteslib/security/encryptor.py,sha256=nwu5YZm9rfEIdjCObBY-Jl5xngCA3hBtAMjkajvAldE,2521
|
|
23
|
+
cloudnoteslib/security/sanitizer.py,sha256=D-45nL1AfD6XRHMEFo6oToOIwx3geJRDLYZFFgXfOgg,1608
|
|
24
|
+
cloudnoteslib-0.1.0.dist-info/METADATA,sha256=pNVf9tgZNRgNCtg29X2-aPQSsX69V_xcl6-xLuHkTxo,1642
|
|
25
|
+
cloudnoteslib-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
26
|
+
cloudnoteslib-0.1.0.dist-info/top_level.txt,sha256=az-9qrV_u-_rIoUsISe5mQAOlK9pMGddgsS8Jex4zro,14
|
|
27
|
+
cloudnoteslib-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cloudnoteslib
|