{"id":6021,"date":"2014-02-19T04:34:06","date_gmt":"2014-02-18T19:34:06","guid":{"rendered":"http:\/\/mk.miko.jp\/blog\/?p=6021"},"modified":"2014-10-13T16:48:21","modified_gmt":"2014-10-13T07:48:21","slug":"%e7%94%bb%e5%83%8f%e3%83%95%e3%82%a3%e3%83%ab%e3%82%bf%e4%bb%98%e3%81%8dftp%e3%82%b5%e3%83%bc%e3%83%90%e3%82%92%e6%9b%b8%e3%81%84%e3%81%a6%e3%81%bf%e3%81%9f","status":"publish","type":"post","link":"http:\/\/mk.miko.jp\/blog\/archives\/6021","title":{"rendered":"\u753b\u50cf\u30d5\u30a3\u30eb\u30bf\u4ed8\u304dFTP\u30b5\u30fc\u30d0\u3092\u66f8\u3044\u3066\u307f\u305f"},"content":{"rendered":"<p>\u3000Nexus 7\u3067\u3001\u96fb\u5b50\u5316\u3057\u305f\u6f2b\u753b\u3068\u304b\u8aad\u3080\u306e\u306b\u3055\u30fc\u3002\u3042\u3093\u307e\u308a\u5927\u304d\u3044\u3068\u3001\u8ee2\u9001\u901f\u5ea6\u7684\u306b\u7cde\u91cd\u304f\u306a\u308b\u3058\u3083\u306a\u3044\u3067\u3059\u304b\u3002<br \/>\n\u3000\u3067\u3082\u3001\u305d\u308c\u3092\u57fa\u6e96\u306b\u753b\u8cea\u843d\u3068\u3057\u3066\u4fdd\u5b58\u3059\u308b\u306e\u3082\u3042\u308c\u3060\u3057\u3001\u308f\u3056\u308f\u3056\u4f4e\u753b\u8cea\u7248\u3068\u304b\u3092\u5206\u3051\u3066\u7f6e\u3044\u3066\u304a\u304f\u306e\u3082\u4f55\u3068\u306a\u304f\u30a2\u30ec\u3067\u3002<\/p>\n<p>\u3000\u3067\u3001\u30aa\u30f3\u30b6\u30d5\u30e9\u30a4\u3067\u753b\u50cf\u3092\u52a0\u5de5\u3059\u308bFTP\u30b5\u30fc\u30d0\u306a\u3089\u3001<a href=\"https:\/\/www.python.org\/\">Python<\/a> + <a href=\"https:\/\/code.google.com\/p\/pyftpdlib\/\">pyftpdlib<\/a> + <a href=\"http:\/\/www.imagemagick.org\/\">ImageMagicK<\/a> + <a href=\"http:\/\/docs.wand-py.org\/en\/0.3.5\/\">Wand<\/a>\u3067\u5272\u3068\u3059\u3050\u306b\u66f8\u3051\u305d\u3046\u306a\u6c17\u304c\u3057\u305f\u306e\u3067\u3001\u66f8\u3044\u3066\u307f\u305f\u3002<br \/>\n\u3000\u3064\u3044\u3067\u306b\u3001\u524a\u9664\u3057\u305f\u3089\u30b4\u30df\u7bb1\u306b\u653e\u308a\u8fbc\u3080\u6a5f\u80fd\u3082\u6b32\u3057\u304b\u3063\u305f\u306e\u3067\u3001<a href=\"https:\/\/pypi.python.org\/pypi\/Send2Trash\">Send2Trash<\/a>\u3082\u4f7f\u3063\u305f\u3002<\/p>\n<p>\uff082014\/7\/10\u66f4\u65b0: \u7121\u5bb3\u3060\u3068\u601d\u3063\u3066\u305f\u304a\u307e\u3051\u6a5f\u80fd\u304c\u7a00\u306b\u30a8\u30e9\u30fc\u3092\u767a\u751f\u3055\u305b\u3066\u3044\u305f\u306e\u3067\u524a\u9664\uff09<br \/>\nserver.py:<\/p>\n<pre class=\"brush:python\">from __future__ import division, print_function, absolute_import\r\nimport ConfigParser\r\nimport hashlib\r\nimport argparse\r\nimport sys\r\nimport os\r\nimport re\r\nimport Tkinter\r\nfrom pyftpdlib.authorizers import DummyAuthorizer, AuthenticationFailed\r\nfrom pyftpdlib.handlers import FTPHandler, DTPHandler\r\nfrom pyftpdlib.servers import ThreadedFTPServer\r\nfrom pyftpdlib.filesystems import AbstractedFS, FilesystemError\r\nfrom send2trash import send2trash\r\nfrom wand.image import Image\r\nimport wand.exceptions\r\nfrom StringIO import StringIO\r\n\r\n\r\n\r\nDEFAULT_CONF_FILE = os.path.splitext(__file__)[0] + &#039;.ini&#039;\r\n\r\n\r\n\r\nclass Conf(object):\r\n\r\n    _parser = argparse.ArgumentParser()\r\n    _parser.add_argument(&#039;--hash&#039;, help=&#039;generate hash, copy to clipboard and exit&#039;)\r\n    _parser.add_argument(&#039;--conf&#039;, default=DEFAULT_CONF_FILE, help=&#039;specifies configuration file(.ini)&#039;)\r\n    args = _parser.parse_args()\r\n\r\n    def __init__(self):\r\n        self._load_conf()\r\n\r\n    def _load_conf(self):\r\n        self._conf = ConfigParser.RawConfigParser()\r\n        self._conf.read(self.args.conf)\r\n\r\n    @property\r\n    def conf(self):\r\n        return self._conf\r\n\r\n    @property\r\n    def listen_address(self):\r\n        return self.conf.get(&#039;FTPServer&#039;, &#039;Host&#039;), self.conf.getint(&#039;FTPServer&#039;, &#039;Port&#039;)\r\n\r\n    @property\r\n    def image_target_width(self):\r\n        return self.conf.getint(&#039;ImageFilter&#039;, &#039;TargetWidth&#039;)\r\n\r\n    @property\r\n    def image_target_height(self):\r\n        return self.conf.getint(&#039;ImageFilter&#039;, &#039;TargetHeight&#039;)\r\n\r\n    @property\r\n    def image_shrink_limit(self):\r\n        return self.conf.getint(&#039;ImageFilter&#039;, &#039;ShrinkLimit&#039;)\r\n\r\n    @property\r\n    def image_rotate(self):\r\n        return {&#039;none&#039;: 0, &#039;right&#039;: 90, &#039;left&#039;: 270}[self.conf.get(&#039;ImageFilter&#039;, &#039;Rotate&#039;)]\r\n\r\n    @property\r\n    def image_stretch(self):\r\n        return self.conf.getboolean(&#039;ImageFilter&#039;, &#039;Stretch&#039;)\r\n\r\n    @property\r\n    def image_shrink(self):\r\n        return self.conf.getboolean(&#039;ImageFilter&#039;, &#039;Shrink&#039;)\r\n\r\n    @property\r\n    def image_stretch_filter(self):\r\n        return self.conf.get(&#039;ImageFilter&#039;, &#039;StretchFilter&#039;)\r\n\r\n    @property\r\n    def image_shrink_filter(self):\r\n        return self.conf.get(&#039;ImageFilter&#039;, &#039;ShrinkFilter&#039;)\r\n\r\n    @property\r\n    def image_stretch_filter_blur(self):\r\n        return self.conf.getfloat(&#039;ImageFilter&#039;, &#039;StretchFilterBlur&#039;)\r\n\r\n    @property\r\n    def image_shrink_filter_blur(self):\r\n        return self.conf.getfloat(&#039;ImageFilter&#039;, &#039;ShrinkFilterBlur&#039;)\r\n\r\n    @property\r\n    def image_jpeg_quality(self):\r\n        return self.conf.getint(&#039;ImageFilter&#039;, &#039;JPEGQuality&#039;)\r\n\r\n    @property\r\n    def image_trim(self):\r\n        return self.conf.getboolean(&#039;ImageFilter&#039;, &#039;Trim&#039;)\r\n\r\n    @property\r\n    def image_trim_fuzz(self):\r\n        return self.conf.getfloat(&#039;ImageFilter&#039;, &#039;TrimFuzz&#039;)\r\n\r\n    @property\r\n    def re_target_filename(self):\r\n        return re.compile(self.conf.get(&#039;ImageFilter&#039;, &#039;TargetFileName&#039;), re.I)\r\n\r\n    @property\r\n    def use_trash(self):\r\n        return self.conf.getboolean(&#039;Global&#039;, &#039;UseTrash&#039;)\r\n\r\n    @property\r\n    def users(self):\r\n        return self.conf.items(&#039;Users&#039;)\r\n\r\nconf = Conf()\r\n\r\n\r\n\r\nclass DummyHashAuthorizer(DummyAuthorizer):\r\n\r\n    def validate_authentication(self, username, password, handler):\r\n\r\n        hash = hashlib.sha512(password).hexdigest()\r\n        try:\r\n            if self.user_table[username][&#039;pwd&#039;] != hash:\r\n                raise KeyError\r\n        except KeyError:\r\n            raise AuthenticationFailed\r\n\r\n\r\n\r\nclass ModifiedAbstractedFS(AbstractedFS):\r\n\r\n    def open(self, filename, mode):\r\n\r\n        def call_super():\r\n            return super(ModifiedAbstractedFS, self).open(filename, mode)\r\n\r\n        if not conf.re_target_filename.search(filename):\r\n            return call_super()\r\n\r\n        try:\r\n            with open(filename, mode) as fd, Image(file=fd) as image:\r\n            # Image(filename=filename) doesn&#039;t handle unicode filename\r\n\r\n                if conf.image_trim:\r\n                    bg_color = image[0][0]\r\n                    image.trim(fuzz=conf.image_trim_fuzz)\r\n                    if image.width * image.height == 0:\r\n                        image.blank(1, 1, background=bg_color)\r\n\r\n                target_width = conf.image_target_width\r\n                target_height = conf.image_target_height\r\n                shrink_limit = conf.image_shrink_limit\r\n\r\n                if (image.width - image.height) * (target_width - target_height) &lt; 0:\r\n                    # rotate\r\n                    rotated_target_width = target_height\r\n                    rotated_target_height = target_width\r\n                    degree = conf.image_rotate\r\n                else:\r\n                    # not rotate\r\n                    rotated_target_width = target_width\r\n                    rotated_target_height = target_height\r\n                    degree = 0\r\n\r\n                # shrink first\r\n                w, h = rotated_target_width, rotated_target_height\r\n                if (conf.image_shrink and\r\n                    (image.width &gt; w or image.height &gt; h) and\r\n                    (image.width &gt; shrink_limit and image.height &gt; shrink_limit)\r\n                    ):\r\n                    if image.width \/ image.height &gt; w \/ h:\r\n                        h = image.height * w \/ image.width\r\n                        if h &lt; shrink_limit:\r\n                            w = w * shrink_limit \/ h\r\n                            h = shrink_limit\r\n                    else:\r\n                        w = image.width * h \/ image.height\r\n                        if w &lt; shrink_limit:\r\n                            h = h * shrink_limit \/ w\r\n                            w = shrink_limit\r\n\r\n                    image.resize(width=int(w), height=int(h),\r\n                                 filter=conf.image_shrink_filter,\r\n                                 blur=conf.image_shrink_filter_blur)\r\n\r\n                # rotate\r\n                image.rotate(degree)\r\n\r\n                # stretch last\r\n                w, h = target_width, target_height\r\n                if conf.image_stretch and (image.width &lt; w and image.height &lt; h):\r\n                    if image.width \/ image.height &gt; w \/ h:\r\n                        h = image.height * w \/ image.width\r\n                    else:\r\n                        w = image.width * h \/ image.height\r\n\r\n                    image.resize(width=int(w), height=int(h),\r\n                                 filter=conf.image_stretch_filter,\r\n                                 blur=conf.image_stretch_filter_blur)\r\n\r\n                image.compression_quality = conf.image_jpeg_quality\r\n                blob = image.make_blob(format=&#039;jpeg&#039;)\r\n                io = StringIO(blob)\r\n                io.name = filename\r\n\r\n        except wand.exceptions.WandException:\r\n            return call_super()\r\n\r\n        return io\r\n\r\n    def rmdir(self, path):\r\n        if not conf.use_trash:\r\n            return super(ModifiedAbstractedFS, self).rmdir(path)\r\n        send2trash(path)\r\n\r\n    def remove(self, path):\r\n        if not conf.use_trash:\r\n            return super(ModifiedAbstractedFS, self).remove(path)\r\n        send2trash(path)\r\n\r\n\r\n\r\nclass FilteredImageFile(file):\r\n    pass\r\n\r\n\r\n\r\ndef main():\r\n\r\n    if conf.args.hash:\r\n        hash = hashlib.sha512(conf.args.hash).hexdigest()\r\n        print(hash)\r\n        copy_to_clipboard(hash)\r\n        sys.exit()\r\n\r\n    start_server()\r\n\r\n\r\n\r\ndef start_server():\r\n\r\n    handler = FTPHandler\r\n\r\n    authorizer = DummyHashAuthorizer()\r\n    for username, value in conf.users:\r\n        homedir, perm, hash = value.split(&#039;,&#039;)\r\n        authorizer.add_user(username, hash, homedir, perm=perm)\r\n    handler.authorizer = authorizer\r\n\r\n    fs = ModifiedAbstractedFS\r\n    handler.abstracted_fs = fs\r\n\r\n    server = ThreadedFTPServer(conf.listen_address, handler)\r\n\r\n    server.serve_forever()\r\n\r\n\r\n\r\ndef copy_to_clipboard(value):\r\n    Tkinter.Text().clipboard_clear()\r\n    Tkinter.Text().clipboard_append(value)\r\n\r\n\r\n\r\nif __name__ == &#039;__main__&#039;:\r\n    main()<\/pre>\n<p>server.ini<\/p>\n<pre class=\"brush:plain\">[Global]\r\nUseTrash=true\r\n\r\n[FTPServer]\r\nHost=0.0.0.0\r\nPort=21\r\n\r\n\r\n\r\n[ImageFilter]\r\n\r\nTargetFileName=\\.(jpg|png|gif|bmp)$\r\nJPEGQuality=90\r\nRotate=right\r\n; left\/right\/none\r\n\r\nTargetWidth=1200\r\nTargetHeight=1776\r\nShrinkLimit=800\r\n\r\n; Stretch\/Shrink\r\n;   Filter: http:\/\/docs.wand-py.org\/en\/0.3.5\/wand\/image.html#wand.image.FILTER_TYPES\r\n;     Recommended Filters:\r\n;       &quot;undefined&quot;, &quot;mitchell&quot;, &quot;lagrange&quot;, &quot;lanczos&quot;, &quot;lanczossharp&quot;, &quot;lanczos2&quot;, &quot;lanczos2sharp&quot;\r\n;   FilterBlur:\r\n;       &gt; 1 is blurry, &lt; 1 is sharp\r\nStretch=true\r\nStretchFilter=mitchell\r\nStretchFilterBlur=0.8\r\nShrink=true\r\nShrinkFilter=lanczossharp\r\nShrinkFilterBlur=0.8\r\n\r\n; Trim Edges\r\n;   TrimFuzz: how much tolerance is acceptable to consider two colors as the same\r\nTrim=true\r\nTrimFuzz=1\r\n\r\n\r\n\r\n[Users]\r\n;username=homedir,permissions,password_hash\r\n;   permissions: https:\/\/code.google.com\/p\/pyftpdlib\/wiki\/Tutorial#2.2_-_Users\r\n;     &quot;e&quot; = change directory (CWD, CDUP commands)\r\n;     &quot;l&quot; = list files (LIST, NLST, STAT, MLSD, MLST, SIZE commands)\r\n;     &quot;r&quot; = retrieve file from the server (RETR command)\r\n;     &quot;a&quot; = append data to an existing file (APPE command)\r\n;     &quot;d&quot; = delete file or directory (DELE, RMD commands)\r\n;     &quot;f&quot; = rename file or directory (RNFR, RNTO commands)\r\n;     &quot;m&quot; = create directory (MKD command)\r\n;     &quot;w&quot; = store a file to the server (STOR, STOU commands)\r\n;     &quot;M&quot; = change mode\/permission (SITE CHMOD command)\r\n;   password_hash:\r\n;     generate with &#039;--hash&#039; option and paste it(copied to clipboard automatically)\r\nreader=D:\\foo\\bar,elr,ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413\r\nuser=D:\\foo\\bar,elrdfmM,b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86\r\n<\/pre>\n<p>\u3000\u3053\u3093\u306a\u611f\u3058\u3067\u3002\u306a\u304b\u306a\u304b\u306e\u3084\u3063\u3064\u3051\u611f\u3002\u3064\u30fc\u304b\u3053\u308c\u3060\u3051\u3067\u5909\u614bFTP\u30b5\u30fc\u30d0\u304c\u52d5\u3044\u3061\u3083\u3046\u3093\u3060\u3082\u3093\u306a\u30fc\u3002<br \/>\n\u3000\u3053\u3046\u3044\u3046\u306e\u304c\u6b32\u3057\u3044\u4eba\u306b\u306f\u975e\u5e38\u306b\u4fbf\u5229\u306a\u6c17\u304c\u3059\u308b\u3093\u3060\u3051\u3069\u3001\u4eba\u306b\u4f7f\u3063\u3066\u3082\u3089\u3046\u6c17\u306e\u7121\u3055\u3059\u304e\u308b\u8a18\u4e8b\u3067\u3042\u308b\u3002\u8aac\u660e\u3081\u3093\u3069\u304f\u3066\u3002\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u306b<code>-h<\/code>\u4ed8\u3051\u3066\u8d77\u52d5\u3059\u308c\u3070\u3001\u3042\u3068\u306f\u52d8\u3067\u4f55\u3068\u304b\u2026\u3001\u306a\u3089\u306a\u3044\u304b\u306a\u3042\u3002\u8ab0\u304b\u3082\u3063\u3068\u666e\u901a\u306b\u6271\u3044\u3084\u3059\u3044\u30bd\u30d5\u30c8\u3068\u3057\u3066\u4f5c\u308b\u4eba\u3044\u306a\u3044\u3060\u308d\u3046\u304b\u3002\u65e2\u306b\u3042\u3063\u305f\u3089\u3001\u307e\u305f\u306f\u4f5c\u3063\u305f\u3089\u6559\u3048\u3066\u304f\u3060\u3055\u3044\u662f\u975e\u3002\u3053\u3093\u306a\u3082\u3093\u6368\u3066\u3066\u305d\u3063\u3061\u4f7f\u3044\u307e\u3059\u3057\u3002<br \/>\n\u3000\u30b5\u30f3\u30d7\u30eb\u304c\u30d5\u30a1\u30a4\u30eb\u66f8\u304d\u8fbc\u307f\u3060\u3051\u7981\u6b62\u3057\u3066\u308b\u306e\u306f\u3001\u4f8b\u3048\u3070\u30d5\u30a1\u30a4\u30eb\u30b3\u30d4\u30fc\u3092\u3057\u3088\u3046\u3068\u3059\u308b\u3068\u30d5\u30a3\u30eb\u30bf\u6e08\u307f\u753b\u50cf\u3092\u30b3\u30d4\u30fc\u3057\u3061\u3083\u3046\u3053\u3068\u306b\u306a\u308b\u3093\u3067\u3001\u3053\u306e\u30b5\u30fc\u30d0\u306e\u52d5\u4f5c\u3092\u8003\u3048\u308b\u3068\u5371\u967a\u3060\u306a\u3001\u3068\u3002\u30b3\u30d4\u30fc\u3058\u3083\u306a\u304f\u79fb\u52d5\u306a\u3089\u5927\u4e08\u592b\u3060\u3051\u3069\u3002<br \/>\n\u3000\u3042\u3068\u3001\u30b5\u30f3\u30d7\u30eb\u306ereader\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\u306f123456\u3001user\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\u306fpassword\u3067\u3042\u308b\u3002\u6700\u60aa\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u65b0\u65e7\u738b\u8005\u3067\u3042\u308b\u306a\u3002<\/p>\n<p>\u3000\u3067\u3001ES\u30d5\u30a1\u30a4\u30eb\u30a8\u30af\u30b9\u30d7\u30ed\u30fc\u30e9\u30fc\u3067\u30a2\u30af\u30bb\u30b9\u3057\u3066\u307f\u305f\u3093\u3060\u3051\u3069\u3001\u4ee5\u524d\u304b\u3089FTP\u3067\u306e\u753b\u50cf\u30ed\u30fc\u30c9\u306b\u602a\u3057\u3055\u304c\u3042\u3063\u305f\u306e\u304c\u518d\u767a\u3057\u3066\u3001\u3069\u3046\u3082\u767a\u751f\u6761\u4ef6\u304c\u5206\u304b\u3089\u3093\u3057\u666e\u901a\u306eFTP\u9bd6\u3067\u3082\u8d77\u304d\u308b\u3093\u3067\u3001<a href=\"https:\/\/play.google.com\/store\/apps\/details?id=com.rhmsoft.fm&#038;hl=ja\">Rhythm Software\u306eFile Manager<\/a>\u3092\u4f7f\u3063\u3066\u307f\u3066\u3044\u308b\u3068\u3053\u308d\u3002\u3053\u306e\u5909\u614bFTP\u30b5\u30fc\u30d0\u3067\u4f7f\u3046\u4ee5\u5916\u306e\u7528\u9014\u3060\u3068\u5fae\u5999\u3060\u3051\u3069\u3001\u305d\u308c\u306a\u308a\u306b\u306f\u884c\u3051\u308b\u3002ES\u30d5\u30a1\u30a4\u30eb\u30a8\u30af\u30b9\u30d7\u30ed\u30fc\u30e9\u30fc\u3068\u4f75\u7528\u3059\u308b\u304b\u306a\u3002<br \/>\n\u3000Android\u306e\u30d5\u30a1\u30a4\u30eb\u30de\u30cd\u30fc\u30b8\u30e3\u30fc\u3063\u3066\u3069\u3046\u3082\u4e00\u9577\u4e00\u77ed\u306a\u611f\u3058\u306a\u3093\u3067\u3001\u7d50\u69cb\u306a\u30c1\u30e3\u30f3\u30b9\u3060\u3068\u601d\u3046\u3093\u3060\u3051\u3069\u3001\u8ab0\u304b\u5b8c\u74a7\u306a\u5974\u3092\u4f5c\u3063\u3066\u304f\u308c\u3093\u304b\u306a\u30fc\u3002<\/p>\n<p>\u3000\u305b\u3063\u304b\u304f\u306a\u306e\u3067\u3001\u30b3\u30fc\u30c9\u306b\u3064\u3044\u3066\u306e\u8a71\u3082\u66f8\u3044\u3066\u304a\u304f\u3002\u3053\u3053\u306f\u5099\u5fd8\u9332\u3067\u3082\u3042\u308b\u306e\u3067\u3002<\/p>\n<ul>\n<li>ThreadedFTPServer\u3092\u63a1\u7528\u3057\u305f\u306e\u306f\u3001\u4f4e\u901f\u306a\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306b\u8fd1\u3044\u72b6\u614b\u306b\u306a\u3063\u3066\u3044\u305f\u70ba\u3002\u3064\u3063\u3066\u3082I\/O\u3058\u3083\u306a\u304fCPU\u306a\u306e\u3067\u3001Python\u3060\u3068\u30de\u30eb\u30c1\u30b9\u30ec\u30c3\u30c9\u3088\u308a\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30b9\u5411\u3051\u306a\u306e\u3067\u306f\u306a\u3044\u304b\u3001\u3068\u601d\u3063\u305f\u3051\u3069\u3001\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30b9\u7248\u306e\u30af\u30e9\u30b9\u306fWindows\u5bfe\u5fdc\u3067\u306f\u306a\u3044\u3063\u307d\u3044\u306e\u3067\u3002\u30af\u30e9\u30b9\u540d\u3092\u4e00\u7b87\u6240\u66f8\u304d\u63db\u3048\u308b\u3060\u3051\u3067\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30b9\u7248\u306b\u306a\u308b\u3051\u3069\u3002<\/li>\n<li>\u753b\u50cf\u5909\u63db\u306e\u3068\u3053\u308d\u306f\u540c\u3058\u3088\u3046\u306a\u51e6\u7406\u3092\u7e70\u308a\u8fd4\u3057\u3066\u3066\u6c5a\u3044\u3051\u3069\u3001\u3068\u308a\u3042\u3048\u305a\u52d5\u304b\u3059\u3060\u3051\u3067\u75b2\u308c\u305f\u3002\u7dba\u9e97\u306b\u3059\u308b\u306e\u3081\u3093\u3069\u3044\u3002<\/li>\n<li>ConfigParser\u95a2\u9023\u3082\u3082\u3063\u3068\u3059\u3063\u304d\u308a\u3084\u308c\u305d\u3046\u306a\u3002<\/li>\n<li>\u3069\u3046\u305b\u3084\u3063\u3064\u3051\u306a\u3089\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u3092\u308f\u3056\u308f\u3056\u5206\u3051\u306a\u3044\u65b9\u304c\u3059\u3063\u304d\u308a\u3057\u305f\u306e\u306b\u3001\u3068\u4eca\u3067\u306f\u601d\u3046\u3002<del>\u3067\u3082\u307e\u3042\u3001\u3053\u308c\u306e\u304a\u9670\u3067\u3001\u30b5\u30fc\u30d0\u3092\u52d5\u304b\u3057\u305f\u307e\u307e\u5225PC\u304b\u3089\u8a2d\u5b9a\u3060\u3051\u5909\u66f4\u3059\u308b\u3001\u3068\u3044\u3046\u306e\u304c\u7c21\u5358\u306b\u3084\u308c\u308b\u304b\u3089\u3044\u3044\u304b\u3002<\/del>\u2190\u30a8\u30f3\u30d0\u30b0\u3057\u3066\u305f\u306e\u3067\u6a5f\u80fd\u524a\u9664<\/li>\n<\/ul>\n<p>\u3000\u6539\u5584\u6848\u3068\u304b\u306e\u30c4\u30c3\u30b3\u30df\u306f\u6b53\u8fce\u3067\u3042\u308b\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u3000Nexus 7\u3067\u3001\u96fb\u5b50\u5316\u3057\u305f\u6f2b\u753b\u3068\u304b\u8aad\u3080\u306e\u306b\u3055\u30fc\u3002\u3042\u3093\u307e\u308a\u5927\u304d\u3044\u3068\u3001\u8ee2\u9001\u901f\u5ea6\u7684\u306b\u7cde\u91cd\u304f\u306a\u308b\u3058\u3083\u306a\u3044\u3067\u3059\u304b\u3002 \u3000\u3067\u3082\u3001\u305d\u308c\u3092\u57fa\u6e96\u306b\u753b\u8cea\u843d\u3068\u3057\u3066\u4fdd\u5b58\u3059\u308b\u306e\u3082\u3042\u308c\u3060\u3057\u3001\u308f\u3056\u308f\u3056\u4f4e\u753b\u8cea\u7248\u3068\u304b\u3092\u5206\u3051\u3066\u7f6e\u3044\u3066\u304a\u304f\u306e\u3082\u4f55\u3068\u306a\u304f\u30a2\u30ec\u3067 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/posts\/6021"}],"collection":[{"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/comments?post=6021"}],"version-history":[{"count":19,"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/posts\/6021\/revisions"}],"predecessor-version":[{"id":6306,"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/posts\/6021\/revisions\/6306"}],"wp:attachment":[{"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/media?parent=6021"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/categories?post=6021"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/mk.miko.jp\/blog\/wp-json\/wp\/v2\/tags?post=6021"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}