Repository: scrapy/xtractmime (language: python)

Issue:
API xtractmime
Created main function and a function for resource metadata(still need to handle multiple content-type headers). 

Should I put all the required flags in a different file "flags.py"?

#1 
mime type split
Splitting `supplied_type` around `";"` 
Added constant variable for the resource header length



Discussion / hints:
Please check these [flags or settings](https://github.com/dveselov/python-libmagic/blob/master/magic/flags.py), maybe helpful later.

Will it be better to use directly [python-magic ](https://pypi.org/project/python-magic/) or  import C header file <magic.h> just as done in python-magic[ here](https://github.com/dveselov/python-libmagic/blob/master/magic/ffi.py)?
> Will it be better to use directly [python-magic ](https://pypi.org/project/python-magic/) or  import C header file <magic.h> just as done in python-magic[ here](https://github.com/dveselov/python-libmagic/blob/master/magic/ffi.py)?

Unless there’s a good reason to use the C file, I would use the Python package API instead.
Please suggest what should be the value for `python-requires` and `classifiers` for `setup.py`
I have added the pattern matching algorithm according to section 6 and added some tests. Please check once

Also, I am thinking of storing the byte tables in a separate file `patterns.py` which can store respective byte-pattern, pattern-mask, and mimetype as a tuple for each type of file.
for e.g, `image_pattern = ((b"\x00\x00\x01\x00",b"\xff\xff\xff\xff","image/x-icon"),  (b"\x00\x00\x02\x00", b"\xff\xff\xff\xff","image/x-icon"),...)`
@Gallaecio Can u please confirm, I think the algo mentioned in section [6.2.1](https://mimesniff.spec.whatwg.org/#signature-for-mp4) for the matching the signature of mp4 file is wrong. 
pt 9 says `while bytes-read < box-size`.  byte-read is 16 and box-size is 4 and it will never enter while loop??

it can be `while box-size < bytes-read`, if its a mistake??
> @Gallaecio Can u please confirm, I think the algo mentioned in section [6.2.1](https://mimesniff.spec.whatwg.org/#signature-for-mp4) for the matching the signature of mp4 file is wrong.
> pt 9 says `while bytes-read < box-size`. byte-read is 16 and box-size is 4 and it will never enter while loop??
> 
> it can be `while box-size < bytes-read`, if its a mistake??

I believe that the algorithm is correct, but you might have misunderstood what _box-size_ means here (e.g. you consider it to be 4?).

The first 4 bytes of the input data in MP4 files seem to indicate the size of some byte sequence they call “box”, which must contain MP4 metadata or something. The algorithm says that you must “Let box-size be the four bytes from sequence[0] to sequence[3], interpreted as a 32-bit unsigned big-endian integer”. So you are supposed to read those 4 bytes as an integer, I suspect using [struct](https://docs.python.org/3/library/struct.html). And then read the input data from the 17th byte, 4 bytes by 4 bytes, up to the box size.
yeah, I misunderstood it 😅, Thanks for the explanation 👍🏼 
> Could you add type hints to the functions that are missing them (even if they're underscored). I'd suggest to add them when first writing the functions, so you don't have to go back later and inspect what the function is doing.

Thanks for suggestion, Type hints will be better for future reference. I will add them to every function


Fix patch:
diff --git a/xtractmime/__init__.py b/xtractmime/__init__.py
index c5cb21d..5b686ec 100644
--- a/xtractmime/__init__.py
+++ b/xtractmime/__init__.py
@@ -1,42 +1,182 @@
 __version__ = "0.0.0"
 from typing import Optional, Set, Tuple
+from xtractmime._patterns import _APACHE_TYPES, WHITESPACE_BYTES
+from xtractmime._utils import (
+    contains_binary,
+    get_archive_mime,
+    get_audio_video_mime,
+    get_extra_mime,
+    get_image_mime,
+    get_text_mime,
+)
+from xtractmime.mimegroups import is_audio_video_mime_type, is_html_mime_type, is_image_mime_type
 
-_APACHE_TYPES = [
-    b"text/plain",
-    b"text/plain; charset=ISO-8859-1",
-    b"text/plain; charset=iso-8859-1",
-    b"text/plain; charset=UTF-8",
-]
-WHITESPACE_BYTES = {b"\t", b"\r", b"\x0c", b"\n", b" "}
+RESOURCE_HEADER_BUFFER_LENGTH = 1445
 
 
-def _is_match_mime_pattern(
-    input_bytes: bytes, byte_pattern: bytes, pattern_mask: bytes, lstrip: Set[bytes] = None
-) -> bool:
+def _find_unknown_mimetype(
+    input_bytes: bytes,
+    sniff_scriptable: bool,
+    extra_types: Optional[Tuple[Tuple[bytes, bytes, Optional[Set[bytes]], bytes], ...]],
+) -> Optional[bytes]:
+    if sniff_scriptable:
+        matched_type = get_text_mime(input_bytes)
+        if matched_type:
+            return matched_type
+
+    matched_type = get_extra_mime(input_bytes, extra_types=extra_types)
+    if matched_type:
+        return matched_type
+
+    matched_type = get_image_mime(input_bytes)
+    if matched_type:
+        return matched_type
+
+    matched_type = get_audio_video_mime(input_bytes)
+    if matched_type:
+        return matched_type
+
+    matched_type = get_archive_mime(input_bytes)
+    if matched_type:
+        return matched_type
+
+    if not contains_binary(input_bytes):
+        return b"text/plain"
+
+    return b"application/octet-stream"
+
+
+def _sniff_mislabled_binary(input_bytes: bytes) -> Optional[bytes]:
+
+    if input_bytes[:2] in (b"\xfe\xff", b"\xff\xfe") or input_bytes[:3] == b"\xef\xbb\xbf":
+        return b"text/plain"
+
+    if not contains_binary(input_bytes):
+        return b"text/plain"
+
+    return b"application/octet-stream"
+
+
+def _sniff_mislabled_feed(input_bytes: bytes, supplied_type: bytes) -> Optional[bytes]:
     input_size = len(input_bytes)
-    pattern_size = len(byte_pattern)
-    mask_size = len(pattern_mask)
+    index = 0
+
+    if input_bytes[:3] == b"\xef\xbb\xbf":
+        index += 3
+
+    while index < input_size:
+        while True:
+            print(input_bytes[index : index + 1])
+            if not input_bytes[index : index + 1]:
+                return supplied_type
+
+            if input_bytes[index : index + 1] == b"<":
+                index += 1
+                break
+
+            if input_bytes[index : index + 1] not in WHITESPACE_BYTES:
+                return supplied_type
+
+            index += 1
+
+        while True:
+            loop_break = False
+            if not input_bytes[index : index + 1]:
+                return supplied_type
+
+            if input_bytes[index : index + 3] == b"!--":
+                index += 3
+                while True:
+                    if not input_bytes[index : index + 1]:
+                        return supplied_type
+
+                    if input_bytes[index : index + 3] == b"-->":
+                        index += 3
+                        loop_break = True
+                        break
+
+                    index += 1
 
-    if pattern_size != mask_size:
-        raise ValueError("pattern's length should match mask's length")
+            if loop_break:
+                break
 
-    if input_size < pattern_size:
-        return False
+            if input_bytes[index : index + 1] == b"!":
+                index += 1
+                while True:
+                    if not input_bytes[index : index + 1]:
+                        return supplied_type
 
-    input_index, pattern_index = 0, 0
+                    if input_bytes[index : index + 1] == b">":
+                        index += 1
+                        loop_break = True
+                        break
 
-    if lstrip:
-        while input_index < input_size and input_bytes[input_index : input_index + 1] in lstrip:
-            input_index += 1
+                    index += 1
 
-    while pattern_index < pattern_size:
-        masked_byte = bytes([input_bytes[input_index] & pattern_mask[pattern_index]])
-        if masked_byte != byte_pattern[pattern_index : pattern_index + 1]:
-            return False
-        input_index += 1
-        pattern_index += 1
+            if loop_break:
+                break
 
-    return True
+            if input_bytes[index : index + 1] == b"?":
+                index += 1
+                while True:
+                    if not input_bytes[index : index + 1]:
+                        return supplied_type
+
+                    if input_bytes[index : index + 2] == b"?>":
+                        index += 2
+                        loop_break = True
+                        break
+
+                    index += 1
+
+            if loop_break:
+                break
+
+            if input_bytes[index : index + 3] == b"rss":
+                return b"application/rss+xml"
+
+            if input_bytes[index : index + 4] == b"feed":
+                return b"application/atom+xml"
+
+            if input_bytes[index : index + 7] == b"rdf:RDF":
+                index += 7
+                while True:
+                    if not input_bytes[index : index + 1]:
+                        return supplied_type
+
+                    if input_bytes[index : index + 24] == b"http://purl.org/rss/1.0/":
+                        index += 24
+                        while True:
+                            if not input_bytes[index : index + 1]:
+                                return supplied_type
+
+                            if (
+                                input_bytes[index : index + 43]
+                                == b"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+                            ):
+                                return b"application/rss+xml"
+
+                            index += 1
+
+                    if (
+                        input_bytes[index : index + 43]
+                        == b"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+                    ):
+                        index += 43
+                        while True:
+                            if not input_bytes[index : index + 1]:
+                                return supplied_type
+
+                            if input_bytes[index : index + 24] == b"http://purl.org/rss/1.0/":
+                                return b"application/rss+xml"
+
+                            index += 1
+
+                    index += 1
+
+            return supplied_type
+
+    return supplied_type
 
 
 def extract_mime(
@@ -46,6 +186,38 @@ def extract_mime(
     http_origin: bool = True,
     no_sniff: bool = False,
     extra_types: Optional[Tuple[Tuple[bytes, bytes, Optional[Set[bytes]], bytes], ...]] = None,
+    supported_types: Set[bytes] = None,
 ) -> Optional[bytes]:
+    extra_types = extra_types or tuple()
+    supplied_type = content_types[-1] if content_types else b""
+    supplied_type = supplied_type.split(b";")[0].strip().lower()
+    check_for_apache = http_origin and supplied_type in _APACHE_TYPES
+    resource_header = memoryview(body)[:RESOURCE_HEADER_BUFFER_LENGTH]
+
+    if supplied_type in (b"", b"unknown/unknown", b"application/unknown", b"*/*"):
+        return _find_unknown_mimetype(resource_header, not no_sniff, extra_types)
+
+    if no_sniff:
+        return supplied_type
+
+    if check_for_apache:
+        return _sniff_mislabled_binary(resource_header)
+
+    if supplied_type.endswith(b"+xml") or supplied_type in {b"text/xml", b"application/xml"}:
+        return supplied_type
+
+    if is_html_mime_type(supplied_type):
+        return _sniff_mislabled_feed(resource_header, supplied_type)
+
+    if supported_types:
+        if is_image_mime_type(supplied_type):
+            matched_type = get_image_mime(resource_header)
+            if matched_type in supported_types:
+                return matched_type
+
+        if is_audio_video_mime_type(supplied_type):
+            matched_type = get_audio_video_mime(resource_header)
+            if matched_type in supported_types:
+                return matched_type
 
-    return b"mimetype"
+    return supplied_type
diff --git a/xtractmime/_patterns.py b/xtractmime/_patterns.py
index d6fc804..e0b2e05 100644
--- a/xtractmime/_patterns.py
+++ b/xtractmime/_patterns.py
@@ -1,3 +1,83 @@
+from typing import Optional, Set, Tuple
+
+
+#: Section 3
+#: https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#terminology  # noqa: E501
+BINARY_BYTES = (
+    b"\x00",
+    b"\x01",
+    b"\x02",
+    b"\x03",
+    b"\x04",
+    b"\x05",
+    b"\x06",
+    b"\x07",
+    b"\x08",
+    b"\x0b",
+    b"\x0e",
+    b"\x0f",
+    b"\x10",
+    b"\x11",
+    b"\x12",
+    b"\x13",
+    b"\x14",
+    b"\x15",
+    b"\x16",
+    b"\x17",
+    b"\x18",
+    b"\x19",
+    b"\x1a",
+    b"\x1c",
+    b"\x1d",
+    b"\x1e",
+    b"\x1f",
+)
+WHITESPACE_BYTES = {b"\t", b"\r", b"\x0c", b"\n", b" "}
+
+#: Section 4.6
+#: https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#mime-type-groups  # noqa: E501
+FONT_TYPES = [
+    b"application/font-cff",
+    b"application/font-off",
+    b"application/font-sfnt",
+    b"application/font-ttf",
+    b"application/font-woff",
+    b"application/vnd.ms-fontobject",
+    b"application/vnd.ms-opentype",
+]
+ARCHIVE_TYPES = [
+    b"application/x-rar-compressed",
+    b"application/zip",
+    b"application/x-gzip",
+]
+JAVASCRIPT_TYPES = [
+    b"application/ecmascript",
+    b"application/javascript",
+    b"application/x-ecmascript",
+    b"application/x-javascript",
+    b"text/ecmascript",
+    b"text/javascript",
+    b"text/javascript1.0",
+    b"text/javascript1.1",
+    b"text/javascript1.2",
+    b"text/javascript1.3",
+    b"text/javascript1.4",
+    b"text/javascript1.5",
+    b"text/jscript",
+    b"text/livescript",
+    b"text/x-ecmascript",
+    b"text/x-javascript",
+]
+
+#: Section 5.1, step 2
+#: https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#interpreting-the-resource-metadata  # noqa: E501
+_APACHE_TYPES = [
+    b"text/plain",
+    b"text/plain; charset=ISO-8859-1",
+    b"text/plain; charset=iso-8859-1",
+    b"text/plain; charset=UTF-8",
+]
+
 #: Section 6.1, step 1
 #: https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#matching-an-image-type-pattern  # noqa: E501
 IMAGE_PATTERNS = (
@@ -72,3 +152,46 @@
     (b"PK\x03\x04", b"\xff\xff\xff\xff", None, b"application/zip",),
     (b"Rar \x1a\x07\x00", b"\xff\xff\xff\xff\xff\xff\xff", None, b"application/x-rar-compressed",),
 )
+
+#: Section 7.1, step 1
+#: https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#identifying-a-resource-with-an-unknown-mime-type  # noqa: E501
+TEXT_PATTERNS = tuple(
+    (prefix + suffix, mask, WHITESPACE_BYTES, b"text/html")
+    for prefix, mask, in (
+        (b"<!DOCTYPE HTML", b"\xff\xff\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xff\xdf\xdf\xdf\xdf\xff"),
+        (b"<HTML", b"\xff\xdf\xdf\xdf\xdf\xff"),
+        (b"<HEAD", b"\xff\xdf\xdf\xdf\xdf\xff"),
+        (b"<SCRIPT", b"\xff\xdf\xdf\xdf\xdf\xdf\xdf\xff"),
+        (b"<IFRAME", b"\xff\xdf\xdf\xdf\xdf\xdf\xdf\xff"),
+        (b"<H1", b"\xff\xdf\xff\xff"),
+        (b"<DIV", b"\xff\xdf\xdf\xdf\xff"),
+        (b"<FONT", b"\xff\xdf\xdf\xdf\xdf\xff"),
+        (b"<TABLE", b"\xff\xdf\xdf\xdf\xdf\xdf\xff"),
+        (b"<A", b"\xff\xdf\xff"),
+        (b"<STYLE", b"\xff\xdf\xdf\xdf\xdf\xdf\xff"),
+        (b"<TITLE", b"\xff\xdf\xdf\xdf\xdf\xdf\xff"),
+        (b"<B", b"\xff\xdf\xff"),
+        (b"<BODY", b"\xff\xdf\xdf\xdf\xdf\xff"),
+        (b"<BR", b"\xff\xdf\xdf\xff"),
+        (b"<P", b"\xff\xdf\xff"),
+        (b"<!--", b"\xff\xff\xff\xff\xff"),
+    )
+    for suffix in (b"\x20", b"\x3E")
+) + (
+    (b"<?xml", b"\xff\xff\xff\xff\xff", WHITESPACE_BYTES, b"text/xml"),
+    (b"%PDF-", b"\xff\xff\xff\xff\xff", None, b"application/pdf"),
+)
+
+#: Section 7.1, step 2
+#: https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#identifying-a-resource-with-an-unknown-mime-type  # noqa: E501
+EXTRA_PATTERNS: Tuple[Tuple[bytes, bytes, Optional[Set[bytes]], bytes], ...] = (
+    (
+        b"%!PS-Adobe-",
+        b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+        None,
+        b"application/postscript",
+    ),
+    (b"\xfe\xff\x00\x00", b"\xff\xff\x00\x00", None, b"text/plain"),
+    (b"\xff\xfe\x00\x00", b"\xff\xff\x00\x00", None, b"text/plain"),
+    (b"\xef\xbb\xbf\x00", b"\xff\xff\xff\x00", None, b"text/plain"),
+)
diff --git a/xtractmime/_utils.py b/xtractmime/_utils.py
index 58ce912..e601915 100644
--- a/xtractmime/_utils.py
+++ b/xtractmime/_utils.py
@@ -1,12 +1,14 @@
 from struct import unpack
-from typing import Optional, Tuple
+from typing import Optional, Set, Tuple
 
-from xtractmime import _is_match_mime_pattern
 from xtractmime._patterns import (
     ARCHIVE_PATTERNS,
     AUDIO_VIDEO_PATTERNS,
+    BINARY_BYTES,
+    EXTRA_PATTERNS,
     FONT_PATTERNS,
     IMAGE_PATTERNS,
+    TEXT_PATTERNS,
 )
 
 SAMPLE_RATES = (44100, 48000, 32000)
@@ -46,6 +48,35 @@
 )
 
 
+def is_match_mime_pattern(
+    input_bytes: bytes, byte_pattern: bytes, pattern_mask: bytes, lstrip: Set[bytes] = None
+) -> bool:
+    input_size = len(input_bytes)
+    pattern_size = len(byte_pattern)
+    mask_size = len(pattern_mask)
+
+    if pattern_size != mask_size:
+        raise ValueError("pattern's length should match mask's length")
+
+    if input_size < pattern_size:
+        return False
+
+    input_index, pattern_index = 0, 0
+
+    if lstrip:
+        while input_index < input_size and input_bytes[input_index : input_index + 1] in lstrip:
+            input_index += 1
+
+    while pattern_index < pattern_size:
+        masked_byte = bytes([input_bytes[input_index] & pattern_mask[pattern_index]])
+        if masked_byte != byte_pattern[pattern_index : pattern_index + 1]:
+            return False
+        input_index += 1
+        pattern_index += 1
+
+    return True
+
+
 def is_mp4_signature(input_bytes: bytes) -> bool:
     input_size = len(input_bytes)
     if input_size < 12:
@@ -64,7 +95,7 @@ def is_mp4_signature(input_bytes: bytes) -> bool:
 
     bytes_read = 16
     while bytes_read < box_size:
-        if input_bytes[bytes_read : bytes_read + 3] == b"mp4":  # noqa: E203
+        if input_bytes[bytes_read : bytes_read + 3] == b"mp4":
             return True
         bytes_read += 4
 
@@ -112,7 +143,7 @@ def is_webm_signature(input_bytes: bytes) -> bool:
 
     limit = min(input_size, 38)
     while index < limit:
-        if input_bytes[index : index + 2] == b"B\x82":  # noqa: E203
+        if input_bytes[index : index + 2] == b"B\x82":
             index += 2
 
             if index >= input_size:
@@ -124,7 +155,7 @@ def is_webm_signature(input_bytes: bytes) -> bool:
             if index >= input_size - 4:
                 break
 
-            if input_bytes[index : index + 4] == b"webm":  # noqa: E203
+            if input_bytes[index : index + 4] == b"webm":
                 return True
         index += 1
 
@@ -136,7 +167,7 @@ def match_mp3_header(input_bytes: bytes, input_size: int, index: int) -> bool:
         return False
 
     if (
-        input_bytes[index : index + 1] != b"\xff"  # noqa: E203
+        input_bytes[index : index + 1] != b"\xff"
         or bytes([input_bytes[index + 1] & 224]) != b"\xe0"
     ):
         return False
@@ -231,17 +262,17 @@ def is_mp3_non_ID3_signature(input_bytes: bytes) -> bool:
         return False
 
 
-def is_image(input_bytes: bytes) -> Optional[bytes]:
+def get_image_mime(input_bytes: bytes) -> Optional[bytes]:
     for pattern in IMAGE_PATTERNS:
-        if _is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
+        if is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
             return pattern[3]
 
     return None
 
 
-def is_audio_video(input_bytes: bytes) -> Optional[bytes]:
+def get_audio_video_mime(input_bytes: bytes) -> Optional[bytes]:
     for pattern in AUDIO_VIDEO_PATTERNS:
-        if _is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
+        if is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
             return pattern[3]
 
     if is_mp4_signature(input_bytes):
@@ -256,17 +287,49 @@ def is_audio_video(input_bytes: bytes) -> Optional[bytes]:
     return None
 
 
-def is_font(input_bytes: bytes) -> Optional[bytes]:
+def get_font_mime(input_bytes: bytes) -> Optional[bytes]:
     for pattern in FONT_PATTERNS:
-        if _is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
+        if is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
             return pattern[3]
 
     return None
 
 
-def is_archive(input_bytes: bytes) -> Optional[bytes]:
+def get_archive_mime(input_bytes: bytes) -> Optional[bytes]:
     for pattern in ARCHIVE_PATTERNS:
-        if _is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
+        if is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
             return pattern[3]
 
     return None
+
+
+def get_text_mime(input_bytes: bytes) -> Optional[bytes]:
+    for pattern in TEXT_PATTERNS:
+        if is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
+            return pattern[3]
+
+    return None
+
+
+def get_extra_mime(
+    input_bytes: bytes,
+    extra_types: Optional[Tuple[Tuple[bytes, bytes, Optional[Set[bytes]], bytes], ...]],
+) -> Optional[bytes]:
+    for pattern in EXTRA_PATTERNS:
+        if is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
+            return pattern[3]
+
+    if extra_types:
+        for pattern in extra_types:
+            if is_match_mime_pattern(input_bytes, pattern[0], pattern[1], pattern[2]):
+                return pattern[3]
+
+    return None
+
+
+def contains_binary(input_bytes: bytes) -> bool:
+    for i in input_bytes:
+        if bytes([i]) in BINARY_BYTES:
+            return True
+
+    return False
diff --git a/xtractmime/mimegroups.py b/xtractmime/mimegroups.py
new file mode 100644
index 0000000..59e5f8e
--- /dev/null
+++ b/xtractmime/mimegroups.py
@@ -0,0 +1,52 @@
+from xtractmime._patterns import (
+    ARCHIVE_TYPES,
+    FONT_TYPES,
+    JAVASCRIPT_TYPES,
+)
+
+
+def is_image_mime_type(mime_type: bytes) -> bool:
+    return mime_type.startswith(b"image/")
+
+
+def is_audio_video_mime_type(mime_type: bytes) -> bool:
+    video_types = (b"audio/", b"video/")
+    return mime_type.startswith(video_types) or mime_type == b"application/ogg"
+
+
+def is_font_mime_type(mime_type: bytes) -> bool:
+    return mime_type.startswith(b"font/") or mime_type in FONT_TYPES
+
+
+def is_zip_mime_type(mime_type: bytes) -> bool:
+    return mime_type.endswith(b"+zip") or mime_type == b"application/zip"
+
+
+def is_archive_mime_type(mime_type: bytes) -> bool:
+    return mime_type in ARCHIVE_TYPES
+
+
+def is_xml_mime_type(mime_type: bytes) -> bool:
+    return mime_type.endswith(b"+xml") or mime_type in (b"text/xml", b"application/xml")
+
+
+def is_html_mime_type(mime_type: bytes) -> bool:
+    return mime_type == b"text/html"
+
+
+def is_scriptable_mime_type(mime_type: bytes) -> bool:
+    if is_xml_mime_type(mime_type):
+        return True
+
+    if is_html_mime_type(mime_type):
+        return True
+
+    return mime_type == b"application/pdf"
+
+
+def is_javascript_mime_type(mime_type: bytes) -> bool:
+    return mime_type.lower() in JAVASCRIPT_TYPES
+
+
+def is_json_mime_type(mime_type: bytes) -> bool:
+    return mime_type.endswith(b"+json") or mime_type in (b"application/json", b"text/json")


Test patch:
diff --git a/tests/files/foo.exe b/tests/files/foo.exe
new file mode 100644
index 0000000..a795db9
Binary files /dev/null and b/tests/files/foo.exe differ
diff --git a/tests/files/foo.html b/tests/files/foo.html
new file mode 100644
index 0000000..dfd9d56
--- /dev/null
+++ b/tests/files/foo.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<head>
+<title>A Sample HTML Document (Test File)</title>
+<meta charset="utf-8">
+<meta name="description" content="A blank HTML document for testing purposes.">
+<meta name="author" content="Six Revisions">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<link rel="icon" href="http://sixrevisions.com/favicon.ico" type="image/x-icon" />
+</head>
+<body>
+  
+<h1>A Sample HTML Document (Test File)</h1>
+<p>A blank HTML document for testing purposes.</p>
+<p><a href="../html5download-demo.html">Go back to the demo</a></p>
+<p><a href="http://sixrevisions.com/html5/download-attribute/">Read the HTML5 download attribute guide</a></p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/tests/files/foo.ps b/tests/files/foo.ps
new file mode 100644
index 0000000..d3e1d0e
Binary files /dev/null and b/tests/files/foo.ps differ
diff --git a/tests/files/foo.txt b/tests/files/foo.txt
new file mode 100644
index 0000000..0639b98
--- /dev/null
+++ b/tests/files/foo.txt
@@ -0,0 +1,21 @@
+Quod equidem non reprehendo;
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quibus natura iure responderit non esse verum aliunde finem beate vivendi, a se principia rei gerendae peti; Quae enim adhuc protulisti, popularia sunt, ego autem a te elegantiora desidero. Duo Reges: constructio interrete. Tum Lucius: Mihi vero ista valde probata sunt, quod item fratri puto. Bestiarum vero nullum iudicium puto. Nihil enim iam habes, quod ad corpus referas; Deinde prima illa, quae in congressu solemus: Quid tu, inquit, huc? Et homini, qui ceteris animantibus plurimum praestat, praecipue a natura nihil datum esse dicemus?
+
+Iam id ipsum absurdum, maximum malum neglegi. Quod ea non occurrentia fingunt, vincunt Aristonem; Atqui perspicuum est hominem e corpore animoque constare, cum primae sint animi partes, secundae corporis. Fieri, inquam, Triari, nullo pacto potest, ut non dicas, quid non probes eius, a quo dissentias. Equidem e Cn. An dubium est, quin virtus ita maximam partem optineat in rebus humanis, ut reliquas obruat?
+
+Quis istum dolorem timet?
+Summus dolor plures dies manere non potest? Dicet pro me ipsa virtus nec dubitabit isti vestro beato M. Tubulum fuisse, qua illum, cuius is condemnatus est rogatione, P. Quod si ita sit, cur opera philosophiae sit danda nescio.
+
+Ex eorum enim scriptis et institutis cum omnis doctrina liberalis, omnis historia.
+Quod si ita est, sequitur id ipsum, quod te velle video, omnes semper beatos esse sapientes. Cum enim fertur quasi torrens oratio, quamvis multa cuiusque modi rapiat, nihil tamen teneas, nihil apprehendas, nusquam orationem rapidam coerceas. Ita redarguitur ipse a sese, convincunturque scripta eius probitate ipsius ac moribus. At quanta conantur! Mundum hunc omnem oppidum esse nostrum! Incendi igitur eos, qui audiunt, vides. Vide, ne magis, inquam, tuum fuerit, cum re idem tibi, quod mihi, videretur, non nova te rebus nomina inponere. Qui-vere falsone, quaerere mittimus-dicitur oculis se privasse; Si ista mala sunt, in quae potest incidere sapiens, sapientem esse non esse ad beate vivendum satis. At vero si ad vitem sensus accesserit, ut appetitum quendam habeat et per se ipsa moveatur, quid facturam putas?
+
+Quem si tenueris, non modo meum Ciceronem, sed etiam me ipsum abducas licebit.
+Stulti autem malorum memoria torquentur, sapientes bona praeterita grata recordatione renovata delectant.
+Esse enim quam vellet iniquus iustus poterat inpune.
+Quae autem natura suae primae institutionis oblita est?
+Verum tamen cum de rebus grandioribus dicas, ipsae res verba rapiunt;
+Hoc est non modo cor non habere, sed ne palatum quidem.
+Voluptatem cum summum bonum diceret, primum in eo ipso parum vidit, deinde hoc quoque alienum; Sed tu istuc dixti bene Latine, parum plane. Nam haec ipsa mihi erunt in promptu, quae modo audivi, nec ante aggrediar, quam te ab istis, quos dicis, instructum videro. Fatebuntur Stoici haec omnia dicta esse praeclare, neque eam causam Zenoni desciscendi fuisse. Non autem hoc: igitur ne illud quidem. Ratio quidem vestra sic cogit. Cum audissem Antiochum, Brute, ut solebam, cum M. An quod ita callida est, ut optime possit architectari voluptates?
+
+Idemne, quod iucunde?
+Haec mihi videtur delicatior, ut ita dicam, molliorque ratio, quam virtutis vis gravitasque postulat. Sed quoniam et advesperascit et mihi ad villam revertendum est, nunc quidem hactenus; Cuius ad naturam apta ratio vera illa et summa lex a philosophis dicitur. Neque solum ea communia, verum etiam paria esse dixerunt. Sed nunc, quod agimus; A mene tu?
\ No newline at end of file
diff --git a/tests/files/foo.xml b/tests/files/foo.xml
new file mode 100644
index 0000000..2bcec7c
--- /dev/null
+++ b/tests/files/foo.xml
@@ -0,0 +1,1598 @@
+﻿<?xml version="1.0" encoding="UTF-8" ?>
+<root>
+	<0>
+		<id>4051</id>
+		<name>manoj</name>
+		<email>manoj@gmail.com</email>
+		<password>Test@123</password>
+		<about />
+		<token>7f471974-ae46-4ac0-a882-1980c300c4d6</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/9b291404-bc2e-4806-88c5-08d29e65a5ad.png</profilePicture>
+		<coverPicture>Images/44af97d9-b8c9-4ec1-a099-010671db25b7.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2020-01-01T11:13:27.1107739</createdAt>
+		<updatedAt>2020-01-02T09:16:49.284864</updatedAt>
+		<livelng>77.389849</livelng>
+		<livelat>28.6282231</livelat>
+		<liveLocation>Unnamed Road, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India</liveLocation>
+		<creditBalance>127</creditBalance>
+		<myCash>0</myCash>
+	</0>
+	<1>
+		<id>4050</id>
+		<name>pankaj</name>
+		<email>p1@gmail.com</email>
+		<password>Test@123</password>
+		<about />
+		<token>e269eeef-1de1-4438-885a-e30a9ad26106</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2020-01-01T07:39:34.1618239</createdAt>
+		<updatedAt>2020-01-01T07:39:34.161824</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</1>
+	<2>
+		<id>3050</id>
+		<name>Neeraj1993</name>
+		<email>neeraj.singh@adequateinfosoft.com</email>
+		<password>286956</password>
+		<about />
+		<token>562c2fb5-6799-4b51-8733-a60564c96adc</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-27T10:16:05.6578091</createdAt>
+		<updatedAt>2019-12-27T10:22:30.8416992</updatedAt>
+		<livelng>77.389849</livelng>
+		<livelat>28.6282231</livelat>
+		<liveLocation>Unnamed Road, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India</liveLocation>
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</2>
+	<3>
+		<id>3049</id>
+		<name>Sophia</name>
+		<email>sophia@gmail.com</email>
+		<password>Test@123</password>
+		<about>Yo</about>
+		<token>f3bc9393-ad13-41a2-a69b-b607a42d829f</token>
+		<country />
+		<location>18302 Lorance Trail, Little Rock, AR 72206, USA</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-19T11:54:19</dob>
+		<gender>2</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T07:36:22.3481221</createdAt>
+		<updatedAt>2019-12-26T07:36:22.3481222</updatedAt>
+		<livelng>77.3674236</livelng>
+		<livelat>28.6260665</livelat>
+		<liveLocation>35, Block A, Industrial Area, Sector 62, Noida, Uttar Pradesh 201309, India</liveLocation>
+		<creditBalance>36</creditBalance>
+		<myCash>0</myCash>
+	</3>
+	<4>
+		<id>3048</id>
+		<name>Raju Prasad</name>
+		<email>raju.nsit@gmail.com</email>
+		<password>Raju@1234</password>
+		<about>Don't Quit Your Day Dream</about>
+		<token>b3eda104-0771-4804-8be2-0e6d7c16412d</token>
+		<country />
+		<location>Karbala Rd, Block G, Sector 5, Dakshinpuri, New Delhi, Delhi 110044, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-01T01:55:34</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/291d0a5a-c8c2-45ac-b79f-cc04e0c6f31e.png</profilePicture>
+		<coverPicture>Images/7aa45b5d-3adf-4da0-a0fe-694f069e9049.png</coverPicture>
+		<enablefollowme>true</enablefollowme>
+		<sendmenotifications>true</sendmenotifications>
+		<sendTextmessages>true</sendTextmessages>
+		<enabletagging>true</enabletagging>
+		<createdAt>2019-12-26T07:17:08.3460039</createdAt>
+		<updatedAt>2019-12-26T14:27:00.4327446</updatedAt>
+		<livelng>77.3674236</livelng>
+		<livelat>28.6260665</livelat>
+		<liveLocation>35, Block A, Industrial Area, Sector 62, Noida, Uttar Pradesh 201309, India</liveLocation>
+		<creditBalance>5</creditBalance>
+		<myCash>0</myCash>
+	</4>
+	<5>
+		<id>3047</id>
+		<name>Ankiish Thapliyal</name>
+		<email>thapliyalankiish958@gmail.com</email>
+		<password>Test@1234</password>
+		<about>I failed many opportunities may times but I am the one who tries again and again every time with a smile.</about>
+		<token>caf070df-d2c2-4e99-ba06-9482ef5eb7ba</token>
+		<country />
+		<location>Dehradun</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-31T03:02:48</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/0da0ca00-cfaf-41e8-ab39-cbff55ec64b3.png</profilePicture>
+		<coverPicture>Images/088fd182-2a2d-4a72-946d-a90d047e4557.png</coverPicture>
+		<enablefollowme>true</enablefollowme>
+		<sendmenotifications>true</sendmenotifications>
+		<sendTextmessages>true</sendTextmessages>
+		<enabletagging>true</enabletagging>
+		<createdAt>2019-12-26T07:13:01.9262534</createdAt>
+		<updatedAt>2019-12-30T11:11:00.4082038</updatedAt>
+		<livelng>77.3790036</livelng>
+		<livelat>28.630186199999997</livelat>
+		<liveLocation>Suite No. 203 H - 15 Rise tower, Sector 63, H Block, Sector 62, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>167</creditBalance>
+		<myCash>0</myCash>
+	</5>
+	<6>
+		<id>3046</id>
+		<name>Aryan Thapliyal</name>
+		<email>ashithewarrior@gmail.com</email>
+		<password>Test@1234</password>
+		<about>Testing is required for an effective performance of software application or product. It's important to ensure that the application should not result into any failures because it can be very expensive in the future or in the later stages of the development</about>
+		<token>c8cb5636-cd01-4133-adac-360cecc710af</token>
+		<country />
+		<location>Dehradun</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-01T05:20:43</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/8a8a93f3-5696-4387-84e5-ac632cc85ec1.png</profilePicture>
+		<coverPicture>Images/cdaf5fa5-e786-49a6-a1d5-453b532f3d8d.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T07:10:53.2318238</createdAt>
+		<updatedAt>2019-12-30T05:32:04.0700419</updatedAt>
+		<livelng>77.37901219999999</livelng>
+		<livelat>28.630237299999997</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>160</creditBalance>
+		<myCash>0</myCash>
+	</6>
+	<7>
+		<id>3045</id>
+		<name>shivam</name>
+		<email>shivam@gmail.com</email>
+		<password>Shivam@123</password>
+		<about />
+		<token>59b6f0af-fc25-4a6b-b865-5fb29023c6df</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/da45be05-a363-4b27-bdf7-1a8c9a912ae1.png</profilePicture>
+		<coverPicture>Images/4885d2c3-3c86-4ed7-b28b-e1900d618724.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T07:01:24.5014557</createdAt>
+		<updatedAt>2019-12-26T07:02:16.9663295</updatedAt>
+		<livelng>77.3674236</livelng>
+		<livelat>28.6260665</livelat>
+		<liveLocation>35, Block A, Industrial Area, Sector 62, Noida, Uttar Pradesh 201309, India</liveLocation>
+		<creditBalance>11</creditBalance>
+		<myCash>0</myCash>
+	</7>
+	<8>
+		<id>3044</id>
+		<name>Navya Upadhyay</name>
+		<email>navya.adequate@gmail.com</email>
+		<password>navya2123</password>
+		<about />
+		<token>0362f1b5-80be-4dff-bd40-c236c79561eb</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T06:53:22.1076016</createdAt>
+		<updatedAt>2019-12-26T06:53:22.1076017</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>5</creditBalance>
+		<myCash>0</myCash>
+	</8>
+	<9>
+		<id>3043</id>
+		<name>Ritu singh</name>
+		<email>ritusinghadequate@gmail.com</email>
+		<password>ritusingh1234</password>
+		<about />
+		<token>a268517f-960a-418a-9c89-48708372702d</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T06:53:10.2343196</createdAt>
+		<updatedAt>2019-12-26T06:53:10.2343197</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>5</creditBalance>
+		<myCash>0</myCash>
+	</9>
+	<10>
+		<id>3042</id>
+		<name>faiz</name>
+		<email>faizadequate@gmail.com</email>
+		<password>Test@1234</password>
+		<about>I am who I am. Your approval is not needed.</about>
+		<token>33dd5829-0a01-4b3b-80d3-1a63a75b3436</token>
+		<country />
+		<location>New Delhi</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-12T12:10:02</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/80cdd447-4a3a-483f-b222-86989cc3d37e.png</profilePicture>
+		<coverPicture>Images/1717f4f1-47e1-4f5f-9129-72d7933aa15a.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T06:30:58.6524884</createdAt>
+		<updatedAt>2019-12-30T06:57:19.58494</updatedAt>
+		<livelng>77.379012</livelng>
+		<livelat>28.630232</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>38</creditBalance>
+		<myCash>0</myCash>
+	</10>
+	<11>
+		<id>3041</id>
+		<name>Martin Wilson</name>
+		<email>ravencomputer667@gmail.com</email>
+		<password>martin@123</password>
+		<about>Travelers, </about>
+		<token>18ceb759-241c-43d3-a9eb-5344ea2ef1d9</token>
+		<country />
+		<location>Moorgate Station (Stop N), London EC2Y 5EJ, UK</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-11T12:29:13</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/023d1a36-ef5e-4248-a9a1-900069fe3f28.png</profilePicture>
+		<coverPicture>Images/0e773003-964f-42c8-b591-b33fa0563a85.png</coverPicture>
+		<enablefollowme>true</enablefollowme>
+		<sendmenotifications>true</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T06:22:36.1180762</createdAt>
+		<updatedAt>2019-12-26T06:29:14.6591852</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>18</creditBalance>
+		<myCash>0</myCash>
+	</11>
+	<12>
+		<id>3040</id>
+		<name>Shweta Singh</name>
+		<email>amelia.claire.hi@gmail.com</email>
+		<password>Test@1234</password>
+		<about>What others think of me is none of my business.I’m the most awesome person I know.</about>
+		<token>e32b4e12-18f3-4fd0-9a3d-2021d8381dff</token>
+		<country />
+		<location>India - Pakistan Border Rd, Bakhasar, Rajasthan 344706, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-02T11:47:56</dob>
+		<gender>2</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/085985b6-0662-4e1d-b5b4-20016d31514f.png</profilePicture>
+		<coverPicture>Images/7efb014a-f551-4702-b5af-2fe11cca2a88.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T06:20:51.0353245</createdAt>
+		<updatedAt>2019-12-30T06:24:31.9803752</updatedAt>
+		<livelng>77.3790045</livelng>
+		<livelat>28.630205699999998</livelat>
+		<liveLocation>Suite No. 203 H - 15 Rise tower, Sector 63, H Block, Sector 62, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>77</creditBalance>
+		<myCash>0</myCash>
+	</12>
+	<13>
+		<id>3039</id>
+		<name>jagjit</name>
+		<email>jagjit.singh.adequate.36@gmail.com</email>
+		<password>Test@1234</password>
+		<about>Take a chance and live life to the fullest. When we are at our most daring is when we feel the most fulfillment.</about>
+		<token>1e150816-7075-4d6d-b3d6-eb1c0e415e61</token>
+		<country />
+		<location>Delhi - Meerut Expy, Nai Basti Dundahera, Ghaziabad, Uttar Pradesh 201009, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2012-01-03T12:00:00</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/fe49d058-de88-4805-8e2d-0c002b090d15.png</profilePicture>
+		<coverPicture>Images/a3dc98f7-0754-4616-bbc0-0395e19bb899.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T06:20:32.873132</createdAt>
+		<updatedAt>2020-01-02T06:29:36.6383214</updatedAt>
+		<livelng>77.3790121</livelng>
+		<livelat>28.630189800000004</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>32</creditBalance>
+		<myCash>0</myCash>
+	</13>
+	<14>
+		<id>3038</id>
+		<name>Ashi 123</name>
+		<email>ashi123@gmail.com</email>
+		<password>Test@1234</password>
+		<about />
+		<token>61a43ad3-02b3-4431-8c1b-1d29933147e1</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-26T05:30:27.4225101</createdAt>
+		<updatedAt>2019-12-26T05:30:27.4225102</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</14>
+	<15>
+		<id>3037</id>
+		<name>shivamvermaa4</name>
+		<email>shivam.vemaa4@gmail.com</email>
+		<password>Shivam@123</password>
+		<about />
+		<token>97534ce9-5386-4b92-9741-fc1860bbcd1a</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-24T11:58:30.3613651</createdAt>
+		<updatedAt>2019-12-24T11:58:30.3613651</updatedAt>
+		<livelng>77.389849</livelng>
+		<livelat>28.6282231</livelat>
+		<liveLocation>Unnamed Road, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India</liveLocation>
+		<creditBalance>10</creditBalance>
+		<myCash>0</myCash>
+	</15>
+	<16>
+		<id>3036</id>
+		<name>Sophia</name>
+		<email>n2@gmail.com</email>
+		<password>Test@123</password>
+		<about>WE</about>
+		<token>1ebfb0ac-7d98-43fb-ba41-0e40091c6071</token>
+		<country />
+		<location>Saint-Louis-Strasse 3, 4056 Basel, Switzerland</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-18T03:18:47</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/f3f7694a-0de4-4598-b141-39ad550d1912.png</profilePicture>
+		<coverPicture>Images/ae9868ef-f87c-4cc2-8429-5cb46dba6cbd.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-24T11:36:36.1739424</createdAt>
+		<updatedAt>2019-12-26T09:48:57.2586835</updatedAt>
+		<livelng>77.389849</livelng>
+		<livelat>28.6282231</livelat>
+		<liveLocation>Unnamed Road, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India</liveLocation>
+		<creditBalance>45</creditBalance>
+		<myCash>0</myCash>
+	</16>
+	<17>
+		<id>3035</id>
+		<name>n1</name>
+		<email>n1@gmail.com</email>
+		<password>Test@123</password>
+		<about>An ordinary Bharitya</about>
+		<token>c40422ef-27ac-4e40-adf5-87403143dc99</token>
+		<country />
+		<location>451 DERA THAKRAN HARIDWAR ROAD MAHANT BALBIR SINGH MARKET, Haridwar Road, Haridwar Rd, Chauda Bigha, Rishikesh, Uttarakhand 249201, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-17T12:33:26</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/4e60754a-e8a7-4db7-b266-f28b2bcf00ae.png</profilePicture>
+		<coverPicture>Images/9ca02453-ecfe-4852-9124-aa0595a9e692.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-24T11:36:03.4815197</createdAt>
+		<updatedAt>2020-01-02T07:20:34.2742376</updatedAt>
+		<livelng>77.389849</livelng>
+		<livelat>28.6282231</livelat>
+		<liveLocation>Unnamed Road, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India</liveLocation>
+		<creditBalance>187</creditBalance>
+		<myCash>0</myCash>
+	</17>
+	<18>
+		<id>3034</id>
+		<name>neha</name>
+		<email>neha@gmail.com</email>
+		<password>Test@123</password>
+		<about />
+		<token>6aaaa999-8e14-40ca-b043-087624c48fd1</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-24T10:35:00.1292083</createdAt>
+		<updatedAt>2019-12-24T10:35:00.1292083</updatedAt>
+		<livelng>77.3674236</livelng>
+		<livelat>28.6260665</livelat>
+		<liveLocation>35, Block A, Industrial Area, Sector 62, Noida, Uttar Pradesh 201309, India</liveLocation>
+		<creditBalance>53</creditBalance>
+		<myCash>0</myCash>
+	</18>
+	<19>
+		<id>3033</id>
+		<name>sanjay</name>
+		<email>sanjay@gmail.com</email>
+		<password>Test@123</password>
+		<about />
+		<token>c9989beb-685a-41d7-b6de-77dd208979df</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-24T08:16:23.8466413</createdAt>
+		<updatedAt>2019-12-24T08:16:23.8466414</updatedAt>
+		<livelng>77.3674236</livelng>
+		<livelat>28.6260665</livelat>
+		<liveLocation>35, Block A, Industrial Area, Sector 62, Noida, Uttar Pradesh 201309, India</liveLocation>
+		<creditBalance>81</creditBalance>
+		<myCash>0</myCash>
+	</19>
+	<20>
+		<id>3032</id>
+		<name>Akku2</name>
+		<email>akku2@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>12ac2112-c7b3-47d3-8d48-e839a1ce3955</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-24T07:30:32.9445148</createdAt>
+		<updatedAt>2019-12-24T07:30:32.9445148</updatedAt>
+		<livelng>77.3790472</livelng>
+		<livelat>28.6302199</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</20>
+	<21>
+		<id>3031</id>
+		<name>Ashish Thapliyal</name>
+		<email>ashi1@gmail.com</email>
+		<password>Test@1234</password>
+		<about>I Am Who I Am, Your Approval Is Not Needed. I Was Reminded That My Blood Type Is Be Positive</about>
+		<token>8889db9b-01f6-4305-b07d-aecc516037bb</token>
+		<country />
+		<location>NH34, Shatabdi Nagar, Rithani, Meerut, Uttar Pradesh 250103, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>1996-10-22T12:00:00</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/fc8af47d-ef15-4c25-9d3f-a7a58c7444f9.png</profilePicture>
+		<coverPicture>Images/92d0e3d1-c075-4dd8-8e8c-196f30e1e689.png</coverPicture>
+		<enablefollowme>true</enablefollowme>
+		<sendmenotifications>true</sendmenotifications>
+		<sendTextmessages>true</sendTextmessages>
+		<enabletagging>true</enabletagging>
+		<createdAt>2019-12-24T06:52:08.6757278</createdAt>
+		<updatedAt>2020-01-02T06:30:51.6595305</updatedAt>
+		<livelng>77.3790169</livelng>
+		<livelat>28.6301942</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>206</creditBalance>
+		<myCash>0</myCash>
+	</21>
+	<22>
+		<id>3030</id>
+		<name>singh</name>
+		<email>singh@gmail.com</email>
+		<password>Test@123</password>
+		<about>jdfgjghjgf </about>
+		<token>280a1f00-8597-4eee-8d46-9c8d5a120ac7</token>
+		<country />
+		<location>Jg Halli Rd, Karnataka 577533, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-04T03:25:02</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/2f6c09a2-d758-45af-8724-e69a6b2eeed4.png</profilePicture>
+		<coverPicture>Images/4c997464-7384-4f26-bcab-ba6d0f1474b9.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-24T06:32:23.0727945</createdAt>
+		<updatedAt>2019-12-24T09:39:40.1944746</updatedAt>
+		<livelng>77.38982399999999</livelng>
+		<livelat>28.6285824</livelat>
+		<liveLocation>noidya sector 63 Vidya polymer, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India</liveLocation>
+		<creditBalance>30</creditBalance>
+		<myCash>0</myCash>
+	</22>
+	<23>
+		<id>3029</id>
+		<name>Akku Testing</name>
+		<email>akku1@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about>For some reason you've got "bootstrap-sass": "^3.3.7" so it looks like you are mixing Bootstrap versions and might be using Bootstrap 3, effectively.</about>
+		<token>7b0400eb-cd4f-45df-a8db-0c0871d46906</token>
+		<country />
+		<location>Noida-Greater Noida Expressway, Amit Nagar, Sadarpur, Greater Noida, Uttar Pradesh, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-18T06:26:55</dob>
+		<gender>2</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/eba5299c-5405-45cc-ac33-ef725d3e7bec.png</profilePicture>
+		<coverPicture>Images/b1d0cff4-3f1f-4571-a638-1e1094eb86bb.png</coverPicture>
+		<enablefollowme>true</enablefollowme>
+		<sendmenotifications>true</sendmenotifications>
+		<sendTextmessages>true</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-24T06:31:54.9038705</createdAt>
+		<updatedAt>2019-12-24T13:00:12.9520741</updatedAt>
+		<livelng>77.3790246</livelng>
+		<livelat>28.6302159</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>161</creditBalance>
+		<myCash>0</myCash>
+	</23>
+	<24>
+		<id>3028</id>
+		<name>Aakankshi Gupta</name>
+		<email>aakankshi.cuminte@gmail.com</email>
+		<password>116331365713184193775</password>
+		<about />
+		<token>c916c01f-5844-445b-9f5a-e60d77ecb620</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/9d38d28e-4021-4063-a703-821d1878a18c.png</profilePicture>
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-16T06:56:43.320768</createdAt>
+		<updatedAt>2019-12-16T06:56:43.3207681</updatedAt>
+		<livelng>77.37902439999999</livelng>
+		<livelat>28.630209599999997</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</24>
+	<25>
+		<id>3026</id>
+		<name>Manresh Chandra 5</name>
+		<email>manresh5@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about>about.me is a personal web hosting service co-founded by Ryan Freitas, Tony Conrad and Tim Young in October 2009.a</about>
+		<token>3c8ad706-9667-477a-adb6-3539f7b10a67</token>
+		<country />
+		<location>Deák Ferenc tér</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-11T11:24:07</dob>
+		<gender>3</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>true</enablefollowme>
+		<sendmenotifications>true</sendmenotifications>
+		<sendTextmessages>true</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-16T05:13:28.5717641</createdAt>
+		<updatedAt>2019-12-16T05:13:28.5717641</updatedAt>
+		<livelng>77.3790338</livelng>
+		<livelat>28.630177699999997</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</25>
+	<26>
+		<id>3025</id>
+		<name>Manresh Chandra 4</name>
+		<email>manresh4@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>8131e59d-7c83-4024-9423-0639a5887b52</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-16T05:11:34.473505</createdAt>
+		<updatedAt>2019-12-16T05:11:34.473505</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</26>
+	<27>
+		<id>3024</id>
+		<name>Manresh Chandra 3</name>
+		<email>manresh3@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>dc752b59-3d36-4b07-bc5c-6cd5913bae83</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-16T05:03:39.4564421</createdAt>
+		<updatedAt>2019-12-16T05:03:39.4564423</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>3</creditBalance>
+		<myCash>0</myCash>
+	</27>
+	<28>
+		<id>3023</id>
+		<name>Manresh Chandra 2</name>
+		<email>manresh2@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>867f49f2-8af8-45bf-9bd5-28ec641d3c44</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-16T05:01:14.0246654</createdAt>
+		<updatedAt>2019-12-16T05:01:14.0246654</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</28>
+	<29>
+		<id>3022</id>
+		<name>Raju Prasad</name>
+		<email>raju.prasad@adequateinfosoft.com</email>
+		<password>Raju@1234</password>
+		<about />
+		<token>58ecfd42-7f10-440e-8007-29c6fa524040</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-13T14:36:34.2151655</createdAt>
+		<updatedAt>2019-12-13T14:36:34.2151655</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</29>
+	<30>
+		<id>3021</id>
+		<name>Ashok Patel</name>
+		<email>ashoktest@gmail.com</email>
+		<password>ashokpatel457</password>
+		<about />
+		<token>520302ff-b08d-445f-be70-11c02d257e7e</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-13T13:47:59.4288322</createdAt>
+		<updatedAt>2019-12-13T13:47:59.4288322</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>3</creditBalance>
+		<myCash>0</myCash>
+	</30>
+	<31>
+		<id>2021</id>
+		<name>manresh1</name>
+		<email>manresh1@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>9305e1c5-82e2-4a79-b0ca-37bb5880f505</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-13T13:17:31.2904215</createdAt>
+		<updatedAt>2019-12-13T13:17:31.2904216</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>2</creditBalance>
+		<myCash>0</myCash>
+	</31>
+	<32>
+		<id>2020</id>
+		<name>Manresh Chandra</name>
+		<email>manresh@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about>My Name is Manresh Chandra. I'm self Motivated Person. I considers mine a ‘forever student,’</about>
+		<token>bc370f5f-7d13-4fe6-9c2c-848198394f8a</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-13T07:08:47.9644619</createdAt>
+		<updatedAt>2019-12-13T07:08:47.9644619</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>3</creditBalance>
+		<myCash>0</myCash>
+	</32>
+	<33>
+		<id>2019</id>
+		<name>Test</name>
+		<email>aakankshi7@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about>test</about>
+		<token>5a1218d2-5d66-4255-9137-0f7e700bdcab</token>
+		<country />
+		<location>Noida</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-11-12T00:00:00</dob>
+		<gender>2</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture>Images/6f1437c7-7796-4d27-8b9a-041f3c5b86d4.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-05T05:39:51.4928759</createdAt>
+		<updatedAt>2019-12-05T06:41:24.107938</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>2</creditBalance>
+		<myCash>0</myCash>
+	</33>
+	<34>
+		<id>2018</id>
+		<name>aakankshi6</name>
+		<email>aakankshi6@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about>A traveller without observation is a bird without wings . Life is a journey, not a destination. Never stop exploring</about>
+		<token>0ab8257f-7574-476d-b96f-508d3917af9b</token>
+		<country />
+		<location>Noida</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-18T00:00:00</dob>
+		<gender>3</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/2e38c3c4-9e55-4b07-aedf-7e91934c167b.png</profilePicture>
+		<coverPicture>Images/938e342d-bd4e-4121-b222-9cb28f670d36.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-05T05:16:04.4212331</createdAt>
+		<updatedAt>2019-12-05T12:25:13.6221215</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</34>
+	<35>
+		<id>2017</id>
+		<name>aakankshi5</name>
+		<email>aakankshi5@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>b6fcf970-3271-492b-866c-76238f126c3f</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/86652baa-c60c-4ef8-8d65-0fda9bde5ae9.png</profilePicture>
+		<coverPicture>Images/51e3fb5e-a9a6-4b3d-8da0-7e882d7774db.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-05T05:06:49.1838089</createdAt>
+		<updatedAt>2019-12-05T05:22:00.9403881</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>1</creditBalance>
+		<myCash>0</myCash>
+	</35>
+	<36>
+		<id>2016</id>
+		<name>aakankshi4</name>
+		<email>aakankshi4@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>1b43db89-29a4-4966-ae57-86d705978dd3</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/3a369b02-20f5-46fc-b6d5-811c071d8afa.png</profilePicture>
+		<coverPicture>Images/7b23cd21-0474-473a-9b44-4bf97f67fba9.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-05T05:04:21.8383669</createdAt>
+		<updatedAt>2019-12-05T05:21:57.4139934</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</36>
+	<37>
+		<id>2015</id>
+		<name>aakankshi3</name>
+		<email>aakankshi3@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>d65f85e3-0f8d-4c67-8de8-1546a7518cba</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/a855f15e-f3b5-4873-8fdd-49172f8d5d51.png</profilePicture>
+		<coverPicture>Images/77db74bd-6df5-4dd3-abcc-f021e6486521.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-05T05:02:05.1655627</createdAt>
+		<updatedAt>2019-12-05T05:21:54.2379269</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</37>
+	<38>
+		<id>2014</id>
+		<name>Aakankshi 2</name>
+		<email>aakankshi2@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about>ewewrewrew</about>
+		<token>4e2923a9-b059-4dc9-8d92-ce0cffa84208</token>
+		<country />
+		<location>Dada Dev Mandir Road</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-11T00:00:00</dob>
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>true</enablefollowme>
+		<sendmenotifications>true</sendmenotifications>
+		<sendTextmessages>true</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-05T05:00:19.5034062</createdAt>
+		<updatedAt>2019-12-05T05:00:19.5034063</updatedAt>
+		<livelng>77.3790249</livelng>
+		<livelat>28.6302141</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>5</creditBalance>
+		<myCash>0</myCash>
+	</38>
+	<39>
+		<id>2013</id>
+		<name>Aakankshi 1</name>
+		<email>aakankshi1@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about>foundations in psychology and sociology and stassy </about>
+		<token>d7fa7194-5ac2-4e32-b11b-3792e5cc067c</token>
+		<country />
+		<location>Delhi</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-26T06:12:30</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>true</enablefollowme>
+		<sendmenotifications>true</sendmenotifications>
+		<sendTextmessages>true</sendTextmessages>
+		<enabletagging>true</enabletagging>
+		<createdAt>2019-12-05T04:38:32.7808454</createdAt>
+		<updatedAt>2019-12-06T05:41:05.3597939</updatedAt>
+		<livelng>77.389849</livelng>
+		<livelat>28.6282231</livelat>
+		<liveLocation>Unnamed Road, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India</liveLocation>
+		<creditBalance>269</creditBalance>
+		<myCash>36</myCash>
+	</39>
+	<40>
+		<id>2012</id>
+		<name>Aakankshi Gupta</name>
+		<email>aakankshi@gmail.com</email>
+		<password>zxcvbnm1</password>
+		<about />
+		<token>4c02ee6e-2cb5-4b75-888f-4adb7c790dad</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-12-05T04:35:42.6189131</createdAt>
+		<updatedAt>2019-12-05T04:35:42.6189131</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>3</creditBalance>
+		<myCash>0</myCash>
+	</40>
+	<41>
+		<id>2011</id>
+		<name>Aankashi</name>
+		<email>alokpatel@gmail.com</email>
+		<password>pankaj@123</password>
+		<about>its me</about>
+		<token>4516169a-58e3-4d04-a355-8c608be5d583</token>
+		<country />
+		<location>New Delhi</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-05T00:00:00</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/9b0f8891-98ec-4b10-91b8-a9f8fbb6d108.png</profilePicture>
+		<coverPicture>Images/fe2c72d4-8eb6-47e6-9e8e-5d1e15e2b9ea.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-30T05:36:52.1332523</createdAt>
+		<updatedAt>2019-12-05T05:21:49.0948144</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>4</creditBalance>
+		<myCash>0</myCash>
+	</41>
+	<42>
+		<id>2010</id>
+		<name>Test 10</name>
+		<email>test02@gmail.com</email>
+		<password>123456</password>
+		<about />
+		<token>ba805b5d-f38f-4a33-9fcb-60f30923479d</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-27T10:41:07.8215121</createdAt>
+		<updatedAt>2019-11-27T10:41:07.8215122</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>3</creditBalance>
+		<myCash>0</myCash>
+	</42>
+	<43>
+		<id>2009</id>
+		<name>Test 9</name>
+		<email>test10@gmail.com</email>
+		<password>123456</password>
+		<about />
+		<token>1fa26ffa-465e-499f-ae9d-3e36fb94a0ea</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-27T10:20:10.5816545</createdAt>
+		<updatedAt>2019-11-27T10:20:10.5816545</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</43>
+	<44>
+		<id>2008</id>
+		<name>Test 8</name>
+		<email>test3@test.com</email>
+		<password>123456</password>
+		<about />
+		<token>822e8f5c-74ba-41f9-911e-9e5a47351dc5</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture />
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-27T10:09:42.6969868</createdAt>
+		<updatedAt>2019-11-27T10:09:42.6969869</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>0</creditBalance>
+		<myCash>0</myCash>
+	</44>
+	<45>
+		<id>2007</id>
+		<name>Neeraj Singh</name>
+		<email>neirajsingh100@gmail.com</email>
+		<password>100569704678350206382</password>
+		<about />
+		<token>47d25887-1933-4cbc-a4eb-6cc829c9cad6</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>/images/9c2dbeed-5ce9-4411-a549-255dc35da175.png</profilePicture>
+		<coverPicture>Images/d3cfe52d-93b0-4f35-87c9-d0c2f18f8daa.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-26T12:42:18.6778716</createdAt>
+		<updatedAt>2019-12-05T05:20:40.9827126</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>2</creditBalance>
+		<myCash>0</myCash>
+	</45>
+	<46>
+		<id>2006</id>
+		<name>Hr. Niels Henriksen</name>
+		<email>contact@adequateinfosoft.com</email>
+		<password>354343138574152</password>
+		<about>i am software developer</about>
+		<token>347d684e-da9b-450e-bc94-cd5a99b04234</token>
+		<country />
+		<location>Jaypee Greens Pari Chowk, Tugalpur Village, Greater Noida, Uttar Pradesh 201310, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-28T06:04:42</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture>Images/ac6a163f-af9f-46db-8327-94ab870000f4.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-26T05:58:34.894975</createdAt>
+		<updatedAt>2019-12-05T05:20:37.5393081</updatedAt>
+		<livelng>77.3790241</livelng>
+		<livelat>28.6302086</livelat>
+		<liveLocation>H15, H Block, Sector 63, Noida, Uttar Pradesh 201301, India</liveLocation>
+		<creditBalance>11</creditBalance>
+		<myCash>0</myCash>
+	</46>
+	<47>
+		<id>2005</id>
+		<name>Test 6</name>
+		<email>pankajadequate@gmail.com</email>
+		<password>sndsjkdsaj161564sasa</password>
+		<about />
+		<token>7a4ae2e1-5b65-4aad-96f0-43336fad5a3b</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture>Images/b372a834-231a-4ea1-beef-5c3c3fb33ef2.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-25T13:12:47.6690112</createdAt>
+		<updatedAt>2019-12-05T05:20:34.2935856</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>2</creditBalance>
+		<myCash>0</myCash>
+	</47>
+	<48>
+		<id>2004</id>
+		<name>Test 5</name>
+		<email>pankajws@gmail.com</email>
+		<password>Pankaj@123</password>
+		<about />
+		<token>1fd08288-57aa-41d9-ae44-29fcbb0a78a6</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture>Images/519c95d8-79d3-4d18-bac8-fc75b817eac9.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-25T11:29:06.938541</createdAt>
+		<updatedAt>2019-12-05T05:20:30.604524</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>4</creditBalance>
+		<myCash>0</myCash>
+	</48>
+	<49>
+		<id>2</id>
+		<name>rajat Saxena</name>
+		<email>rajat.nirmal@gmail.com</email>
+		<password>test</password>
+		<about>abcd</about>
+		<token>00fb57db-10ad-4661-b3e0-7366c6698ac0</token>
+		<country />
+		<location>3465</location>
+		<lng>8.7977</lng>
+		<lat>5.8348759</lat>
+		<dob>2019-11-17T16:56:35.8</dob>
+		<gender>1</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/0f0ab4a5-4f00-4275-b2dc-be3b157f5e53.png</profilePicture>
+		<coverPicture>Images/0153a968-6dd0-4c9c-9b92-8995e99985d3.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>2019-11-17T16:56:35.8</createdAt>
+		<updatedAt>2019-12-05T05:21:02.1337931</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>43</creditBalance>
+		<myCash>0</myCash>
+	</49>
+	<50>
+		<id>3</id>
+		<name>Pankaj Patel</name>
+		<email>Pankaj@gmail.com</email>
+		<password>123456</password>
+		<about />
+		<token>f6b4bcc8-448b-4b65-84cb-48e9569c5cfe</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/0eff867e-62ec-43a7-a535-7e83b6b27a30.png</profilePicture>
+		<coverPicture>Images/4bbe816b-a60c-419f-a87b-34508c633d30.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>0001-01-01T00:00:00</createdAt>
+		<updatedAt>2019-12-05T13:25:01.977078</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>62</creditBalance>
+		<myCash>0</myCash>
+	</50>
+	<51>
+		<id>1003</id>
+		<name>Test 2</name>
+		<email>pankajabc@gmail.com</email>
+		<password>Pankaj@123</password>
+		<about>An ordinary bhartiya..</about>
+		<token>c8f53478-4cfb-4382-8531-b44b6d20cd8c</token>
+		<country />
+		<location>Jaipur Engineering College Rd, Kukas, Rajasthan 302028, India</location>
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob>2019-12-31T11:06:38</dob>
+		<gender>2</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/07cac01f-2a12-4125-ba8b-8eff42333925.png</profilePicture>
+		<coverPicture>Images/db6fce41-9924-4c78-9099-c2890e6f0cac.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>0001-01-01T00:00:00</createdAt>
+		<updatedAt>2019-12-23T13:43:27.5816869</updatedAt>
+		<livelng>77.389849</livelng>
+		<livelat>28.6282231</livelat>
+		<liveLocation>Unnamed Road, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India</liveLocation>
+		<creditBalance>16</creditBalance>
+		<myCash>0</myCash>
+	</51>
+	<52>
+		<id>1004</id>
+		<name>Test 2</name>
+		<email>pankajabcd@gmail.com</email>
+		<password>Pankaj@123</password>
+		<about />
+		<token>3f92cdef-1d8a-4f08-8468-9938dc9284ce</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture>Images/7da06d0e-e110-44e9-b417-4b014fe8a889.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>0001-01-01T00:00:00</createdAt>
+		<updatedAt>2019-12-05T05:19:23.3650433</updatedAt>
+		<livelng>77.3674236</livelng>
+		<livelat>28.6260665</livelat>
+		<liveLocation>35, Block A, Industrial Area, Sector 62, Noida, Uttar Pradesh 201309, India</liveLocation>
+		<creditBalance>3</creditBalance>
+		<myCash>0</myCash>
+	</52>
+	<53>
+		<id>1005</id>
+		<name>Test 3</name>
+		<email>test@test.com</email>
+		<password>123456</password>
+		<about />
+		<token>cc2ed6c5-0a59-4aca-9b8e-a686e0a4fa03</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture />
+		<coverPicture>Images/6d9afca5-3e79-4979-9091-a83d8df7b388.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>0001-01-01T00:00:00</createdAt>
+		<updatedAt>2019-12-05T05:19:29.704463</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>44</creditBalance>
+		<myCash>0</myCash>
+	</53>
+	<54>
+		<id>1006</id>
+		<name>Test 4</name>
+		<email>test1@test.com</email>
+		<password>123456</password>
+		<about />
+		<token>f33f3325-bb08-41a5-b545-d2b5c443720f</token>
+		<country />
+		<location />
+		<lng>0</lng>
+		<lat>0</lat>
+		<dob />
+		<gender>0</gender>
+		<userType>1</userType>
+		<userStatus>1</userStatus>
+		<profilePicture>Images/b3f2677f-10a8-46e6-8d48-cfba2cc1e0b5.png</profilePicture>
+		<coverPicture>Images/e9845113-f874-469d-8e89-53a86f351887.png</coverPicture>
+		<enablefollowme>false</enablefollowme>
+		<sendmenotifications>false</sendmenotifications>
+		<sendTextmessages>false</sendTextmessages>
+		<enabletagging>false</enabletagging>
+		<createdAt>0001-01-01T00:00:00</createdAt>
+		<updatedAt>2019-12-05T05:22:11.8963884</updatedAt>
+		<livelng>0</livelng>
+		<livelat>0</livelat>
+		<liveLocation />
+		<creditBalance>1</creditBalance>
+		<myCash>0</myCash>
+	</54>
+</root>
\ No newline at end of file
diff --git a/tests/test_foo.py b/tests/test_foo.py
deleted file mode 100644
index 30e2c41..0000000
--- a/tests/test_foo.py
+++ /dev/null
@@ -1,2 +0,0 @@
-def test_foo():
-    assert True
diff --git a/tests/test_main.py b/tests/test_main.py
index 3cb5eb9..ba890e4 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -1,40 +1,147 @@
 import pytest
 
-from xtractmime import _is_match_mime_pattern, WHITESPACE_BYTES
+from xtractmime import (
+    _find_unknown_mimetype,
+    _sniff_mislabled_binary,
+    _sniff_mislabled_feed,
+    extract_mime,
+)
 
 
 class TestMain:
 
-    input_bytes = b"GIF87a" + bytes.fromhex("401f7017f70000")
+    sample_xml1 = b"""<?xml version = "1.0" encoding = "UTF-8" ?>
+                        <!--Sample xml comment-->
+                        <rss version="2.0">
+                        <class_list>
+                           <student>
+                              <name>XYZ</name>
+                              <grade>A</grade>
+                           </student>
+                        </class_list>"""
+
+    sample_xml2 = b"""<?xml version = "1.0" encoding = "UTF-8" ?>
+                        <feed xmlns="http://www.w3.org/2005/Atom">
+                        <class_list>
+                           <student>
+                              <name>XYZ</name>
+                              <grade>A</grade>
+                           </student>
+                        </class_list>"""
+
+    sample_xml3 = b"""<?xml version = "1.0" encoding = "UTF-8" ?>
+                        <!ELEMENT spec (front, body, back?)>
+                        <class_list>
+                           <student>
+                              <name>XYZ</name>
+                              <grade>A</grade>
+                           </student>
+                        </class_list>"""
+
+    sample_xml4 = b"""<?xml version="1.0" encoding="utf-8"?>
+                        <rdf:RDF
+                          xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+                          xmlns:content="http://purl.org/rss/1.0/modules/content/"
+                          xmlns="http://purl.org/rss/1.0/"
+                        >
+                        </rdf:RDF>"""
+
+    sample_xml5 = b"""<?xml version="1.0" encoding="utf-8"?>
+                        <rdf:RDF
+                          xmlns:content="http://purl.org/rss/1.0/modules/content/"
+                          xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+                          xmlns="http://purl.org/rss/1.0/"
+                        >
+                        </rdf:RDF>"""
 
     @pytest.mark.parametrize(
-        "input_bytes,byte_pattern,pattern_mask,lstrip,expected",
+        "body,content_types,http_origin,no_sniff,supported_types,expected",
         [
-            (input_bytes, b"GIF87a", b"\xff\xff\xff\xff\xff\xff", None, True),
-            (input_bytes, b"GIF87a", b"\xff\xff\xff\xff\xff", None, ValueError),
-            (b" \t\n\rGIF87a", b"GIF87a", b"\xff\xff\xff\xff\xff\xff", WHITESPACE_BYTES, True),
-            (b"GIF", b"GIF87a", b"\xff\xff\xff\xff\xff\xff", None, False),
-            (b"\xff\xff\xff\xff\xff\xff", b"GIF87a", b"\xff\xff\xff\xff\xff\xff", None, False),
+            ("foo.pdf", None, True, False, None, b"application/pdf"),
+            ("foo.gif", (b"image/gif",), True, True, None, b"image/gif"),
+            ("foo.txt", (b"text/plain",), True, False, None, b"text/plain"),
+            ("foo.xml", (b"text/xml",), True, False, None, b"text/xml"),
+            ("foo.html", (b"text/html",), True, False, None, b"text/html"),
+            ("foo.gif", (b"image/gif",), True, False, (b"image/gif",), b"image/gif"),
+            ("foo.mp4", (b"video/mp4",), True, False, (b"video/mp4",), b"video/mp4"),
+            (b"\x00\x00\x00\x00", (b"text/test",), True, False, None, b"text/test"),
+            (b"", (b"text/html; charset=utf-8",), True, False, None, b"text/html"),
+            (b"", (b"text/htmlpdfthing",), True, False, None, b"text/htmlpdfthing"),
+            (b"", None, True, False, None, b"text/plain"),
         ],
     )
-    def test_is_match_mime_pattern(
-        self, input_bytes, byte_pattern, pattern_mask, lstrip, expected
+    def test_extract_mime(
+        self, body, content_types, http_origin, no_sniff, supported_types, expected
     ):
-        if type(expected) == type and issubclass(expected, Exception):
-            with pytest.raises(expected):
-                _is_match_mime_pattern(
-                    input_bytes=input_bytes,
-                    byte_pattern=byte_pattern,
-                    pattern_mask=pattern_mask,
-                    lstrip=lstrip,
-                )
-        else:
-            assert (
-                _is_match_mime_pattern(
-                    input_bytes=input_bytes,
-                    byte_pattern=byte_pattern,
-                    pattern_mask=pattern_mask,
-                    lstrip=lstrip,
-                )
-                == expected
+        if isinstance(body, str):
+            with open(f"tests/files/{body}", "rb") as input_file:
+                body = input_file.read()
+        assert (
+            extract_mime(
+                body,
+                content_types=content_types,
+                http_origin=http_origin,
+                no_sniff=no_sniff,
+                supported_types=supported_types,
             )
+            == expected
+        )
+
+    @pytest.mark.parametrize(
+        "input_bytes,expected",
+        [
+            ("foo.txt", b"text/plain"),
+            ("foo.exe", b"application/octet-stream"),
+            (b"\xfe\xff", b"text/plain"),
+        ],
+    )
+    def test_sniff_mislabled_binary(self, input_bytes, expected):
+        if isinstance(input_bytes, str):
+            with open(f"tests/files/{input_bytes}", "rb") as input_file:
+                input_bytes = input_file.read()
+        assert _sniff_mislabled_binary(input_bytes) == expected
+
+    @pytest.mark.parametrize(
+        "input_bytes,sniff_scriptable,extra_types,expected",
+        [
+            ("foo.pdf", True, None, b"application/pdf"),
+            ("foo.gif", False, None, b"image/gif"),
+            ("foo.mp4", False, None, b"video/mp4"),
+            ("foo.zip", False, None, b"application/zip"),
+            ("foo.txt", False, None, b"text/plain"),
+            ("foo.exe", False, None, b"application/octet-stream"),
+            (b"test", False, ((b"test", b"\xff\xff\xff\xff", None, b"text/test"),), b"text/test"),
+        ],
+    )
+    def test_find_unknown_mimetype(self, input_bytes, sniff_scriptable, extra_types, expected):
+        if isinstance(input_bytes, str):
+            with open(f"tests/files/{input_bytes}", "rb") as input_file:
+                input_bytes = input_file.read()
+        assert _find_unknown_mimetype(input_bytes, sniff_scriptable, extra_types) == expected
+
+    @pytest.mark.parametrize(
+        "input_bytes,supplied_type,expected",
+        [
+            ("foo.xml", b"text/xml", b"text/xml"),
+            (sample_xml1, b"application/rss+xml", b"application/rss+xml"),
+            (sample_xml2, b"application/atom+xml", b"application/atom+xml"),
+            (sample_xml3, b"text/xml", b"text/xml"),
+            (sample_xml4, b"application/rss+xml", b"application/rss+xml"),
+            (sample_xml5, b"application/rss+xml", b"application/rss+xml"),
+            (b"test", b"text/test", b"text/test"),
+            (b" ", None, None),
+            (b"<", None, None),
+            (b"<!--", None, None),
+            (b"<!", None, None),
+            (b"<?", None, None),
+            (b"<rdf:RDF", None, None),
+            (b"<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'", None, None),
+            (b"<rdf:RDF xmlns:content='http://purl.org/rss/1.0/modules/content/'", None, None),
+            (b"", None, None),
+        ],
+    )
+    def test_sniff_mislabled_feed(self, input_bytes, supplied_type, expected):
+        if isinstance(input_bytes, str):
+            with open(f"tests/files/{input_bytes}", "rb") as input_file:
+                input_bytes = input_file.read()
+        assert _sniff_mislabled_feed(input_bytes, supplied_type) == expected
diff --git a/tests/test_mimegroups.py b/tests/test_mimegroups.py
new file mode 100644
index 0000000..b716676
--- /dev/null
+++ b/tests/test_mimegroups.py
@@ -0,0 +1,143 @@
+import pytest
+
+from xtractmime import mimegroups
+
+
+ALL_MIME_GROUPS = {
+    name[3:-10]: getattr(mimegroups, name)
+    for name in dir(mimegroups)
+    if name.startswith("is_") and name.endswith("_mime_type")
+}
+
+
+@pytest.mark.parametrize(
+    "mime_type,mime_groups",
+    [
+        # MIME type types
+        (b"image/foo", {"image"}),
+        (b"audio/foo", {"audio_video"}),
+        (b"video/foo", {"audio_video"}),
+        (b"font/foo", {"font"}),
+        # MIME types subtype suffixes
+        (b"application/foo+zip", {"zip"}),
+        (b"application/foo+xml", {"xml", "scriptable"}),
+        (b"application/foo+json", {"json"}),
+        # 4.6. MIME type groups, audio or video MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#audio-or-video-mime-type
+        (b"application/ogg", {"audio_video"}),
+        # 4.6. MIME type groups, font MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#font-mime-type
+        (b"application/font-cff", {"font"}),
+        (b"application/font-off", {"font"}),
+        (b"application/font-sfnt", {"font"}),
+        (b"application/font-ttf", {"font"}),
+        (b"application/font-woff", {"font"}),
+        (b"application/vnd.ms-fontobject", {"font"}),
+        (b"application/vnd.ms-opentype", {"font"}),
+        # 4.6. MIME type groups, zip-based MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#zip-based-mime-type
+        (b"application/zip", {"zip", "archive"}),
+        # 4.6. MIME type groups, archive MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#archive-mime-type
+        (b"application/x-rar-compressed", {"archive"}),
+        (b"application/zip", {"zip", "archive"}),
+        (b"application/x-gzip", {"archive"}),
+        # 4.6. MIME type groups, xml MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#xml-mime-type
+        (b"text/xml", {"xml", "scriptable"}),
+        (b"application/xml", {"xml", "scriptable"}),
+        # 4.6. MIME type groups, html MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#html-mime-type
+        (b"text/html", {"html", "scriptable"}),
+        # 4.6. MIME type groups, scriptable MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#scriptable-mime-type
+        (b"application/pdf", {"scriptable"}),
+        # 4.6. MIME type groups, javascript MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#javascript-mime-type
+        (b"application/ecmascript", {"javascript"}),
+        (b"application/javascript", {"javascript"}),
+        (b"application/x-ecmascript", {"javascript"}),
+        (b"application/x-javascript", {"javascript"}),
+        (b"text/ecmascript", {"javascript"}),
+        (b"text/javascript", {"javascript"}),
+        (b"text/javascript1.0", {"javascript"}),
+        (b"text/javascript1.1", {"javascript"}),
+        (b"text/javascript1.2", {"javascript"}),
+        (b"text/javascript1.3", {"javascript"}),
+        (b"text/javascript1.4", {"javascript"}),
+        (b"text/javascript1.5", {"javascript"}),
+        (b"text/jscript", {"javascript"}),
+        (b"text/livescript", {"javascript"}),
+        (b"text/x-ecmascript", {"javascript"}),
+        (b"text/x-javascript", {"javascript"}),
+        # 4.6. MIME type groups, json MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#json-mime-type
+        (b"application/json", {"json"}),
+        (b"text/json", {"json"}),
+        # 5.1. Interpreting resource metadata
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#interpreting-the-resource-metadata
+        (b"text/plain", {}),
+        (b"text/plain; charset=ISO-8859-1", {}),
+        (b"text/plain; charset=iso-8859-1", {}),
+        (b"text/plain; charset=UTF-8", {}),
+        # 6.1. Matching an image type pattern
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#matching-an-image-type-pattern
+        (b"image/x-icon", {"image"}),
+        (b"image/bmp", {"image"}),
+        (b"image/gif", {"image"}),
+        (b"image/webp", {"image"}),
+        (b"image/png", {"image"}),
+        (b"image/jpeg", {"image"}),
+        # 6.2. Matching an audio or video type pattern
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#matching-an-audio-or-video-type-pattern
+        (b"audio/basic", {"audio_video"}),
+        (b"audio/aiff", {"audio_video"}),
+        (b"audio/mpeg", {"audio_video"}),
+        (b"application/ogg", {"audio_video"}),
+        (b"audio/midi", {"audio_video"}),
+        (b"video/avi", {"audio_video"}),
+        (b"audio/wave", {"audio_video"}),
+        (b"video/mp4", {"audio_video"}),
+        (b"video/webm", {"audio_video"}),
+        (b"audio/mpeg", {"audio_video"}),
+        # 6.3. Matching a font type pattern
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#matching-a-font-type-pattern
+        (b"application/vnd.ms-fontobject", {"font"}),
+        (b"font/ttf", {"font"}),
+        (b"font/otf", {"font"}),
+        (b"font/collection", {"font"}),
+        (b"font/woff", {"font"}),
+        (b"font/woff2", {"font"}),
+        # 6.4. Matching an archive type pattern
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#matching-an-archive-type-pattern
+        (b"application/x-gzip", {"archive"}),
+        (b"application/zip", {"zip", "archive"}),
+        (b"application/x-rar-compressed", {"archive"}),
+        # 7. Determining the computed mime type of a resource
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#determining-the-computed-mime-type-of-a-resource
+        (b"unknown/unknown", {}),
+        (b"application/unknown", {}),
+        (b"*/*", {}),
+        # 7.1. Identifying a resource with an unknown MIME type
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#identifying-a-resource-with-an-unknown-mime-type
+        (b"text/html", {"html", "scriptable"}),
+        (b"application/postscript", {}),
+        (b"text/plain", {}),
+        (b"application/octet-stream", {}),
+        # 7.3. Sniffing a mislabeled feed
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#sniffing-a-mislabeled-feed
+        (b"application/rss+xml", {"xml", "scriptable"}),
+        (b"application/atom+xml", {"xml", "scriptable"}),
+        # 8.8. Sniffing in a text track context
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#sniffing-in-a-text-track-context
+        (b"text/vtt", {}),
+        # 8.9. Sniffing in a cache manifest context
+        # https://mimesniff.spec.whatwg.org/commit-snapshots/609a3a3c935fbb805b46cf3d90768d695a1dcff2/#sniffing-in-a-cache-manifest-context
+        (b"text/cache-manifest", {}),
+    ],
+)
+def test_mime_group(mime_type, mime_groups):
+    assert all(
+        is_in_mime_group(mime_type) == (mime_group in mime_groups)
+        for mime_group, is_in_mime_group in ALL_MIME_GROUPS.items()
+    )
diff --git a/tests/test_utils.py b/tests/test_utils.py
index e3dfb9c..e815f3a 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,12 +1,17 @@
 import pytest
 
 from unittest import mock
+from xtractmime._utils import is_match_mime_pattern
+from xtractmime._patterns import WHITESPACE_BYTES
 
 from xtractmime._utils import (
-    is_archive,
-    is_audio_video,
-    is_font,
-    is_image,
+    contains_binary,
+    get_archive_mime,
+    get_audio_video_mime,
+    get_extra_mime,
+    get_font_mime,
+    get_image_mime,
+    get_text_mime,
     is_mp3_non_ID3_signature,
     is_mp4_signature,
     is_webm_signature,
@@ -31,6 +36,40 @@ class TestUtils:
     with open("tests/files/foo.gif", "rb") as fp:
         body_gif = fp.read()
 
+    input_bytes = b"GIF87a" + bytes.fromhex("401f7017f70000")
+
+    @pytest.mark.parametrize(
+        "input_bytes,byte_pattern,pattern_mask,lstrip,expected",
+        [
+            (input_bytes, b"GIF87a", b"\xff\xff\xff\xff\xff\xff", None, True),
+            (input_bytes, b"GIF87a", b"\xff\xff\xff\xff\xff", None, ValueError),
+            (b" \t\n\rGIF87a", b"GIF87a", b"\xff\xff\xff\xff\xff\xff", WHITESPACE_BYTES, True),
+            (b"GIF", b"GIF87a", b"\xff\xff\xff\xff\xff\xff", None, False),
+            (b"\xff\xff\xff\xff\xff\xff", b"GIF87a", b"\xff\xff\xff\xff\xff\xff", None, False),
+        ],
+    )
+    def test_is_match_mime_pattern(
+        self, input_bytes, byte_pattern, pattern_mask, lstrip, expected
+    ):
+        if type(expected) == type and issubclass(expected, Exception):
+            with pytest.raises(expected):
+                is_match_mime_pattern(
+                    input_bytes=input_bytes,
+                    byte_pattern=byte_pattern,
+                    pattern_mask=pattern_mask,
+                    lstrip=lstrip,
+                )
+        else:
+            assert (
+                is_match_mime_pattern(
+                    input_bytes=input_bytes,
+                    byte_pattern=byte_pattern,
+                    pattern_mask=pattern_mask,
+                    lstrip=lstrip,
+                )
+                == expected
+            )
+
     @pytest.mark.parametrize(
         "input_bytes,expected",
         [
@@ -133,16 +172,48 @@ def test_audio_video(self, input_bytes, expected):
         if isinstance(input_bytes, str):
             with open(f"tests/files/{input_bytes}", "rb") as input_file:
                 input_bytes = input_file.read()
-        assert is_audio_video(input_bytes) == expected
+        assert get_audio_video_mime(input_bytes) == expected
+
+    @pytest.mark.parametrize(
+        "input_bytes,expected",
+        [
+            ("foo.html", b"text/html"),
+            ("foo.pdf", b"application/pdf"),
+            (b"\x00\x00\x00\x00", None),
+        ],
+    )
+    def test_text(self, input_bytes, expected):
+        if isinstance(input_bytes, str):
+            with open(f"tests/files/{input_bytes}", "rb") as input_file:
+                input_bytes = input_file.read()
+        assert get_text_mime(input_bytes) == expected
+
+    @pytest.mark.parametrize(
+        "input_bytes,extra_types,expected",
+        [
+            ("foo.ps", None, b"application/postscript"),
+            (b"test", ((b"test", b"\xff\xff\xff\xff", None, b"text/test"),), b"text/test"),
+            (b"\x00\x00\x00\x00", None, None),
+        ],
+    )
+    def test_extra(self, input_bytes, extra_types, expected):
+        if isinstance(input_bytes, str):
+            with open(f"tests/files/{input_bytes}", "rb") as input_file:
+                input_bytes = input_file.read()
+        assert get_extra_mime(input_bytes, extra_types) == expected
 
     def test_image(self):
-        assert is_image(self.body_gif) == b"image/gif"
-        assert is_image(b"\x00\x00\x00\x00") is None
+        assert get_image_mime(self.body_gif) == b"image/gif"
+        assert get_image_mime(b"\x00\x00\x00\x00") is None
 
     def test_font(self):
-        assert is_font(self.body_ttf) == b"font/ttf"
-        assert is_font(b"\x00\x00\x00\x00") is None
+        assert get_font_mime(self.body_ttf) == b"font/ttf"
+        assert get_font_mime(b"\x00\x00\x00\x00") is None
 
     def test_archive(self):
-        assert is_archive(self.body_zip) == b"application/zip"
-        assert is_archive(b"\x00\x00\x00\x00") is None
+        assert get_archive_mime(self.body_zip) == b"application/zip"
+        assert get_archive_mime(b"\x00\x00\x00\x00") is None
+
+    def test_contains_binary(self):
+        assert contains_binary(b"\x00\x01")
+        assert not contains_binary(b"\x09\x0a")